Azure Automation: Secure your webhook

Azure Infrastructure, Windows PowerShell

In my previous post titled Azure Automation: Sync Runbooks from Visual Studio Team Services, I used a webhook. The webhook is just a URL that will be triggered using an HTTP POST. In Azure Automation, they look like this:

https://s1events.azure-automation.net/webhooks?token=xxyyzzaabbcc

Anyone who got the URL, could simply do an HTTP POST and your webhook would be invoked. For example:

Invoke-WebRequest -Uri https://s1events.azure-automation.net/webhooks?token=xxyyzzaabbcc -Method POST

All is not lost, we can add *some* security to this using WebhookData.

[click to continue…]

0 comments

Azure Automation: Sync Runbooks from Visual Studio Team Services

Azure Infrastructure, Windows PowerShell

 

This is sort of an update or branch off of a blog post by Gary Keong titled: Azure Automation: Integrating Runbook Source Control using Visual Studio Online (July 2014) and includes some of my learnings.

Use Case

We are going to sync some runbooks for the purposes of subscription management. This could include things like setting up alerts, applying permissions, and applying policies to the subscription. I’m going to assume you have a Visual Studio Team Services Account (create one if not).

In this example, I will use two Azure Automation Accounts.

  • The first one will hold the “Sync Runbook.” It simply syncs my Visual Studio Team Services (VSTS) Git repository to my second Automation Account. We’ll call this the Sync Automation Account.
  • The second one will hold the runbooks that manage the subscription. We’ll call this the Manager Automation Account.

[click to continue…]

0 comments

Infamous “Object reference not set to an instance of an object” for Azure Disk Encryption

Azure Infrastructure

I’m working on encrypting RedHat 7.2 VM using Managed Disks. Keep in mind, to work with Managed Disks in PowerShell, you should upgrade to the latest AzureRM module (version 3.7.0 as of this writing). The command to start the encryption process is the same for Windows as it is for Linux:

?View Code POWERSHELL
1
2
3
Set-AzureRmVMDiskEncryptionExtension -ResourceGroupName $resourceGroupName -VMName $vmNameForEncryption `
-AadClientID $aadClientID -AadClientSecret $aadClientSecret -DiskEncryptionKeyVaultUrl $diskEncryptionKeyVaultUrl `
-DiskEncryptionKeyVaultId $keyVaultResourceId -VolumeType OS

However, when executing this command for a Linux VM which uses Managed Disks, it fails:

?View Code POWERSHELL
1
2
3
4
Set-AzureRmVMDiskEncryptionExtension : Object reference not set to an instance of an object.
At line:1 char:1
+ Set-AzureRmVMDiskEncryptionExtension -ResourceGroupName $resourceGrou ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[click to continue…]

0 comments

Automatic Static IP Addresses for Azure VMs

Azure Infrastructure

EDIT: Updated the hyperlink to GitHub, this is now published here: https://github.com/Azure/azure-quickstart-templates/tree/master/101-vm-automatic-static-ip

During a recent project, I had a need to use only static IP addresses for my virtual machines. However, having to look up the next available IP address seemed counter-intuitive.

What’s the problem anyway

For systems that require a static IP addresses (like Active Directory), or systems that rely on external (non-self-updating) DNS, the default behavior in Azure is problematic because by default a dynamic private IP address is assigned. You can absolutely assign a static IP address by specifying it in your Azure Resource Manager (ARM) template or PowerShell script:

{
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Static",
              "privateIPAddress": "192.168.0.4"

However, there are a couple of issues with this:

1. I need to know the IP address ahead of time. Unlike the ASM model where we had Test-AzureStaticVNetIP cmdlet, we don’t have an ARM equivalent.

2. Azure’s DHCP system isn’t always aware that this IP address is taken.

What’s the solution

I’m going to detail one approach, the one I have used to solve this and would be happy to hear about other approaches to this. What we can do is let the Azure Virtual Network’s DHCP system allocate the IP address and then switch it over to a static IP. This is simple to do from the Azure portal as shown in several articles such as this one. However, we need a more automated approach. By using linked templates, we can create a Network Interface Card (NIC) with a dynamic IP address and then update that NIC with its own IP address, setting it to static.

The ARM template to create the NIC will look as follows:

 

    {
      "apiVersion": "2015-06-15",
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[variables(‘nicName’)]",
      "location": "[resourceGroup().location]",
      "dependsOn": [
        "[concat(‘Microsoft.Network/virtualNetworks/’, variables(‘virtualNetworkName’))]"
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Dynamic",
              "subnet": {
                "id": "[variables(‘SubnetRef’)]"
              }
            }
          }
        ]
      }
    },
{
      "type": "Microsoft.Resources/deployments",
      "name": "[concat(‘updateip’)]",
      "apiVersion": "2015-01-01",
      "dependsOn": [
        "[concat(‘Microsoft.Network/networkInterfaces/’, variables(‘nicName’))]"
      ],
      "properties": {
        "mode": "Incremental",
        "templateLink": {
          "uri": "[variables(‘updateip_templateUri’)]",
          "contentVersion": "1.0.0.0"
        },
        "parameters": {
          "nicName": {
            "value": "[variables(‘nicName’)]"
          },
          "SubnetRef": {
            "value": "[variables(‘SubnetRef’)]"
          },
          "privateIp": {
            "value": "[reference(concat(‘Microsoft.Network/networkInterfaces/’, variables(‘nicName’))).ipConfigurations[0].properties.privateIPAddress]"
          }
        }
      }
    }
  ],
  "outputs": {
    "privateIp": {
        "type": "string",
        "value": "[reference(variables(‘nicName’)).ipConfigurations[0].properties.privateIPAddress]"
    }
  }

 

I’m showing two resources. First the NIC and it’s being created as your normally would with a dynamic IP address. The other resource is a deployment (linked template) that is dependent on creation of the NIC. In this resource we are passing a private IP address as the parameter. The value of this parameter is coming from the existing NIC resource. The linked template is simply specifying the creation of the NIC again, but with a static IP. Here’s how that looks:

 

    {
      "type": "Microsoft.Network/networkInterfaces",
      "name": "[parameters(‘nicName’)]",
      "apiVersion": "2015-06-15",
      "location": "[resourceGroup().location]",
      "tags": {
        "Role": "Web Server"
      },
      "dependsOn": [
      ],
      "properties": {
        "ipConfigurations": [
          {
            "name": "ipconfig1",
            "properties": {
              "privateIPAllocationMethod": "Static",
              "privateIPAddress": "[parameters(‘privateIp’)]",
              "subnet": {
                "id": "[parameters(‘SubnetRef’)]"
              }
            }
          }
        ]
      }
    }

Note that we are using “Static” allocation and specifying the parameter for the privateIPAddress. When called, this template is overwriting the original NIC properties and we can include other items such as tags.

Try it out

The complete example is available on GitHub. Please note, you will need to customize the parameters and also update the location of the linked template (it currently points to a non-existent location). For example, you could update it to point directly to my GitHub repository or use your own storage account.

0 comments

Profile Import fails when running Central Administration over ssl

SharePoint

I’m documenting this issue I discovered last week because I haven’t seen it mentioned elsewhere.

The issue occurs only when using the new SharePoint Active Directory Import in SharePoint 2013 when your Central Administration site is running over SSL. When you first setup your profile sync, you have three choices under “Configure Synchronization Settings”:

  1. Use SharePoint Profile Synchronization (This one leverages the built-in FIM)
  2. Use SharePoint Active Directory Import (This is the direct AD Import)
  3. Enable External Identity Provider

 

I haven’t tested with #1 and #3 so this issue may not apply to those. I originally configured Central Administration to run over port 443 (the default SSL port) and my IIS bindings only have the “https” type installed. By selecting my certificate in IIS, it gives me the proper host header: https://spadmin.mynetwork.com.

I did test using alternate ports without success. When using http, any port will work, whether you use the default port 80 or some other port like 8888. I’d like to mention if everything is setup correctly and working, Spence Harbar (@harbars) has a great blog post which explains how to set this up: http://www.harbar.net/archive/2012/07/23/sp13adi.aspx. Refer to that post to see how good ULS logs look. What if you have a similar configuration to the one I have?

You’ll see something like this first:

CreateProfileImportExportId: Could not InitializeProfileImportExportProcess for end point 'direct://spadmin.mynetwork.com:443/_vti_bin/profileimportexportservice.asmx?ApplicationID=03063851-9e17-4f94-8db6-a71f7b967bd3', retries left '0': Exception 0

And then:

ActiveDirectory Import failed for ConnectionForectName 'mynetwork.com', ConnectionSynchronizationOU 'DC=mynetwork,DC=com', ConnectionUserName 'mynetwork\spupssync'. Error message: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Microsoft.Office.Server.UserProfiles.UserProfileApplicationNotAvailableException: No User Profile Application 

The Workaround

As far as I know, there is no true fix, its a bug. I hope this will be addressed by an update. To get this working you must use a non-SSL Central Administration. However, as a workaround, you can put a load balancer in front of  Central Administration so that client to server communications are encrypted but they’re unencrypted from the load balancer to Central Administration.

0 comments
%d bloggers like this: