TechOnTip Weblog

Run book for Technocrats

Powershell Tip: Date Formatting ISO 8601

Posted by Brajesh Panda on October 10, 2016

Convert current date to ISO 8601 format (like 2016-10-10T16:35:48.477):  Get-Date -format s

Convert ISO 8601 format to Powershell’s date time format:  [datetime]::Parse($date). where $date has the ISO 8601 input.  Here is the reference to one of my old post which converts user input to powershell’s DateTime format.

Here are two other interesting articles.



Posted in Powershell | Leave a Comment »

Powershell: Use Convert-String to parse email addresses

Posted by Brajesh Panda on September 13, 2016

Feed: GoateePFE
Posted on: Tuesday, September 13, 2016 8:14 AM
Author: Ashley McGlone
Subject: Use the new PowerShell cmdlet Convert-String to parse email addresses

Tired of hacking away at RegEx and string functions to parse text? This post is for you!

New toys

PowerShell 5.x includes a number of new features. One of the lesser-known and incredibly powerful is the string conversion set of cmdlets. The names are very similar. Check out how Get-Help describes them:

PS C:\> Get-Help Convert*-String | Format-Table Name,Synopsis -AutoSize
Name Synopsis

Posted in Mix & Match | Leave a Comment »

Powershell – Change CSV Headers

Posted by Brajesh Panda on September 2, 2016

CSV file has below headers and I want to change them by appending 1 to each one of them.

Name, samaccountname, ComputerEnabled, User, UserEnable, UserOffice, UserDepartment

$headers = "name1","samaccountname1","ComputerEnabled1","User1","UserEnabled1","UserOffice1","UserDepartment1"

Get-Content C:\AdobeStandard.csv -Encoding Default | Select-Object -Skip 1 | ConvertFrom-CSV -UseCulture -Header $headers

Posted in Mix & Match | Leave a Comment »

Azure Backup Reporting

Posted by Brajesh Panda on August 10, 2016

In the absence of any good reporting mechanism for Azure Backup Agents, I have created this one for my work. We just start backing up some branch file servers to Azure and that number will go up. So for now it is okay, will see what improvements I can do to this. If you have an idea please suggest or implement and send me a copy😉

######################### Microsoft Azure Backup AReporting###########################
##### Script needs PSRemoting and Azure Backup Powershell Module (MSOnlineBackup)#####

# Individual server array
# $AzureBackupAgents = 'serverA', 'serverB'

# Get server names from a AD security group.
$AzureBackupAgents = Get-ADGroupMember Azure_Backup_Reporting | select Name

# Create an empty array
$Consolidated = @()

# Retrieve data for each Azure Backup Agent
foreach($Node in $AzureBackupAgents)
 # Agent as AD Computer name attribute
 $Agent = $Node.Name
 # Select last 10 Azure Backup Jobs from the remote agent thru psremoting
 $AgentReports = Invoke-Command -ComputerName $Agent -ScriptBlock `
 # Find time (ticks) offset between Local and UTC for UTC to local time conversion
 $Date = Get-Date;
 $UTC = $Date.ToUniversalTime();
 $OffSet = $Date – $UTC;
 # Find last 10 job details
 Get-OBJob -Previous 10 | select Jobtype, `
 @{Name="StartTime"; Expression ={($_.JobStatus.StartTime).AddTicks($OffSet.Ticks)}}, `
 @{Name="EndTime"; Expression ={($_.JobStatus.EndTime).AddTicks($OffSet.Ticks)}}, `
 @{Name="JobState"; Expression ={$_.JobStatus.JobState}}, `
 @{Name="BackupSizeInGB"; Expression ={($_.JobStatus.DatasourceStatus.ByteProgress.Progress / 1GB).ToString('#.##')}}, `
 @{Name="TotalSizeInGB"; Expression ={($_.JobStatus.DatasourceStatus.ByteProgress.Total / 1GB).ToString('#.##')}}, `
 @{Name="FailedFileLog"; Expression ={$_.JobStatus.FailedFileLog}}

 # Filter & Select last 24 hours logs
 $Day = (Get-Date).AddHours(-24)
 $Filtered = $AgentReports | where{$_.StartTime -gt $Day} | Sort StartTime -Descending | Select @{Name="AgentName"; Expression ={$_.PSComputerName}}, JobType, StartTime, Endtime, JobState, BackupSizeInGB, TotalSizeInGB, FailedFileLog
 ($Filtered | Measure-Object).Count
 $Consolidated += $Filtered

# Add new properties to the array to capture Recovery Point Details
$Consolidated | Add-Member -MemberType NoteProperty TotalRPs ''
$Consolidated | Add-Member -MemberType NoteProperty OldestRP ''
$Consolidated | Add-Member -MemberType NoteProperty LatestRP ''

# retrieve Recovery Port details from each agent.
foreach($Node in $Consolidated)
 $RecoveryPoints = Invoke-Command -ComputerName $Node.AgentName -ScriptBlock `
 Get-OBAllRecoveryPoints | Sort-Object backuptime
 $Node.TotalRPs = ($RecoveryPoints | Measure-Object).Count
 $Node.OldestRP = $RecoveryPoints[0].BackupTime
 $Node.LatestRP = $RecoveryPoints[-1].BackupTime

# Email the consolidated report with HTML formating

 # HTML Formating; Styles to be placed in the header
 $a = "<style>"
 $a = $a + "BODY{font-family: Verdana, Arial, Helvetica, sans-serif;font-size:10;font-color: #000000}"
 $a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
 $a = $a + "TH{border-width: 1px;padding: 0px;border-style: solid;border-color: black;background-color: #E8E8E8}"
 $a = $a + "TD{border-width: 1px;padding: 0px;border-style: solid;border-color: black}"
 $a = $a + "</style>"

 # Mail Alert
 $MailSubject = "Consolidated Azure Backup Report for Last 24hrs"
 $MailBody = $Consolidated | Select AgentName,JobType,StartTime,EndTime,JobState,BackupSizeInGB,TotalSizeInGB,TotalRPs,OldestRP,LatestRP,FailedFileLog | ConvertTo-Html -Head $a

 # Mailout the Report
 $smtpServer = "smtp.local"
 $msg = new-object Net.Mail.MailMessage
 $smtp = new-object Net.Mail.SmtpClient($smtpServer)

 $msg.From = "AzureBackupAdmin@domain.local"
 $msg.Subject = $MailSubject
 $msg.Body = $MailBody

Email Output looks like below;

azuer backup

Posted in Azure, Powershell | Leave a Comment »

Upgrade Windows 10 Pro to Enterprise

Posted by Brajesh Panda on August 9, 2016

From an elevated command prompt run changepk.exe and supply the MAK activation key. It will take 15-20mins to finish the upgrade & couple of times auto reboot to get converted to enterprise edition.

Posted in Mix & Match | Leave a Comment »


Posted by Brajesh Panda on July 26, 2016

Here is a nice article which describes Certificate Revocation List vs Online Certificate Status Protocol.

Credit goes to Mr. R DONATO

Ricky Donato is the Founder and Chief Editor of He currently works as a Principal Network Security Engineer and has a keen interest in automation and the cloud.

You can find Ricky on Twitter @f3lix001


Certificate Revocation is used within PKI (Public Key Infrastructure) to instruct the client that the certificate can no longer be trusted. This is required in scenarios where the private key has been compromised.


Prior to a CA issuing a certificate to a company the CA performs a level of validation on the authenticity that the company are who they say they are. There are 3 levels of validation ranging from DV (lowest) level all the way up to EV (highest).

Domain Validation (DV) – This type of certificate is the least expensive of the 3. It requires a basic form of domain validation to be performed. Validation is performed by email.
Organization Validation (OV) – When obtaining an OV certificate the company name is checked against a company register, i.e Chamber of Commerce.
Extended Validation (EV) – Like OV a company search is performed, however the physical location is also checked and the contact who requested the certificate is also validated.


CRL (Certificate Revocation) was first released to provide the CA with the ability to revoke certificates., however due to limitations with this method it was superseded by OCSP.

Below details each of these methods along with their main advantages and disadvantages.


CRL (Certificate Revocation Lists) contains a list of certificate serial numbers that have been revoked by the CA. The client then checks the serial number from the certificate against the serial numbers within the list (sample shown below).

Revoked Certificates:
Serial Number: 2572757EAAF2BEC5980067579A0A7705
Revocation Date: May 1 19:56:10 2013 GMT
Serial Number: 776DDD15D25C713616E7D4A8EACFB4A1
Revocation Date: May 24 13:03:16 2013 GMT

To instruct the client on where to find the CRL, a CRL distribution point is embedded within each certificate (shown below),

X509v3 extensions:
X509v3 Authority Key Identifier:
 X509v3 Subject Key Identifier:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Basic Constraints: critical
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Certificate Policies:
 X509v3 CRL DistributionPoints:

The main disadvantages to CRL are :

· Can create a large amount of overhead, as the client has to search through the revocation list. In some cases this can be 1000’s of lines long.

· CRLs are updated periodically every 5-14 days. Potentially leaving the attack surface open until the next CRL update.

· The CRL is not checked for OV or DV based certificates. Checked for EV certificates.

· If the client is unable to download the CRL then by default the client will trust the certificate.


OCSP (Online Certificate Status Protocol) removes many of the disadvantages of CRL by allowing the client to check the certificate status for a single certificate.

The OCSP process in shown below,

1. Client receives certificate.

2. Client sends OCSP Request to a OCSP Responder (over HTTP) with the certificates serial number.

3. OCSP Responder replies with a certificate status of either Good, Revoked or Unknown (shown below)

Response verify OK
0x25F5V12D5E6FD0BD4EAF2A2C966F3B4aE: good
 This Update: Jan 19 00:24:56 2011 GMT
 Next Update: Jan 26 00:24:56 2011 GMT

The main advantage to OCSP is that because the client can query the status of a single certificate, rather then having to download and parse an entire list there is much less overhead on the client and network.

However the main disadvantages to OCSP are,

· OCSP Requests are sent for each certificate. Because of this there can be a huge over head on the OCSP Responder (i.e the CA) for high traffic websites.

· If the private key was comprised the attacker would need to leverage a MITM attack to intercept and pose as the server. Because most browsers slienty ignore OCSP if the protocol times out OCSP can still not be considered a 100% reliable method for mitigating HTTPS server key comprises.

· The OCSP is not enforced for OV or DV based certificates. Checked for EV certificates.


OCSP Stapling resolves the overhead issues with OCSP and CRL by having the certificate holder (i.e the server) periodically performing the OCSP Request. The OCSP Response is then sent back to the client (i.e stapled) during the SSL handshake.

NOTE The OCSP Response is signed by the CA to ensure that it has not been modified before being sent back to the client.

The main disadvantages with OCSP Stapling are,

· Only supported within TLS 1.2.

· It is still not supported by many browsers . This results in either the OCSP validity method not being used or standard OCSP being used instead.



OCSP Stapling<

Certificate Types / Browser Functionality

Posted in Mix & Match | Leave a Comment »

Powershell with Internet Proxy Servers

Posted by Brajesh Panda on June 24, 2016

Posted in Mix & Match | Leave a Comment »

ADFS: NameID Claim with Additional Properties

Posted by Brajesh Panda on May 26, 2016

Lately I was doing a SAS application (Axxerrion) integration with our ADFS. And they had a requirement to get a few things as additional properties i.e. spnamequalifier, namequalifier & nameID format to be mentioned as transient.

Here what I came up with. They also needed UPN for validation. So in 1st rule I am creating two outgoing claims. In 2nd custom rule, I am adding attributes to the Outgoing NameID claim. Final claim screenshot is at the bottom.

Claim Rules

Rule 1:











Rule 2:

c:[Type == ““]

=> issue(Type = ““, Issuer = c.Issuer, OriginalIssuer = c.OriginalIssuer, Value = c.Value, ValueType = c.ValueType, Properties[““] = “urn:oasis:names:tc:SAML:2.0:nameid-format:transient”, Properties[““] = “https://<Adfs_URL>/adfs/ls/“, Properties[““] = ““);

Saml Claim thru SAML Tracer

Posted in ADFS | Leave a Comment »

Powershell Trick: Execute Logon Script as per Group Membership

Posted by Brajesh Panda on May 22, 2016

If((Get-ADPrincipalGroupMembership $env:username).name -like “Domain Users”)

{Write-Host “Yes”}

Change the Write-Host section with the action script, what you want to execute. I think this is what you want.

Here $env:username gets the logged on user name. It is like “whoami” command, without the domain info. You can get domain info using $env:USERDNSDOMAIN

Posted in Mix & Match, Powershell | Tagged: | Leave a Comment »

Powershell Trick: Convert TXT to HTML and Send Email

Posted by Brajesh Panda on May 17, 2016

If you want to get contents from a txt file and send its content in email body, this trick will do the job. My txt file has multiple separate lines, like general error files.

So this trick joins all lines with <BR> HTML encode to introduce line breaks. If you do not use this encode and just do get-content, all lines will be messed like a paragraph and will be hard to read.

$Body = (Get-Content <File Path>) -join ‘<BR>’

After you encode the html, make sure use BodyAsHtml to set outgoing email format. So email client will convert html page back to readable format.

Send-MailMessage -From <> -To <> -Subject <Message> -Body $Body -BodyAsHtml -SmtpServer smtp.server

Posted in Mix & Match, Powershell | Tagged: | Leave a Comment »

Powershell Trick: Capture Valid IP

Posted by Brajesh Panda on April 30, 2016

[ipaddress]$ipaddress = Read-Host “Type valid ip”

Posted in Mix & Match, Powershell | Tagged: | Leave a Comment »

Windows Hello: Password Less World

Posted by Brajesh Panda on April 13, 2016

Interesting technology…

Posted in Mix & Match | Leave a Comment »

Powershell – Get AD Forest Details

Posted by Brajesh Panda on March 30, 2016

Get AD Forest Details…

$Forest = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest() | select -expandproperty domains

$Forest | Add-Member -MemberType NoteProperty DCs ”

$forest | ForEach-Object {$PSitem.DCs = ($PSItem | select -ExpandProperty DomainControllers) -join ‘,’}


Like Domains, sites can be expanded for more details etc. So I am going to work on this and expand the same to get more details… Thank you Jason Heisley for motivating me to learn ADSI .Net Namespaces😉

Posted in Mix & Match, Powershell | Tagged: | Leave a Comment »

Service Now REST API and PowerShell

Posted by Brajesh Panda on March 28, 2016

Disclaimer… Neither am I a software developer nor a Service Now Guru. In the absence of our service now dev guy, I just got some time to play around with my powershell stuff. Just out of curiosity trying to learn how to work with REST API using Powershell.

Latest service now instances (starting with Eureka release) supports REST API. More info can be found here

There are tons of REST client resources in programming languages & dev guys understand them better. But as an infrastructure professional, without much of Dev knowledge, I play around with Powershell & bit with Chrome’s REST Extension. So “Invoke-RestMethod” cmdlet is my friend here. Note, Powershell 3.0 and above support this. I use latest one… 5.0😉. Just learned a new app from, These GUI tools are kind of cool to understand different parameters.

1. So Service Now REST API can be connected using two methods;

a. With Normal User ID & Password. Means every time you query, you need to send out both user ID & password for authentication. Although it goes thru HTTPS, it is little bit too much when you are doing all these stateless queries.

b. With Token based authentication. Starting with Service now’s Fuji release we can use Access Token to do all these queries. And this Access Token expires after certain time (default 30mins), then we can use another token called as Refresh Token with a fixed Client ID (like a weird string user name) & Client secret (like a complex password) to regenerate the Access Token.

2. Let’s see the powershell codes for 1(a) method.

# Query Incident Table and get maximum numbers of ticket

$URI = ‘’

# OR Query Incident Table and get one ticket using sysparm query

# $URI = ‘https://’

$SNowUser = “DomainUser” # If integrated with ADFS or any SAML Identity Source for SSO

$SNowPass = ConvertTo-SecureString –String “Password” –AsPlainText -Force

$SNowCreds = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $SNowUser, $SNowPass

$Incidents = Invoke-RestMethod -Uri $URI -Credential $SNowCreds -Body $Body -ContentType "application/json"



3. For 1(b) method, you have to enable OAuth 2.0 thru service now portal. Here are the steps;

4. You may have to give yourself security admin role. I think I have that access in our Dev instance. I am going to figure that out later. As it is not my current priority, I have not checked those details.

5. Here is a screenshot. I created a new one for my Powershell Scripts.

In Service Now – Search “system oauth” – click on “application registry” – Click “new” – Select “Create an Oauth api endpoint for external clients” – configure necessary things..

6. Keep Client ID & Client Secret in a safe place. You may like to change Refresh token and access token time period as per our requirement.

7. Here is a nice video presentation from service now team using getpostman app. This one demonstrate how to generate refresh token & access token. And then how to use access token to retrieve data. But I am going to give you few line of Powershell codes here…

# Get Refresh token and Access Token using below script

$username = “DomainUsername”

$password = “Password”

$ClientID = “Paste Client ID from Step 6”

$ClientSecret = “Paste Client Secret from Step 6”

# Query REST Endpoint

$RestEndpoint = ‘’

$body = [System.Text.Encoding]::UTF8.GetBytes(‘grant_type=password&username=’+$username+’&password=’+$password+’&client_id=’+$ClientID+’&client_secret=’+$ClientSecret)

Invoke-RestMethod -Uri $RestEndpoint -Body $Body -ContentType ‘application/x-www-form-urlencoded’ -Method Post

8. Output will be somewhat like below..

scope : useraccount

token_type : Bearer

expires_in : 1800

refresh_token : jsdfkajd;ewiorqjkfmsdkfamdfi;qirjqwkvm,c vkoejpmfklsdmfpiopioqijekmfd,kj7381893409mkas

access_token : sdnfok34u59834mdkfmaoiei4u398mlak;smr9i43uumaslkjripp98q347ja;k3ju409932mf;lkaj493q883

9. Now let’s use the access_token to retrieve data. We need to pass access_token thru headers as authorization. Do not forget that Bearer word to append before the access token.

# Query Incident Table and get maximum numbers of ticket

$URI = ‘’

# OR Query Incident Table and get one ticket using sysparm query

# $URI = ‘https://’

$headers = @{“authorization” = “Bearer sdnfok34u59834mdkfmaoiei4u398mlak;smr9i43uumaslkjripp98q347ja;k3ju409932mf;lkaj493q883”}

$result = Invoke-RestMethod -Uri $URI -Headers $headers

10. After 1800 seconds, the access_token will expire and we need a new one. We can use the step 7 or below codes with the existing refresh_token, client id & secret to get a new access_token.

# Get Access Token using Refresh Token.

$Refreshtoken = "jsdfkajd;ewiorqjkfmsdkfamdfi;qirjqwkvm,c vkoejpmfklsdmfpiopioqijekmfd,kj7381893409mkas"

$ClientID = “Paste Client ID from Step 6”

$ClientSecret = “Paste Client Secret from Step 6”

# Query REST Endpoint

$RestEndpoint = ‘’

$body = [System.Text.Encoding]::UTF8.GetBytes(‘grant_type=refresh_token&client_id=’+$ClientID+’&client_secret=’+$ClientSecret+’&refresh_token=’+$refreshtoken)

Invoke-RestMethod -Uri $RestEndpoint -Body $Body -ContentType ‘application/x-www-form-urlencoded’ -Method Post

11. Output will be kind of same as step 8, with a different access_token. Then repeat step 9 using new access token.

Posted in Mix & Match, Powershell | Tagged: , , | Leave a Comment »

Application of Active Directory Snapshot feature

Posted by Brajesh Panda on March 21, 2016

Posted in Active Directory User Management, BackupExec 2010, BackupExec2010R3, Mix & Match, Powershell | Tagged: | Leave a Comment »

%d bloggers like this: