MARS 20

ARM - Provisionnez un Azure Automation avec un RunAsAccount

Lorsque vous voulez utiliser Azure Automation pour gérer vos ressources Azure, vous devez créer un Service Principal qui vous servira de RunAsAccount. Il est possible de faire cela via le portail Azure, et cela vous créera un compte qui ressemble à celui là.

image

Si vous avez une convention de nommage, le nom de l’application : reference-aa_5cz2xH6ut6qwABcMDEIfJNCdFX2GZIDGHNrMbVunQAY= ne vous convient sûrement pas, ça tombe bien moi non plus.

Pour cela, il faut précréer votre Service principal avant de créer votre compte Automation via un template ARM dans mon cas. Le compte doit respecter les éléments suivants :

  • Avoir un joli nom qui répond à vos contraintes de naming : pretty-app
  • Une HomePage Url correspondant à l’url de votre service sur Azure : https://management.azure.com//subscriptions/##SUBSCRIPTION_ID##/resourceGroups/aa/providers/Microsoft.Automation/automationAccounts/sample-aa
  • Un certificat à renseigner en tant que secret de votre application.

Donner des droits à ce compte sur la souscription Azure que vous souhaitez afin de pouvoir valider le bon fonctionnement de votre compte Applicatif.

Maintenant, passons à notre template ARM, qui est le suivant :

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {},
    "variables": {
        "aa-appId": "##_APPLICATION_ID_##",
        "aa-tenantId": "##_TENANT_ID_##",
        "aa-certBase64Value": "##_CERTIFICATE_VALUE_BASE64_##",
        "aa-certThumbprint": "##_CERTIFICATE_THUMBPRINT_##",
        "aa-subId": "##_SUBSCRIPTION_ID_##"
    },
    "resources": [
        {
            "type": "Microsoft.Automation/automationAccounts",
            "apiVersion": "2015-10-31",
            "name": "sample-aa",
            "location": "[resourceGroup().location]",
            "properties": {
                "sku": {
                    "name": "Free"
                }
            },
            "resources": [
                {
                    "name": "AzureRunAsCertificate",
                    "type": "certificates",
                    "apiVersion": "2015-10-31",
                    "dependsOn": [
                        "sample-aa"
                    ],
                    "properties": {
                        "base64Value": "[variables('aa-certBase64Value')]"
                    }
                },
                {
                    "name": "AzureRunAsConnection",
                    "type": "connections",
                    "dependsOn": [
                        "sample-aa",
                        "AzureRunAsCertificate"
                    ],
                    "apiVersion": "2015-10-31",
                    "properties": {
                        "connectionType": {
                            "name": "AzureServicePrincipal"
                        },
                        "fieldDefinitionValues": {
                            "ApplicationId": "[variables('aa-appId')]",
                            "TenantId": "[variables('aa-tenantId')]",
                            "CertificateThumbprint": "[variables('aa-certThumbprint')]",
                            "SubscriptionId": "[variables('aa-subId')]"
                        }
                    }
                }
            ]
        }
    ],
    "outputs": {}
}

Si on détaille un peu on retrouve ici notre account automation :

{
    "type": "Microsoft.Automation/automationAccounts",
    "apiVersion": "2015-10-31",
    "name": "sample-aa",
    "location": "[resourceGroup().location]",
    "properties": {
        "sku": {
            "name": "Free"
        }
    }
}

Maintenant on ajoute le certificat qui sert à nous identifier avec notre service principal

{
    "name": "AzureRunAsCertificate",
    "type": "certificates",
    "apiVersion": "2015-10-31",
    "dependsOn": [
        "sample-aa"
    ],
    "properties": {
        "base64Value": "[variables('aa-certBase64Value')]"
    }
}

Et pour finir, il faut créer le compte dans Azure Automation

{
    "name": "AzureRunAsConnection",
    "type": "connections",
    "dependsOn": [
        "sample-aa",
        "AzureRunAsCertificate"
    ],
    "apiVersion": "2015-10-31",
    "properties": {
        "connectionType": {
            "name": "AzureServicePrincipal"
        },
        "fieldDefinitionValues": {
            "ApplicationId": "[variables('aa-appId')]",
            "TenantId": "[variables('aa-tenantId')]",
            "CertificateThumbprint": "[variables('aa-certThumbprint')]",
            "SubscriptionId": "[variables('aa-subId')]"
        }
    }
}

Et voilà, vous pouvez maintenant utiliser un Azure Automation avec un RunAsAccount qui respecte votre règle de nommage.


MARS 13

Powershell - Astuces avec le module Az pour les Storage Account

Vous n’êtes pas sans savoir que Microsoft a mis à jour son module Powershell AzureRM par Az. Ce module a l’usage a pour principale modification de remplacer vos commandes AzureRM par Az comme on peut le voir ci-dessous :

Connect-AzureRMAccount

Connect-AzAccount

Techniquement pour les migrations de vos scripts c’est assez simple à mettre en oeuvre, donc n’hésitez pas à migrer !

Par ailleurs, le module Az apporte quelques nouveautés plutôt cools notamment pour le Storage. J’avais publié différents articles sur le support de RBAC pour accéder aux data du blob storage :

Et bien maintenant il y a une nouvelle solution, vous pouvez le faire via le module Powershell via les commandes suivantes

Connect-AzAccount # Via un Service Principal ou non

New-AzStorageContext -StorageAccountName $storageDestinationName -UseConnectedAccount

Et voilà comment passer un token AD sans avoir à écrire 30 lignes de powershell. A noter qu’il existe aussi une fonctionnalité similaire pour vos comptes de Storage de dev local

New-AzStorageContext -Local

Et dans une moindre mesure, il est possible de se connecter à un storage de manière anonyme, même si dans ce cas précis, je ne vois pas l’avantage par rapport à des appels REST standards.

New-AzStorageAccount -StorageAccountName $storageDestinationName -Anonymous

Mais bon l’option existe donc si vous voulez l’utiliser, allez-y.


MARS 11

ARM - Nouveautés mars 2019

Un petit article pour vous faire part des nouveautés disponibles sur ARM que je trouve vraiment cool, et surtout que j’attendais particulièrement.

Possibilité d’ajouter un paramètre avec la date currente.

"parameters": {
    "time": {
        "type": "string",
        "defaultValue": "[utcNow()]",
        "metadata": {
            "description": "This returns the current UTC time of deployment. This function may only be used in the defaultValue of a parameter."
        }
    },
    "date": {
        "type": "string",
        "defaultValue": "[utcNow('dd-MM-yy')]",
        "metadata": {
            "description": "Standard dateTime format strings are supported: https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings"
        }
    }   
}

A noter que celui-ci ne marche que dans l’objet paramètre et non pas dans la partie variable. Du coup il est maintenant possible d’ajouter la date de création de vos ressources dans vos tags.

Il est maintenant possible d’ajouter un peu d’aléa grâce à la génération de guid dans vos templates

"parameters": {
    "guid": {
        "type": "string",
        "defaultValue": "[newGuid()]",
        "metadata": {
            "description": "This will generate a new GUID each time this template is deployed. This function may only be used in the defaultValue of a parameter."
        }
    },
    "trulyUnique": {
        "type": "string",
        "defaultValue": "[uniqueString(newGuid())]",
        "metadata": {
            "description": "This will generate a new uniqueString() each time this template is deployed. This is not idempotent, use with care."
        }
    },
    "trulyUniqueGuid": {
        "type": "string",
        "defaultValue": "[guid(newGuid())]",
        "metadata": {
            "description": "This will generate a new guid each time this template is deployed. The guid() function can be idempotent, used this way it is not."
        }
    }
}

Voilà il y a aussi d’autres nouveautés liées à ARM, je vous laisse aller voir le blog dédié à celles-ci: https://azure.microsoft.com/en-us/updates/azure-resource-manager-template-language-additions/


FEVR 06

ARM - Rejoindre un domaine Active Directory avec prestaging

Créer des machines virtuelles sur Azure est plutôt simple. Cela se corse lorsque vous voulez les créer avec diverses règles de sécurité “built-in”.

Par exemple, dans mon cas, je souhaite associer ma VM fraichement créée à un active directory on premise (connecté via un Express Route) dans une OU spécifique avec l’obligation de faire du préstaging de machine dans mon OU.

Pour cela j’ai utiisé l’extension JsonADDomainExtension fournie par Microsoft qui est présente dans les QuickStart ARM https://github.com/Azure/azure-quickstart-templates/tree/master/201-vm-domain-join-existing.

Cet exemple est parfait pour créer une nouvelle VM dans mon OU. Le prestaging demande un peu plus d’exploration, en effet tout se base sur la variable domainJoinOptions qui est fixée à 3. Si vous faîtes une recherche sur votre moteur préférée vous allez trouver des notions de magic number 3 ce qui ne va pas vous aider.

En allant plus loin vous allez tomber sur cette documentation qui vous liste les différentes options : https://docs.microsoft.com/en-us/windows/desktop/api/lmjoin/nf-lmjoin-netjoindomain

Celle qui nous intéresse dans ce cas précis est l’option 20 :

  • NETSETUP_DOMAIN_JOIN_IF_JOINED
  • 0x00000020
  • Allows a join to a new domain even if the computer is already joined to a domain.

Du coup cela me donne en ARM le code suivant :

{
    "name": "[concat(parameters('vmName'),'/', 'JoinADDomain')]",
    "apiVersion": "2015-06-15",
    "type": "Microsoft.Compute/virtualMachines/extensions",
    "location": "[variables('location')]",
    "tags": "[variables('consolidateTags')]",
    "condition": "[parameters('joinActiveDirectory')]",
    "dependsOn": [
        "[concat('Microsoft.Compute/virtualMachines/', parameters('vmName'), '/extensions/AzureDiskEncryption')]"
    ],
    "properties": {
        "publisher": "Microsoft.Compute",
        "type": "JsonADDomainExtension",
        "typeHandlerVersion": "1.3",
        "autoUpgradeMinorVersion": true,
        "settings": {
            "Name": "[parameters('domainActiveDirectory')]",
            "User": "[parameters('domainOperator')]",
            "Restart": "true",
            "Options": "20",
            "OUPath": "[parameters('domainOUPath')]"
        },
        "protectedSettings": {
            "Password": "[parameters('domainOperatorPassword')]"
        }
    }
}

JANV 15

Verrouillez vos ressources via ARM

Verrouiller ses ressources sur Azure est un moyen simple de s’affranchir d’erreurs d’inattention. Il existe plusieurs types de verrous que l’on peut poser sur Azure qui sont les suivants :

  • ReadOnly
  • CanNotDelete

Il est possible de les mettre soit sur chacune de vos ressources, sur les groupes de ressources ou alors sur votre souscription.

Maintenant voyons comment faire cela en ARM.

Verrouiller une ressource

{
    "type": "Microsoft.Network/virtualNetworks/providers/locks",
    "apiVersion": "2016-09-01",
    "name": "[concat('VirtualNetwork1', '/Microsoft.Authorization/vnetLock')]",
    "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks', 'VirtualNetwork1')]"
    ],
    "properties": {
        "level": "CanNotDelete",
        "notes": "VNET can not delete"
    }
}

Cette partie de template ARM contient les éléments suivants :

  • Type : Type de la ressource suivi de /providers/locks
  • Name : Nom de la ressource suivi de /Microsoft.Authorization/ puis le nom du Lock

Verrouiller un groupe de resource

{
    "type": "Microsoft.Authorization/locks",
    "apiVersion": "2016-09-01",
    "name": "rgLock",
    "dependsOn": [
        "[resourceId('Microsoft.Network/virtualNetworks', 'VirtualNetwork1')]"
    ],
    "properties": {
        "level": "CanNotDelete",
        "notes": "RG can not delete"
    }
}

Cette partie de template est utilisable via la commande New-AzureRmResourceGroupDeployment. Bien entendu faites bien attention aux dépendances, surtout si vous mettez un level à ReadOnly

Verrouiller une souscription

{
    "type": "Microsoft.Authorization/locks",
    "apiVersion": "2016-09-01",
    "name": "subLock",
    "properties": {
        "level": "CanNotDelete",
        "notes": "sub can not delete"
    }
}

Cette partie de template est utilisable via la commande New-AzureRmDeployment uniquement.