OCTO 26

Réaliser une copie de vos bases SQL Database

Lorsque vous voulez créer des environnements identiques à un autre, par exemple pour réaliser une copie de votre PROD vers une PPROD, ou mettre en place un environnement de PRA. Le problème se situe au plus souvent de vos données, puisque si je souhaite utiliser un backup et le restore sur une autre base, cela peut prendre beaucoup de temps entre la réalisation du backup et sa restauration.

Sur SQL Database, il est possible de faire une copie de votre base de données vers un autre SQL Database de manière très simple et très rapide en utiliant la commande suivante:

CREATE DATABASE newDestinationDB AS COPY OF sourcedemo.sourcedb;

Cette commande magique a tout de même quelques contraintes : si vous utilisez uniquement des comptes SQL, il faut que le compte que vous utilisez sur les deux servers ait un login et un mot de passe identique. Si vous utilisez un compte provenant d’un Azure Active Directory, vous n’aurez pas de problème car il s’agira du même compte.

Ayant eu à mettre en place ces comptes récemment et n’ayant pas trouvé la doc Azure très limpide à ce sujet, j’ai décidé d’en écrire un article.

Commençons donc par se connecter sur le SQL Server contenant la base de données que l’on souhaite copier.

Créons notre compte de la manière suivante :

CREATE LOGIN backup_sa WITH PASSWORD = 'topsecure42!'

Puis sur la base de données que l’on souhaite copier

CREATE USER backup_sa FROM LOGIN backup_sa
GO
-- role owner sur la base de données que l'on souhaite copier
sp_addrolemember db_owner, backup_sa

En ce qui concerne votre base de données source, vous avez fini votre setup. Maintenant passons à votre serveur cible, celui où vous voulez copier votre base de données.

Créons notre compte de la même manière que précédemment :

CREATE LOGIN backup_sa WITH PASSWORD = 'topsecure42!'

Puis sur la base de données master il faut ajouter notre utilisateur dans le groupe db_manager

CREATE USER backup_sa FROM LOGIN backup_sa
GO
-- role dbmanager sur la base de données que l'on souhaite copier
sp_addrolemember dbmanager, backup_sa

Il est ensuite possible de réaliser votre copie de base de données via la commande suivante :

CREATE DATABASE destinationdb AS COPY OF sourcedemo.sourcedb;

OCTO 19

Container - Héberger vos sites Web

Depuis un moment, l’utilisation des containers est de plus en plus fréquente, mais attention ce n’est pas parce que c’est à la mode qu’il faut les utiliser à tort et à travers.

La plateforme Azure n’est pas indifférente aux containers, et bien heureusement. Il existe plein de manières de mettre en place des containers dans Azure, nous allons donc voir comment les mettre en place et pourquoi utiliser tel ou tel service sur Azure.

Pour commencer, on va prendre le cas d’un container ou d’un ensemble de containers ayant pour but d’afficher un pur site web, car effectivement l’utilisation des containers n’est pas uniquement exclusive aux architectures microservices.

Prenons en premier exemple un site très simple basé sur un container ayant ce docker file :

FROM nginx:alpine
COPY . /usr/share/nginx/html

Bon comme on peut le voir c’est plus dur de faire compliquer. Mais l’image m’offre l’avantage de ne pas avoir à mettre moi-même en place mon NGINX.

Maintenant si je veux mettre en place ce site Web sur Azure, j’ai plein de possibilités comme celle de créer un cluster AKS ou un cluster Service Fabric, mais vous serez d’accord avec moi sur le fait que ça serait sortir le marteau pour tuer une mouche.

Sur le service de Web Apps d’Azure il est possible d’héberger un container qui se situe dans n’importe quel registry accessible depuis ma Web App.

Pour ma part, je vais créer une registry sur Azure via le Service Azure Container Registry

$registry = New-AzureRmContainerRegistry -ResourceGroupName $rgName -Name $acrName -EnableAdminUser -Sku Basic

Puis j’enregitre ces accès dans mon Docker afin de pouvoir publier mes images dessus.

$credentials = Get-AzureRmContainerRegistryCredential -Registry $registry
docker login $registry.LoginServer -u $credentials.Username -p $credentials.Password

Pour ceux qui n’ont jamais utilisé Docker, et pour les autres un rappel ne faisant jamais de mal, voici comment construire notre image et l’envoyer sur une registry distante

docker build -t sample-web-app .\WebApp\
docker tag sample-web-app ($registry.LoginServer + '/sample-web-app:v1')
docker push ($registry.LoginServer + '/sample-web-app:v1')

Maintenant que notre image est sur notre registry Azure, il est possible de la déployer n’importe où que ce soit dans Azure ou ailleurs.

Je vais donc créer une nouvelle Web App sur Azure via le portail, il est bien entendu possible de faire la même chose via un template ARM ou des scripts.

image

Maintenant que mon container est hébergé, il est automatiquement configuré pour être mis à jour à chaque fois que je pousse une nouvelle version de mon image sur ma registry, il est bien entendu possible de désactiver cette fonctionnalité si besoin.

Il est aussi possible d’utiliser des images plus complexes via l’outil docker compose afin d’avoir de multiples containers qui sont exécutés au sein de votre Web App. Voici un exemple de configuration yml que vous pouvez utiliser, c’est celle qui est disponible sur la documentation Azure :

version: '3.3'

services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
volumes:
    db_data:

Comme vous pouvez le voir, il s’agit ici d’un site Wordpress avec sa base de données. Il n’est par ailleurs actuellement pas possible d’utiliser toutes les fonctionnalités de Docker compose au sein de vos Web Apps, du coup vous pouvez oublier ce service si vous voulez vous servir des éléments suivants :

  • build : Non autorisé
  • depends_on : ignoré
  • networks : ignoré
  • secrets : ignoré

Selon moi le support des containers pour les Web App offre une solution idéale pour vos containers légers qui doivent tourner H24, et pour lesquels vous ne voulez pas à avoir à gérer un cluster sous jacent.


OCTO 12

Générer un token Azure AD via les REST API

Dernièrement j’ai eu le besoin d’accéder à un compte de stockage via un compte applicatif, j’ai donc mis en plac un SPN avec un droit RBAC sur mon compte de stockage, comme je le montre dans cet article : http://blog.woivre.fr/blog/2018/09/connectez-vous-a-vos-comptes-de-stockage-via-azure-active-directory

Maintenant il faut que je génère mon token d’accès, chose qui est assez simple avec les différentes librairies ADAL, cependant pour mon besoin j’avais les contraintes suivantes :

  • Compte applicatif avec une authentification par certificat
  • Pas de librairies supplémentaires (adieu ADAL)
  • Powershell

Première étape, il faut générer un token JWT. Pour rappel un token JWT répond à la structure suivante : base64(header).base64(payload).base64(signature)

Commençons par la construction de notre header, pour cela il nous faut le hash de notre certificat, que l’on peut récupérer de la manière suivante :

$cert = Get-Item Cert:\CurrentUser\My\$ThumbprintValue

$hash = $cert.GetCertHash()
$hashValue = [System.Convert]::ToBase64String($hash)  -replace '\+','-' -replace '/','_' -replace '='

Il est maintenant possible de constuire notre header de la manière suivante, ainsi que notre payload :

[hashtable]$header = @{alg = 'RS256'; typ= "JWT"; x5t = $thumprintValue}
[hashtable]$payload = @{aud = "https://login.microsoftonline.com/$TenantUrl/oauth2/token"; iss = $applicationId; sub=$applicationId; jti = "22b3bb26-e046-42df-9c96-65dbd72c1c81"; exp = $exp; nbf= 1536160449}

Maintenant qu’on a toutes les informations, il faut générer notre signature, et construire notre token

$headerjson = $header | ConvertTo-Json -Compress
$payloadjson = $payload | ConvertTo-Json -Compress

$headerjsonbase64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($headerjson)) -replace '\+','-' -replace '/','_' -replace '='
$payloadjsonbase64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($payloadjson)) -replace '\+','-' -replace '/','_' -replace '='

$jwt = $headerjsonbase64 + "." + $payloadjsonbase64
$toSign = [System.Text.Encoding]::UTF8.GetBytes($jwt)

$Signature = [Convert]::ToBase64String($rsa.SignData($toSign,[Security.Cryptography.HashAlgorithmName]::SHA256,[Security.Cryptography.RSASignaturePadding]::Pkcs1)) -replace '\+','-' -replace '/','_' -replace '='

$token = "$headerjsonbase64.$payloadjsonbase64.$Signature"

A noter qu’il est possible de valider la création de votre jeton JWT sur des sites comme celui-ci : https://jwt.io/

Et voilà nous avons notre token JWT qui nous servira à avoir notre access Token qu’on va pouvoir récupérer de la manière suivante:


$url = "https://login.microsoftonline.com/$TenantUrl/oauth2/token"
$body = "resource=https%3A%2F%2F$storageAccountName.blob.core.windows.net%2F&client_id=$applicationId&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=$token&grant_type=client_credentials"
$responseToken = Invoke-WebRequest -Method POST -ContentType "application/x-www-form-urlencoded"  -Headers @{"accept"="application/json"} -Body $body $url -Verbose

$accessToken = ($responseToken.Content | ConvertFrom-Json).access_token

Après avoir générer notre token, il est possible de l’utiliser dans nos headers pour appeler les REST API de notre storage.

$headerSMA =  @{"Authorization" = "Bearer " + $accessToken; "x-ms-version" = "2017-11-09"}
Invoke-WebRequest -Headers $headerSMA -Method GET "https://$storageAccountName.blob.core.windows.net/$containerName/$blobName"  -OutFile $outFile

Et voilà comment appeler des API Azure tout en s’affranchissant d’ADAL. Même si on est d’accord créer notre Token avec ADAL c’est beaucoup plus simple. Et surtout moins long à lire.


OCTO 05

Créer vos groupes de ressources via un template ARM

La création des groupes de ressources se fait généralement par le portail Azure, ou via votre terminal préféré (CLI ou PowerShell). Il est posssible dorénavant de créer vos groupes de ressources via un template ARM.

Prenons un exemple de template ARM pour créer notre resource group :

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {},
    "variables": {
        "location": "West Europe",
        "name": "rg-test"
    },
    "resources": [
        {
            "type": "Microsoft.Resources/resourceGroups",
            "apiVersion": "2018-05-01",
            "location": "[variables('location')]",
            "name": "[variables('name')]",
            "properties": {}
        }
    ],
    "outputs": {}
}

Maintenant pour déployer ce template ARM, il est possible d’utiliser la commande suivante :

New-AzureRmResourceGroupDeployment -Name deploy-rg -TemplateFile .\azuredeploy.json -ResourceGroupName existing-rg

Le problème c’est qu’il faut déjà avoir un resource group dans notre souscription, ce qui n’est pas top pour initier une souscription. Mais depuis peu, il est possible d’utiliser la commande suivante :

New-AzureRmDeployment -Name deploy-rg -TemplateFile .\azuredeploy.json

Il est bien entendu possible de retrouver les déploiements passés via la commande

Get-AzureRmDeployment

Ou alors vous pouvez retrouver vos déploiements dans la blade Souscription dans le portail Azure.

Happy deploy !


SEPT 25

Connectez vous à vos comptes de Stockage via Azure Active Directory

On a vu dans un précédent article comment utiliser le KeyVault pour générer des SAS Keys : http://blog.woivre.fr/blog/2018/09/generer-des-cles-sas-pour-vos-storage-grace-a-keyvault

Dans la même philosophie que ce dernier, il est possible de s’affranchir totalement des clés de Storage dans vos configs ou votre code source, même si j’espère que pour ce dernier c’est déjà le cas.

Certains services sur Azure supportent des rôles RBAC sur les données, comme notamment les Storage Accounts, qui contiennent des droits Reader ou Contributor sur les Blob et les Queues.

Grâce à cela il est possible pour un compte AD spécifique de se connecter à mon Stockage Azure pour récupérer un fichier par exemple.

Les noms des rôles build-in qui existent autour de la donnée sont les suivants :

  • Storage Blob Data Contributor (Preview)
  • Storage Blob Data Reader (Preview)
  • Storage Queue Data Contributor (Preview)
  • Storage Queue Data Reader (Preview)

A noter, qu’il est possible de setup ces différentes permissions via la propriété DataAction dans la définition de vos rôles RBAC

Vu que pour le moment le SDK C# pour le Storage ne supporte pas cette nouvelle fonctionnalité il faut le faire via les API REST Azure, comme ci-dessous :

AuthenticationContext authContext = new AuthenticationContext($"https://login.microsoftonline.com/{TenantId}");
AuthenticationResult authResult = await authContext.AcquireTokenAsync($"https://{StorageAccountName}.blob.core.windows.net/", new ClientCredential(ApplicationId, SecretKey));
	
HttpClient client = new HttpClient(); 
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + authResult.AccessToken);
client.DefaultRequestHeaders.Add("x-ms-version", "2017-11-09");

var response = await client.GetStringAsync($"https://{StorageAccountName}.blob.core.windows.net/{ContainerName}/{BlobName}");	

A noter qu’ici, je génère un token grâce à ADAL et que je demande bien celui-ci pour mon compte de stockage.

Avec cet article, vous avez encore moins d’excuses de conserver vos clés de stockage dans vos configs.