• Using Azure Traffic Manager with IP White-listed resources

    Using Azure Traffic Manager with IP White-listed resources

    The question was, how can you use Azure Traffic Manager if the destinations are restricted with IP white lists?
    This is the only way I could find:

    1. There is a blob that contains the source IPs of the probes. Here is the file, And here is the reference
    2. This list would need to be queried often because I couldn’t find any indication of when it would be updated
    3. I wrote PowerShell to parse the results and put it into an NSG.
    
    $RGName= "Your RG Name"
    $NSGName = "Your NSG Name"
    $NSGRuleName = "Your Rule Name"
    $Priority = 120
    $DestinationPortRange = 443
    $url="https://azuretrafficmanagerdata.blob.core.windows.net/probes/azure/probe-ip-ranges.json"
    $results=Invoke-RestMethod -Uri $url
    $allAddresses=@()
    foreach ($address in $results.ipv4_prefixes){
    $allAddresses += $address.ip_prefix
    }
    # for some reason, get-AzureRmNetworkSecurityRuleConfig errors out if there is no matchin name
    # could use a try - catch
    if  ((Get-AzureRmNetworkSecurityGroup -ResourceGroupName $RGName -Name $NSGName | get-AzureRmNetworkSecurityRuleConfig -Name $NSGRuleName -ErrorAction SilentlyContinue) -eq $null){
    # Creating RUle
    Get-AzureRmNetworkSecurityGroup -ResourceGroupName $RGName -Name $NSGName | `
    Add-AzureRmNetworkSecurityRuleConfig -Name $NSGRuleName -Description "Allow Probe from ATM" -Access Allow -Protocol Tcp -Direction Inbound -Priority $Priority -SourceAddressPrefix $allAddresses -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange $DestinationPortRange | Set-AzureRmNetworkSecurityGroup
    }
    else {
    # Updating Rule
    Get-AzureRmNetworkSecurityGroup -ResourceGroupName $RGName -Name $NSGName | `
    Set-AzureRmNetworkSecurityRuleConfig -Name $NSGRuleName -Description "Allow Probe from ATM" -Access Allow -Protocol Tcp -Direction Inbound -Priority $Priority -SourceAddressPrefix $allAddresses -SourcePortRange * -DestinationAddressPrefix * -DestinationPortRange $DestinationPortRange | Set-AzureRmNetworkSecurityGroup
    }
    
    

    Hope that helps.


  • PowerShell to move a VM to a new Log Analytics WorkSpace

    This code uninstalls the Microsoft Monitoring agent and re-installs it to a new WorkSpace.

    
    # change your VM Name and it's resource group
    $vm = get-azurermvm -VMName YourVMName -ResourceGroupName VMResourceGroup
    Remove-AzureRmVMExtension -ResourceGroupName $vm.ResourceGroupName -VMName $vm.Name -Name MicrosoftMonitoringAgent -Force
    # put in your new workspaceId & workspaceKey
    $workspaceId = "NewWorksSpaceID"
    $workspaceKey = "SupaSecretKey"
    
    $PublicSettings = @{"workspaceId" = $workspaceId;"stopOnMultipleConnections" = $false}
    $ProtectedSettings = @{"workspaceKey" = $workspaceKey}
    
    Set-AzureRmVMExtension -ExtensionName "MicrosoftMonitoringAgent" -ResourceGroupName $vm.resourcegroupname -VMName $vm.name `
    -Publisher "Microsoft.EnterpriseCloud.Monitoring" `
    -ExtensionType "MicrosoftMonitoringAgent" `
    -TypeHandlerVersion 1.0 `
    -Settings $PublicSettings `
    -ProtectedSettings $ProtectedSettings `
    -Location $vm.Location
    

    Nothing special, just thought I would put it here. Mayby it will help someone?


  • Use the REST API to create a new Project in Azure DevOps

    As the title says, I wanted to create a new project in VSTS / Azure DevOps, whatever you want to call it. Here is the code to do that. You need a Personal Access Token to authenticate with.

    $User="[email protected]"
    $PAT="YourPAT"
    $Organization="YourOrg"
    $base64authinfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $User, $PAT)))
    $url="https://dev.azure.com/$Organization/_apis/projects?api-version=5.1-preview.4"
    $body = @"
    {
      "name": "FabrikamTravel",
      "description": "Frabrikam travel app for Windows Phone",
      "capabilities": {
        "versioncontrol": {
          "sourceControlType": "Git"
        },
        "processTemplate": {
          "templateTypeId": "6b724908-ef14-45cf-84f8-768b5384da45"
        }
      }
    }
    "@
    Invoke-RestMethod -Method POST -ContentType application/json -Uri $url -Headers @{Authorization=("Basic {0}" -f $base64authinfo)} -Body $Body
    

    Hope that helps someone?


  • Using PowerShell to query Azure Log Analytics via the REST API

    I wanted to pull some data out of Azure Log Analytics using PowerShell and the REST API. Here is the code to Pull all errors in the Application event logs on VMs that are pushing their logs into Log Analytics via MicrosoftMonitoringAgent.

    Hopefully this may help someone:

    $SubscriptionId = "$($env:SubscriptionId)"
    $TenantId       = "$($env:TenantId)" 
    $ClientID       = "$($env:ClientID)"      
    $ClientSecret   = "$($env:ClientSecret)"  
    $TenantDomain   = "$($env:TenantDomain)" 
    $loginURL       = "https://login.microsoftonline.com/$TenantId/oauth2/token"
    $resource       = "https://api.loganalytics.io"         
    
    $body           = @{grant_type="client_credentials";resource=$resource;client_id=$ClientID;client_secret=$ClientSecret}
    $oauth          = Invoke-RestMethod -Method Post -Uri $loginURL -Body $body
    $headerParams = @{'Authorization'="$($oauth.token_type) $($oauth.access_token)"}
    
    $Workspacename="Your WS Name"
    $WorkspaceId="Your WS ID"
    
    $url="https://api.loganalytics.io/v1/workspaces/$WorkspaceId/query"
    $body = @{query = 'Event | where EventLog == "Application" | order by TimeGenerated asc | project Computer,EventLog,Source,EventLevelName,EventID,RenderedDescription,TimeGenerated'} | ConvertTo-Json
    $webresults=Invoke-RestMethod -UseBasicParsing -Headers $headerParams -Uri $url -Method Post -Body $body -ContentType "application/json"
    

    Notes:

    1. I keep my subscription information in Env Varaibles. It is easier for me to swtich to a different Tenant
    2.  This returns the results in tables. To move the tables into an object look at this person’s code at line 60  https://blog.tyang.org/2017/11/14/searching-oms-using-the-new-search-language-kusto-rest-api-in-powershell/
    3. My interpretation of code in #2
    $resultsTable=$webresults.Content | ConvertFrom-Json
    $count = 0
    foreach ($table in $resultsTable.Tables) {
    $count += $table.Rows.Count
    }
    $results = New-Object object[] $count
    $i = 0;
    foreach ($table in $resultsTable.Tables) {
        foreach ($row in $table.Rows) {
            # Create a dictionary of properties
            $properties = @{}
            for ($columnNum=0; $columnNum -lt $table.Columns.Count; $columnNum++) {
                $properties[$table.Columns[$columnNum].name] = $row[$columnNum]
            }      
            $results[$i] = (New-Object PSObject -Property $properties)
            $null = $i++
        }
    }
    $results
    




  • Removing machines from Azure State Configuration (DSC)

    I have been provisioning machines over an over trying to learn all the VM Extensions. One of the extensions that I have been playing with is the DSC extension. Every time I provision with this extension, it adds an additional record into the State Configuration, resulting in many stale machines. I wanted to clear out all the old machines. I couldn’t find a way to do it in PowerShell, so I figure out how to do it via the REST API (and PowerShell).

    Here is the code to remove all machines from Azure State Configuration (DSC)

    $SubscriptionId = "$($env:SubscriptionId)"
    $TenantId       = "$($env:TenantId)" 
    $ClientID       = "$($env:ClientID)"      
    $ClientSecret   = "$($env:ClientSecret)"  
    $TenantDomain   = "$($env:TenantDomain)" 
    $loginURL       = "https://login.microsoftonline.com/$TenantId/oauth2/token"
    $resource       = "https://management.core.windows.net/"    
    $resourceGroupName = "YourResourceGroupName "
    $automationAccountsName ="YourAutomationAccountsName "
    
    # get the OAUTH token & prepare header
    $body           = @{grant_type="client_credentials";resource=$resource;client_id=$ClientID;client_secret=$ClientSecret}
    $oauth          = Invoke-RestMethod -Method Post -Uri $loginURL -Body $body
    $headerParams = @{'Authorization'="$($oauth.token_type) $($oauth.access_token)"}
    
    # main query to find all the nodes
    $url="https://management.azure.com/subscriptions/$SubscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.Automation/automationAccounts/$automationAccountsName/nodes?api-version=2018-01-15"
    $results=Invoke-RestMethod -Uri $url -Headers $headerParams -Method Get
    # Loop through all the nodes and delete them all.
    foreach ($node in $($results.value | Select-Object  -ExpandProperty properties | Select nodeid)){
    $url="https://management.azure.com/subscriptions/$SubscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.Automation/automationAccounts/$automationAccountsName/nodes/$($node.nodeId)?api-version=2018-01-15"
    Invoke-RestMethod -Uri $url -Headers $headerParams -Method Delete
    }
    

    Notes:

    1. I put all my SPN info into environmental varaibles (easier to switch of needed)
    2. Put in your RG name and Auutomation Account Name
    3. Warning. This will delete all nodes!

    HTH


  • My WSL/BASH setup

    Not sure if this a “Bootstrap” or not, but I wanted to have my WSL/Bash home directory match my windows home directory. This is the code that I use when I setup a new WSL/BASH instance.

    This will find your home directory via PowerShell and put it in a variable “$WINHOME”.

    Then I make make soft links to the directories in my “My Documents”.

    Finally, I add the first part to my .bashrc. (lines 1-4)

    
    WINHOME=/mnt/$(powershell.exe -noprofile -noninteractive -command '& {(gci env:USERPROFILE).Value}')
    WINHOME=$(echo $WINHOME | sed 's/\\/\//g' | sed 's/\r$//' | sed 's/\://g' )
    WINHOME=$(echo ${WINHOME/C/c})
    export WINHOME=$WINHOME
    
    ln -s $WINHOME/Documents
    ln -s $WINHOME/Downloads
    

  • My SSL/Certificate Cheatsheet

    Whenever a certificate needs to be renewed, I always have to scramble to remember how to update/renew. I finally put a cheat sheet together.

    I decided I will do all cert related stuff form Linux. Here are some commands:

    To request a new csr with a new key:

    openssl req -newkey rsa:2048 -keyout yourcompany.com.key -out yourcompany.com.csr
    
    Generating a 2048 bit RSA private key
    .............................................................................................+++
    .............+++
    writing new private key to 'stratgovadvisors.com'
    Enter PEM pass phrase:
    Verifying - Enter PEM pass phrase:
    -----
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [AU]:US
    State or Province Name (full name) [Some-State]:New York
    Locality Name (eg, city) []:New York
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:Your Company name
    Organizational Unit Name (eg, section) []:IT
    Common Name (e.g. server FQDN or YOUR name) []:*.yourcompany.com
    Email Address []:
    
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:
    

    To request a new csr with an existing key:

    openssl req -new -key yourcompany.com.key -out yourcompany.com.csr 
    

    To make a PFX form a Private key and a cert:

    openssl pkcs12 -export -out yourcompany.com.pfx -inkey yourcompany.com.key -in yourcompany.com.crt
    

    To extract Private key and Cert from a PFX (3 steps)

    Export the private key

    openssl pkcs12 -in yourcompany.com.pfx -nocerts -out yourcompany.com.pem -nodes
    

    Export the certificate

    openssl pkcs12 -in yourcompany.com.pfx -nokeys -out yourcompany.com.crt
    

    Remove the passphrase from the private key

    openssl rsa -in yourcompany.com.pem -out yourcompany.com.key 
    

  • My PowerShell scripts to encrypt Azure VM disks

    This is my steps that I took from this very long document.

    First we need to create a Key vault and then an AAD application, then you connect them. Make note of the output of $aadClientID.

    $KeyVaultName="YourName-EastUS"
    $ResourceGroupName="Default-EastUS"
    $Location="East US"
    
    
    #Create New KeyVault
    New-AzureRmKeyVault -VaultName $KeyVaultName -ResourceGroupName $ResourceGroupName -Location $Location
    
    #Create New AAD Application
    $aadClientSecret = "YourLongSecret"
    $azureAdApplication = New-AzureRmADApplication -DisplayName "Encryption-EastUS" -HomePage "https://IThinkAnythingCanGoHere" -IdentifierUris "https://IThinkAnythingCanGoHereURi" -Password $aadClientSecret
    $servicePrincipal = New-AzureRmADServicePrincipal -ApplicationId $azureAdApplication.ApplicationId
    $aadClientID = $azureAdApplication.ApplicationId
    $aadClientID
    Set-AzureRmKeyVaultAccessPolicy -VaultName $KeyVaultName -ServicePrincipalName $aadClientID -PermissionsToKeys all -PermissionsToSecrets all -ResourceGroupName $ResourceGroupName;
    Set-AzureRmKeyVaultAccessPolicy -VaultName $KeyVaultName -EnabledForDiskEncryption
    

    Once that is setup, you can encrypt a VM:

    $KeyVaultName="YourName-EastUS"
    $ResourceGroupName="Default-EastUS"
    $Location="East US"
    $vmName="VMNAME"
    
    $aadClientSecret = "YourLongSecret"
    $aadClientID = "YouMadeNoteOfThisAbove"
    $KeyVault = Get-AzureRmKeyVault -VaultName $KeyVaultName -ResourceGroupName $ResourceGroupName;
    $diskEncryptionKeyVaultUrl = $KeyVault.VaultUri;
    $KeyVaultResourceId = $KeyVault.ResourceId;
    
    Set-AzureRmVMDiskEncryptionExtension -ResourceGroupName $ResourceGroupName -VMName $vmName -AadClientID $aadClientID -AadClientSecret $aadClientSecret -DiskEncryptionKeyVaultUrl $diskEncryptionKeyVaultUrl -DiskEncryptionKeyVaultId $KeyVaultResourceId;
    

    If you did not make note of your aadClientID, then you run:

    get-AzureRmADApplication
    

    And the ApplicationId is what you are looking for.

    I forgot how I set this up, so I went back and made some notes, and now I hope this helps someone.