Translate

недеља, 23. октобар 2016.

FTP

Vec sam postavio skriptu za Upload na FTP sajt a evo sad i dodatne dve funkcije koje listaju fajlove na FTP serveru i brisu

function Get-FtpDir {
param($url, $credentials)
begin{

  $request = [Net.FtpWebRequest]::Create($url)
  if ($credentials) { $request.Credentials = $credentials }
  $request.Method = [System.Net.WebRequestMethods+FTP]::ListDirectory
  (New-Object IO.StreamReader $request.GetResponse().GetResponseStream()).ReadToEnd() -split "`r`n"
}}


function Remove-FtpFile{
param ($url, $credentials)
begin {
  $request = [System.Net.FtpWebRequest]::create($url)
  if ($credentials) { $request.Credentials =  $credentials }
  $request.Method = [System.Net.WebRequestMethods+Ftp]::DeleteFile
  [Void] $request.GetResponse()
}}


Primeri za koriscenje ovih funkcija su:

Get-FtpDir -url 'someftpaddress' -credentials get-credentials
Remove-FtpFile ("$ftpPath/FileName.txt") -credentials get-credentials


 

понедељак, 12. септембар 2016.

Provera korisnika u lokalnoj grupi

Evo jos jedna skripta, tj funkcija, na lokalnom ili udaljenom racunaru proverava sve korisnike u odredjenoj lokalnoj grupi i pravi listu.

1. citajuci ADSI proverava sve korisnike u grupi
2. za svakog lokalnog korisnika proverava opet ADSI i cita vrednosti
3. za svakog domenskog korisnika proverava u domenu vrednosti


function Get-GroupUsers {

    param(
    [Parameter(Mandatory=$true,valuefrompipeline=$true)]
    [string]$Compname, [string]$GroupName)
   
    begin {

foreach($computer in $Compname){



[ADSI]$group = "WinNT://$computer/$GroupName,group"
$members = $group.invoke("Members")
$found = ($members | measure).count

      if ($found -gt 0 ) {
        $members | foreach {
       
            $Hash = [ordered]@{Computername = $computer.toUpper()}
            $hash.Add("Name",$_[0].GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null))

            $ADSPath = $_[0].GetType().InvokeMember("ADSPath", 'GetProperty', $null, $_, $null)
            $hash.Add("ADSPath",$ADSPath)

            $hash.Add("Class",$_[0].GetType().InvokeMember("Class", 'GetProperty', $null, $_, $null)) 
   
            $hash.Add("Domain",$ADSPath.Split("/")[2])

            if ($ADSPath -match "/$computer/") {
                $local = $True
                }
            else {
                $local = $False
                }
            $hash.Add("IsLocal",$local)
$user = New-Object -TypeName PSObject -Property $hash
If($user.IsLocal -eq 'True'){
#################Local Users
$lusr = $user.name
$AllLocalAccounts = Get-WmiObject -Class Win32_UserAccount -ComputerName $computer -Namespace "root\cimv2" -filter "LocalAccount=True AND Name='$lusr'"
Foreach($LocalAccount in $AllLocalAccounts)
    {
[ADSI]$computerl="WinNT://$computer"
$LastLogin = $computerl.psbase.children | where {$_.name -eq "$lusr"} | select @{name="LastLogin";Expression={$_.psbase.properties.lastLogin}}
        $Object = New-Object -TypeName PSObject
        $Object|Add-Member -MemberType NoteProperty -Name "Computer Name" -Value $computer
        $Object|Add-Member -MemberType NoteProperty -Name "Name" -Value $LocalAccount.Name
        $Object|Add-Member -MemberType NoteProperty -Name "Full Name" -Value $LocalAccount.FullName
        $Object|Add-Member -MemberType NoteProperty -Name "Caption" -Value $LocalAccount.Caption
          $Object|Add-Member -MemberType NoteProperty -Name "Disabled" -Value $LocalAccount.Disabled
          $Object|Add-Member -MemberType NoteProperty -Name "Status" -Value $LocalAccount.Status
          $Object|Add-Member -MemberType NoteProperty -Name "LockOut" -Value $LocalAccount.LockOut
        $Object|Add-Member -MemberType NoteProperty -Name "Password Changeable" -Value $LocalAccount.PasswordChangeable
        $Object|Add-Member -MemberType NoteProperty -Name "Password Expires" -Value $LocalAccount.PasswordExpires
        $Object|Add-Member -MemberType NoteProperty -Name "Password Required" -Value $LocalAccount.PasswordRequired
        $Object|Add-Member -MemberType NoteProperty -Name "SID" -Value $LocalAccount.SID
        $Object|Add-Member -MemberType NoteProperty -Name "SID Type" -Value $LocalAccount.SIDType
        $Object|Add-Member -MemberType NoteProperty -Name "Account Type" -Value $LocalAccount.AccountType
        $Object|Add-Member -MemberType NoteProperty -Name "Domain" -Value $LocalAccount.Domain
        $Object|Add-Member -MemberType NoteProperty -Name "Description" -Value $LocalAccount.Description
        $Object|Add-Member -MemberType NoteProperty -Name "Type" -Value 'Local User'
        $Object|Add-Member -MemberType NoteProperty -Name "Last Login" -Value $LastLogin.lastlogin
        $Object
}

}else{
#################Domain Users

$lusr = $user.Name
$domainUser = Get-ADUser $lusr    -ErrorAction SilentlyContinue
$userProp = Get-ADUser $lusr -Properties * -ErrorAction SilentlyContinue
$Object1 = New-Object -TypeName PSObject
if(($domainUser.Enabled) -eq 'true'){$dis = 'False'}else{$dis = 'True'}
if(($userProp.CannotChangePassword) -eq 'True'){$changepass = 'False'}else{$changepass = 'True'}
if(($userProp.PasswordNeverExpires) -eq 'True'){$pasexp = 'False'}else{$pasexp = 'True'}
if(($userProp.PasswordNotRequired) -eq 'True'){$pasreq = 'False'}else{$pasreq = 'True'}
if(($userProp.isDeleted) -eq 'True'){$stat = 'Deleted'}else{$stat = 'OK'}
if(($userProp.Description) -eq 'True'){$stat = 'Deleted'}else{$stat = 'OK'}
        $Object1|Add-Member -MemberType NoteProperty -Name "Computer Name" -Value $computer
        $Object1|Add-Member -MemberType NoteProperty -Name "Name" -Value $domainUser.Name
        $Object1|Add-Member -MemberType NoteProperty -Name "Full Name" -Value $domainUser.UserPrincipalName
        $Object1|Add-Member -MemberType NoteProperty -Name "Caption" -Value $domainUser.SamAccountName
          $Object1|Add-Member -MemberType NoteProperty -Name "Disabled" -Value $dis
          $Object1|Add-Member -MemberType NoteProperty -Name "Status" -Value $stat
          $Object1|Add-Member -MemberType NoteProperty -Name "LockOut" -Value $userProp.LockedOut
        $Object1|Add-Member -MemberType NoteProperty -Name "Password Changeable" -Value $changepass
        $Object1|Add-Member -MemberType NoteProperty -Name "Password Expires" -Value $pasexp
        $Object1|Add-Member -MemberType NoteProperty -Name "Password Required" -Value $pasreq
        $Object1|Add-Member -MemberType NoteProperty -Name "SID" -Value $domainUser.SID.Value
        $Object1|Add-Member -MemberType NoteProperty -Name "SID Type" -Value 'No Data'
        $Object1|Add-Member -MemberType NoteProperty -Name "Account Type" -Value $userProp.sAMAccountType
        $Object1|Add-Member -MemberType NoteProperty -Name "Domain" -Value (Get-ADDomain).forest
        $Object1|Add-Member -MemberType NoteProperty -Name "Description" -Value $userProp.Description
        $Object1|Add-Member -MemberType NoteProperty -Name "Type" -Value 'Domain User'
        $Object1
        }



         }

}
else{}

}}}


parametri funkcije su naziv racunara i naziv lokalne grupe.

Primer:
Get-GroupUsers -Compname $env:COMPUTERNAME -GroupName 'administrators'

петак, 29. јануар 2016.

Public ip skripta

Ukoliko imate klijenta ili održavate udaljenu lokaciju koja nema statičku ip adresu, ili jednostavno imate potrebu da uvek znate spoljnu adresu određene mreže, u nastavku se nalazi jednostavna powershell skripta koja će vas obavestiti svaki put kada dodje do promene.

Pošto na nivou operativnog sitema račnara koji se nalazi u određenom LAN-u ne postoji način da se dođe do javne ip adrese te mreže, ova skripta poziva WebAPI (https://api.ipify.org) koji vraća ip adresu sa kojeg je HTTP_Request stigao (javnu ip adresu vaše mreže ukoliko se ne nalazite iza proksija) a zatim upoređuje sa lokalno sačuvanom adresom iz prethodne provere. Ukoliko adrese nisu iste, poslaće email obaveštenje sa detaljima o novoj ip adresi.

#Putanja do fajla u kom se čuva ip adresa iz poslednje provere
$filePath = "ip.txt" 
$Old_IP = ''

$From = "sender@gmail.com"
$To = "receiver@gmail.com"
$Subject = "Ip changed"
$SMTPServer = "smtp.gmail.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587) 
$SMTPClient.EnableSsl = $true 
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("email username", "email password"); 

#blok koji proverava da li postoji fajl ip.txt na odredjenoj lokaciji
 ukoliko nema kreira novi prazan fajl (da bi i prilikom prvog pokretanja skripte poslao obaveštenje) a ukoliko postoji uzima njegov sadržaj (ip iz poslednje provere)
if(!(Test-Path -Path $filePath))
  {
   new-item -Path $filePath –itemtype file
  }
else
  {
$Old_IP = Get-Content $filePath
  }
#Pozivanje WebApi-ja koji vraća trenutnu javnu ip adresu
$url = 'https://api.ipify.org?format=json'
$Http_request =  Invoke-RestMethod -Uri $url
$Curent_IP = $Http_request.ip 

#Proverava adresu iz fajla sa preuzetom adresom
if($Old_IP -ne $Curent_IP){
$Curent_IP | Out-File ip.txt
$SMTPMessage = New-Object System.Net.Mail.MailMessage($From,$To,$Subject, $Curent_IP)
$SMTPClient.Send($SMTPMessage)
}


четвртак, 28. јануар 2016.

skripta za monitoring web resursa

Dostupnost Web stranice, WebAPI-ja/Servisa ili bilo kog drugog resursa  koji hostujete na Webu-u je izuzetno kritična i važna stavka u administraciji sistema. Zbog Marfijevog zakona, u jednom trenutku će se desiti da Web resursi jednostavno postanu nedostupni iz nepoznatog razloga, a vi nećete ni biti svesni dok telefoni ne počnu da zvone.

U nastavku se nalazi primer skripte koja služi kao monitoring, log i alert sistem koja može da prati dostupnost i vreme odziva bilo kog resursa na webu, šalje email obaveštenje o statusu i upisuje log u bazu. U mom slučaju i ovom primeru skripta nadgleda Web Servise

#U mom slučaju pristup bilo kom Web servisu zahteva Log-In sekvencu koja vraća token za autentifikaciju tako da sam ja na samom početku skripte pozvao LoginServis sa mojim kredencijalima pomoću cmdleta Invoke-RestMethod koji automatski parsira JSON formatirane stringove i njihove vrednosti pakuje u ps objekte

$Login = Invoke-RestMethod -Uri http://mojLoginUrlServis?Username=mojusername"&"Password=mojpass

#Moj username i accsess Token za pozivanje drugih Servisa dobijeni Login sekvencom
$Token = $Login.Token
$Username = $Login.Username

#Dodatni parametri koji zahtevaju WebServisi
$Params = @{username = $Username;token=$Token;page = 0;Delatnost='ninja';Grad="Beograd"}

$datetime = ' '

#Podešavanja email klijenta
$From = "sender@gmail.com" 
$To = "receiver@gmail.com"
$Subject = "Web API is offline"
$SMTPServer = "smtp.gmail.com"
$SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587) 
$SMTPClient.EnableSsl = $true 
$SMTPClient.Credentials = New-Object System.Net.NetworkCredential("email-username", "email-password");
$Body = ""
$SendMail = 0

$HTTP_Status = ' '

#.txt fajl u kom se nalaze putanje do resursa koji se nadgledaju 
$content = Get-Content -Path "url.txt"

$conn = New-Object System.Data.SqlClient.SqlConnection
#SQL connecton string 
$conn.ConnectionString = "Data Source=xxx.xxx.xxx.xxx; Initial Catalog = DbName; User ID = DbUser; Password = DbPassword"

$conn.open()

foreach ($url in $content) {
    $datetime = Get-Date 
#Merenje vremena odziva Servisa
    $time =  Measure-Command -Expression {
    try { 

       $HTTP_Request =  Invoke-WebRequest -Uri $url -Body $params -ErrorAction SilentlyContinue
       $HTTP_Status = $HTTP_Request.StatusCode

#U ps-u ako HTTPREQUEST vrati rezultat različit od 200 (200 = Servis je dostupan), rezultat se tretira kao exception i skripta puca ukoliko se na cmdletu koji izaziva grešku ne postavi -ErrorAction SilentlyContinue
    
                 $online = 1       
    }
    catch {

#Blok koji hendluje grešku i kreira tekst email obaveštenja a takodje uzima i ResponseCode koji pomaže prilikom dijagnostikovanja greške

    $HTTP_Status = $_.Exception.Response.StatusCode.Value__
    $Body = $Body + "Webservice: " + $url + " is offline Time:"+ $datetime + " Reason: " +  $_.Exception.Response.StatusCode.Value__ + "r`n"                
                    $online = 0     
         }
     }

 #Upisivanje log-a u Bazu
    $response_time = $time.TotalSeconds
    $cmd = New-Object System.Data.SqlClient.SqlCommand
    $cmd.connection = $conn
    $cmd.CommandText = "INSERT INTO Monitoring (Url,Online,Response_time,Date,Response_code) VALUES('{0}','{1}','{2}','{3}','{4}')" -f $url,$online,$response_time,$datetime,$HTTP_Status
    $cmd.ExecuteNonQueryAsync() | Out-Null 
}
  if($SendMail -eq 1){
 #Slanje email notifikacije
         $SMTPMessage = New-Object System.Net.Mail.MailMessage($From,$To,$Subject,$Body)
         $SMTPClient.Send($SMTPMessage)

        }
  $conn.Close()



субота, 23. јануар 2016.

FTP servis u PowerShell-u

Evo neceg sto sam nedavno pisao.

Rec je o powershell skripti koja nadgleda odredjeni folder i cim se pojavi *.xml fajl uradi upload na ftp server.

while($true){
$configfilePath = 'E:\ftpxml\config.xml'
$settings = [xml](get-content $configfilePath)
$podesavanja = $settings.RootElement.ftp

###Log file
$LogFileName = (get-date).ToString("yyyyMMdd")
$logFile = "E:\ftpxml\Log\ftp_upload_$LogFileName.log"

$ftpaddress = $podesavanja.ftpaddress
$ftpuser = $podesavanja.username
$ftppass = $podesavanja.password
$copyfrom = $podesavanja.FolderA
$copytoo = $podesavanja.FolderB
$sleep = $podesavanja.waittime
$ftptime = $podesavanja.ftptime

$ftp = "ftp://$ftpaddress/"
$webclient = New-Object System.Net.WebClient
$webclient.Credentials = New-Object System.Net.NetworkCredential($ftpuser,$ftppass) 

foreach($item in (dir $copyfrom -Include *.xml)){
    Start-Sleep -Seconds $ftptime
    $uri = New-Object System.Uri($ftp+$item.Name)
    $webclient.UploadFile($uri, $item.FullName)
    if($?){
    $uploadtime = Get-Date
    Add-Content $logFile "$uploadtime File $item Uploaded"
    Copy-Item $item.FullName $copytoo
    if((Test-Path "$copytoo\$item") -eq 'True'){
    $copytime = Get-Date
    Add-Content $logFile "$copytime File $item Copyed"
    Remove-Item $item.FullName
    $removetime = Get-Date
    Add-Content $logFile "$removetime File $item Deleted from Source Folder"
    }
    }
 }
 Start-Sleep -Seconds $sleep
 }



 Sva podesavanja su u *.xml fajlu koji izgleda:

<?xml version="1.0"?>
<?xml-stylesheet type='text/xsl' href='style.xsl'?>
<RootElement>
    <ftp>
        <ftpaddress>ftpServerAdresa:21</ftpaddress>
        <username>ftpuser</username>
        <password>ftppassword</password>
        <FolderA>C:\test1</FolderA>
        <FolderB>C:\test2</FolderB>
        <waittime>60</waittime>
        <ftptime>60</ftptime>
    </ftp>
</RootElement>


Tako da skripta cita sva podesavanja sa xml fajla, nadgleda FolderA i cim se pojavi *.xml fajl uploaduje na ftp server i zatim kopira fajl u FolderB

u 22. redu skripte se nalazi deo
foreach($item in (dir $copyfrom -Include *.xml)){

gde mozete da izmenite da gleda bilo koju drugu ekstenziju ili ukoliko se ukloni -include *.xml gleda sve fajlove u FolderA.

Sve sto se desi, loguje se u folderu koji je definisan u 8. redu
$logFile = "E:\ftpxml\Log\ftp_upload_$LogFileName.log"
 tako da bi vam skripta radila vi treba da promenite putanju LOG fajla kao i putanju config fajla u 2. redu.

Ja sam u svakom slucaju skriptu bildovao kao Windows Servis uz pomoc PowerGUI-a

субота, 16. јануар 2016.

Skripa za restart routera Telnet i SSH

Jeftiniji routeri sa kojima sam se susretao su imali tendenciju da prestanu sa radom i bilo ih je potrebno restartovati. Problem nastaje kad imate veliki broj uređaja na različitim lokacijama koje su kilometrima udaljene od vaše. Procedura kod ovakvog slučaja je sledeća - zove vas nezadovoljan korisnik kome "ništa ne radi" ili je računar "crkao" jer nema google-a. Sad je došao red na deo kad vi pokušate da mu dajete uputstva preko telefona a on vidi samo "mnoštvo žica i kutija sa trepćućim svetlima". Sa istim problemima sam se i ja susretao i postoji rešenje!
Da bi se implementiralo rešenje potreban je drugačiji pristup routeru od onog preko web UI a to se može postići preko servisa kao što su Telnet i SSH.
Nekad routeri mogu da koriste samo Telnet ili samo SSH i iz tog razloga sam napisao skripte za oba servisa.


Skripta za restart routera preko Telnet-a.

Postoji nekoliko preduslova da bi ova skripta mogla da radi ali se ispunjavanjem istih ne bih bavio u ovom tekstu.
1. Telnet mora biti instaliran na računaru sa kog se skripa pokreće.
2. Na routeru se mora dozvoliti pristup preko Telnet-a.

Otvorite nov txt u notepadu i u njega upišete sledeće komande:

Option explicit
Dim oShell
set oShell= Wscript.CreateObject("WScript.Shell")
oShell.Run "telnet"                                                                   
WScript.Sleep 3000                                                           
oShell.Sendkeys "192.168.0.1~"                                           
WScript.Sleep 3000                                                                
oShell.Sendkeys "username~"
WScript.Sleep 3000
oShell.Sendkeys "password~"
WScript.Sleep 3000
oShell.Sendkeys "system reboot~"
WScript.Sleep 3000
oShell.Sendkeys "~"
Wscript.Quit

Napomena: kod nekih routera, komanda za restartovanje je reboot a kod nekih system reboot.

Dokument je potrebno sačuvati kao .vbs (visal basic script).
Ukoliko vam skripa radi ali ne može da dobije vezu ka routeru, proverite port koji router koristi za ovaj protokol i promenite port na 22 ili 23.

Skripta za restart routera preko SSH.

Ovaj način je malo komplikovaniji pošto Windows za razliku od Linuxa, nema ugrađen servis za SSH kao što ima za Telnet i potrebno ga je instalirati.
Softver za SSH pristup po mom izboru je Putty. Preuzmite ga Ovde.

Potrebno je kreirati dva nova txt fajla. U prvi upišite sledeće:

start lokacija\putty.exe -ssh adresa routera -l username -pw password -m lokacija\imefajla.txt

Fajl sačuvajte pod nastavkom .bat.

U drugi .txt upišite "reboot" i sačuvajte ga.

Primer:

start D:\putty.exe -ssh 192.168.0.1 -l admin -pw admin -m D:\komanda.txt

Router bez Telneta ili SSH

Ukoliko imate router čiji vam firmware ne dozvoljava pristup preko ovih servisa, možete postaviti nov firmware na router (npr. OpenWrt). U ovom slučaju bi bilo poželjno da se konsultujete sa nekim ko je već radio tzv. flashovanje routera.