Search This Blog

Tuesday, November 13, 2018

Run TimeStamped Pings against large Computer list

Had to run long term ping test against a number of devices. As such I created the following script that will ping the devices, with a timestamp, logging to a file.

computer list is in a file, should be in the same folder as the script. In this case file called ips.txt.

param ([ Int32 ] $ PingCount = 14400 , [ string ] $ file = '.\ips.txt' )

 

function Get-ScriptDirectory

{

    #Determine the folder in which the script lives.

    $ Invocation = ( Get-Variable MyInvocation -Scope 1 ).Value

    Split-Path $ Invocation .MyCommand.Path

}

 

$ scriptPath = Get-ScriptDirectory

 

$ TimeStampPing = {

    param ( $ comp , $ count , $ scriptPathBlock )

    filter timestamp { " $ ( Get-Date - Format o): $ _ " } ;

    ping $ comp -n $ count | timestamp > " $ ( $ scriptPathBlock )\pingtest- $ ( $ comp ).txt"

  }

 

foreach ( $ line in Get-Content $ file ) {

    Start-Job -ScriptBlock $ TimeStampPing -ArgumentList $ line , $ PingCount , $ scriptPath

}


Share/Bookmark

Monday, November 12, 2018

Powershell: Post code to blogger from Visual Studio Code

Using the blogger web tool, have been able to paste from VSC to web tool and it will colour code.

Just need to jump to HTML view and change the style paramters of the div's from

 white-space: pre;

to

 white-space: pre-wrap;

which will allow for the code to wrap.


OLD: Notes for myself, as I forget by the time I write something new.Smile

Using Visual Studio Code to create Powershell code.

You can copy and paste to word and the formatting is maintained.

Save the file as an rtf file.

Use an rtf converter to convert to HTML. I use the MultiDOC Converter (freeware).

I then paste this HTML code into Windows Live Writer.

Note: If you go from the edit tab, then live writer will change the style class to lower case, and then they wont match the uppercase class names in the code.

So to publish just paste the style block into the code page, just prior to publish.

Reference:

http://www.multidoc-converter.com/en/index.html


Share/Bookmark

Powershell: Cloudflare List all domains and search for ip

Quick Note: This code is quickly put together to prompt for the Cloudflare API key and email, then will list all the domains in cloudflare and also prompt for an ip to search for within all domains. Please ignore the debugging and extra code

$ CloudflareAPIKey = Read-Host -Prompt 'Enter the API Key' ;

$ CloudflareAPIEmail = Read-Host -Prompt 'Enter the API email e.g. user@domain' ;

$ headers = @ {

    "X-Auth-Key" = $ CloudflareAPIKey ;

    "X-Auth-Email" = $ CloudflareAPIEmail ;

    "Content-Type" = 'application/json'

}

 

#this may need changing when Cloudflare update the api

[ string ] $ cloudFlareApiBaseUrl = "https://api.cloudflare.com/client/v4"

 

#Force TLS version to be 1.2 (cloudflare only allows tls1.2 now)

[ Net.ServicePointManager ]::SecurityProtocol = [ Net.SecurityProtocolType ]::Tls12

 

# Get Zones from cloudflare

$ request = Invoke-WebRequest -Uri " $ { cloudFlareApiBaseUrl }/zones" -Method "GET" -Headers $ headers

$ CloudflarePagedDomains = ConvertFrom-Json $ request .Content

[ int ] $ pageCount = $ CloudflarePagedDomains .result_info [ 0 ].total_pages

 

$ CloudflareAllDomains = @ ()

 

$ IpSearchValue = Read-Host -Prompt 'IP address to search for in Cloudflare' ;

 

write-host "List of all domains in cloudflare" -foregroundcolor "Yellow"

for ( $ i = 1 ; $ i -le $ pageCount ; $ i ++)

{

    $ Parameters = @ {

        page = $ i

      }

      $ request = Invoke-WebRequest -Uri " $ { cloudFlareApiBaseUrl }/zones" -Method "GET" -Headers $ headers -Body $ Parameters

      $ CloudflarePagedDomains = ConvertFrom-Json $ request .Content

    #loop through $request.result array...

    Foreach ( $ CloudflareDomain IN $ CloudflarePagedDomains .result ) {

        $ CloudflareAllDomains += $ CloudflareDomain .name ;

        write-host " $ ( $ CloudflareDomain .name ) `r " -foregroundcolor "DarkCyan"

    }

}

 

Foreach ( $ CloudflareDomain IN $ CloudflareAllDomains ) {

    $ request = Invoke-WebRequest -Uri " $ { cloudFlareApiBaseUrl }/zones/?name= $ { CloudflareDomain }" -Method "GET" -Headers $ headers

   

    $ zoneId = $ ( ConvertFrom-Json $ request .Content ).result[ 0 ].id

    write-host "Searching $ (( $ CloudflareDomain ).padright( 75 )) $ ( $ zoneId )" -foregroundcolor "Yellow"

    $ Parameters = @ {

        type = 'A'

        content = $ IpSearchValue

      }

    $ request = Invoke-WebRequest -Uri " $ { cloudFlareApiBaseUrl }/zones/ $ { zoneId }/dns_records" -Method "GET" -Headers $ headers -Body $ Parameters

 

    Foreach ( $ RecordFound IN $ ( ConvertFrom-Json $ request .Content ).result) {

        write-host " $ (( $ RecordFound .name ).padright( 75 )) $ ( $ RecordFound .content )" -foregroundcolor "Green"

    }

}

 

 


Share/Bookmark

Monday, October 15, 2018

Availability Groups–Not preferred replica

Came across an issue where are AG failed over, but 4 of 47 databases decided the local secondary db replica was not preferred and set their preferred replica to DR.

AG backup preferences had been correctly set, and in the past this database AG had happily failed over multiple times without issue.

The AG housed 47 databases, with only 4 decided to go to DR??

In the end I have now idea why or how SQL decided that these 4 should be preferred at DR site, and the other 43 were on the local secondary.

image

In the end I resolved by manually forcing a failover back to the current local secondary replica (DB02). When this was the primary, I then failed back to DB02. I did this just to ensure there wasn’t an issue failing over in a certain direction.

To check that all databases were correctly set I created the following scripts that will list the value of sys.fn_hadr_backup_is_preferred_replica

EXECUTE master.sys.sp_MSforeachdb 'USE [?]; DECLARE @dby VARCHAR(max); SET @dby=DB_NAME(); SELECT @dby;SELECT sys.fn_hadr_backup_is_preferred_replica (@dby);'

This made it easy to confirm all servers and database were correctly setup.

Still none the wiser how it can get so muddled.


Share/Bookmark

Tuesday, June 19, 2018

I don’t like mondays… Powershell: Move specific files

Recently had to move files from an archive location. THe archive location was a reasonable large folder structure containing around 60000 files of various sizes (between 1Kb to 100GB+).
The archive was to be cleaned out leaving only files created on a Monday. I won’t go into why this was the case.
Came up with the following script, which works pretty well.


$SourceRootPath = '\\server01\sourceRootFolder\'
$DestinationRootPath = '\\server02\DestinationRootFolder\DesitnationSubFolder'
Set-Location $SourceRootPath

$Count = 0;

#Replicate source folder structure in destination folder
Copy-Item $SourceRootPath $DestinationRootPath -filter {PSIContainer} -Recurse -Force

$allbackups = get-childitem $SourceRootPath -Recurse -filter '*.bak' | Where-Object {!$_.PSIsContainer -and $_.lastwritetime.DayOfWeek -ne 'Monday'}

ForEach ($file in $allbackups)
{
    $Count++;
    $relativePath = Resolve-Path -Path $file.DirectoryName -Relative
    $DestinationPath = Join-Path $DestinationRootPath -childpath $relativePath.replace('.\','')
    Write-Progress -Activity "Moving  $($file.FullName)" -Status 'Progress ->' -PercentComplete (([int]($Count / $allbackups.Count)) * 100)
    Move-Item -Path $file.FullName -Destination $DestinationPath
}


Share/Bookmark

Tuesday, June 12, 2018

AWS–ADFS setup (Federation)–Windows AD

Recently had to setup ADFS federation for access to AWS.

I found an excellent article about setting this up, however I did experience some issues and I will detail them here, there is nothing wrong with the article it was just out environment.

https://aws.amazon.com/blogs/security/aws-federated-authentication-with-active-directory-federation-services-ad-fs/

What happened is that in our domain we setup some groups as  domain local security groups. As it turns out the method in this article that returns the groups for the user (rule: Get AD Groups), uses a LDAP attribute called tokengroups. What is not apparent is that this will not return groups that are distribution groups or domain local groups….

There is no obvious error that indicates this, and it was only why faulting finding that I stumbled across this article, and it has a side note that states this fact.!! Its actually in the real world example.

https://blogs.technet.microsoft.com/askds/2013/05/07/ad-fs-2-0-claims-rule-language-part-2/

So the quickest and easiest solution for us was to change the group to universal. However the second article above does detail that memberOf can be used in tokengroup place, however the result is the full distinguished name and needs to be manipulated before it can be used.

If I get time I will try and see if I can use this method. I will post here if I can.

Update: OK, looking at this further the memberOf feature only includes groups in which the user is a direct member… so nested groups become a problem.

further reference

https://social.technet.microsoft.com/wiki/contents/articles/13829.ad-fs-2-0-domain-local-groups-in-a-claim.aspx

https://www.morgantechspace.com/2015/08/active-directory-tokengroups-vs-memberof.html


Share/Bookmark

Monday, May 07, 2018

Powershell: Format Fixed Width String (-f format operator)

Had to build a table in a text format of a predetermined width. What I found is that the –f operator can assist with building this

I had a variable that I stored the text output in, and then appened the results to it.

Add table header to string variable

$StringOutput += "{0,-80}{1,10}{2,25}" -f 'Filename','Size (KB)','Date';

Then loop through results

foreach (item in list)

{

$sqlStringOutput += "{0,-80}" -f $item.Name + "{0,10}" -f ("{0:n2}" -f ($item.Length/1kb)) + "{0,25}" -f ("{0:yyyy-MM-dd HH:mm:ss}" -f ([datetime]::ParseExact($item.LastWriteTime,'MM/dd/yyyy HH:mm:ss',$null))) + $htmlbr;

}

Output

Filename                                                                         Size (KB)                     Date

filename1.bak                                                                         0.50      2018-04-22 22:37:40
filename2.bak                                                                         0.50      2018-04-23 22:39:35

So I have used different ways to build the string using formatting.

1. "{0,-80}{1,10}{2,25}"  - this is one format string, the first number 0,1,2 are the indexes of the following strings. the –80,10,25 are how wide the end string is (with padding), the – number means align left, positive align right.

2. I used multiple format strings then concatenate them together, I just found it easier to read (due to nested format strings on the numbers and dates.

References

https://blogs.technet.microsoft.com/heyscriptingguy/2013/03/11/understanding-powershell-and-basic-string-formatting/

https://ss64.com/ps/syntax-f-operator.html


Share/Bookmark

Thursday, May 03, 2018

Powershell: reveal hidden/truncated data in output

Things to try

1. $FormatEnumerationLimit = –1

2. Select-Object –ExpandProperty <property>

Output will display everything.

https://blogs.technet.microsoft.com/heyscriptingguy/2011/11/20/change-a-powershell-preference-variable-to-reveal-hidden-data/


Share/Bookmark

Powershell: List basic path info for all folders recursively

Had the need to create one big list of all folders in a folder tree. I could get this using Get-Childitem but it broke it down into a nicely formatted output, which is not what I needed.

I wanted just one path per line.

I came up with the following. Initially the output was being truncated, so long paths were truncated with …

This truncate can be removed by setting the following variable to –1

$FormatEnumerationLimit=-1

Not sure why but $FormatEnumerationLimit didnot work, I have to use the ExpandProperty function of the select-object cmdlet.

Get-ChildItem -path \\server\rootfolderpath -Recurse | ?{ $_.PSIsContainer }| Select -ExpandProperty FullName | Format-table FullName > folders.txt


Share/Bookmark

Wednesday, April 25, 2018

Office 365–Remove Office365 user/contact out of sync

Just had to deal with a hybrid office 365 environment, so on prem AD was syncing to office 365 – no writeback.

Over the time that dirsync/aad connect has been syncing, OUs have been added and removed. As such some issues have occurred with contacts and users. We then had issues when OUs were added back that contacts and users collided on some data (proxyaddresses).

In some cases we were able to make changes to the objects on prem, and these then sync’d in the next run.

However we had some where the office 365 /Azure AD object had become orphaned. Office 365 thought they were sync’d with on prem AD, and as such the gui (web) interface would not allow us to delete these objects.

This is easy to fix, just need to connect to office 365 using powershell to remove the object.

Install the powershell modules if you don’t have them

  • Install-Module -Name AzureRM -AllowClobber –Force
  • Install-Module MSOnline

Connect to Azure/Office365

  • $credential = Get-Credential
  • Connect-MsolService -Credential $credential
  • Get-MsolContact -objectid fad9c2dd-xxxxx-x-xxxx-x-x-x-x-x-x-x
  • Remove-MsolContact -objectid fad9c2dd-xxxxx-x-xxxx-x-x-x-x-x-x-x

Share/Bookmark