Bare minimum to arrange for building and deploying to Azure with GitLab
Azure Infrastructure-as-code GitLab
Table of contents:
In this short post you’ll find how to prepare your GitLab to deploy to Azure.
Service principal #
Generate Service Principal (aka App Registration) using azure CLI (either builtin shell or local terminal, you must be logged in with Owner
role credentials since we need to assign role to the scope):
1
2az ad sp create-for-rbac --name GitLabServicePrincipalName --role Owner --scopes /
3
4{
5 "appId": "<REDACTED>",
6 "displayName": "GitLabServicePrincipalName",
7 "password": "<REDACTED>",
8 "tenant": "<REDACTED>"
9}
Feel free to change scopes and role (i.e. custom role or subscription scope instead). Learn more how to generate SPN here.
Secrets in GitLab #
Safe appId
, password
, tenant
and subscription ID in GitLab => Settings => CI/CD => Variables (make sure to enable checkbox Mask variable for each secret so the values won’t end up in the logs of the job).
GitLab CI example #
Example of .gitlab-ci.yml
:
1# You can override the included template(s) by including variable overrides
2# SAST customization: https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings
3# Secret Detection customization: https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings
4# Dependency Scanning customization: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings
5# Container Scanning customization: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
6# Note that environment variables can be set in several places
7# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
8include:
9- template: Security/SAST.gitlab-ci.yml
10image: mcr.microsoft.com/azure-cli
11variables:
12 appId: "$appId"
13 password: "$password"
14 tenant: "$tenant"
15 subId: "$subId"
16stages:
17- build
18- test
19- deploy
20build-job:
21 stage: build
22 script:
23 - echo "Building Bicep artifact ... "
24 - az login --service-principal -u $appId -p $password -t $tenant
25 - az account set -s $subId
26 - az group create -g rg-group -l westeurope
27 - az deployment group what-if -g rg-group -f ./bicep/main.bicep
28 - az deployment group validate -g rg-group -f ./bicep/main.bicep
29 artifacts:
30 paths:
31 - bicep
32 expire_in: 1 week
33 only:
34 - dev
35unit-test-job:
36 stage: test
37 script:
38 - echo "Running unit tests... This will take about 60 seconds."
39 - sleep 60
40 - echo "Code coverage is 90%"
41 only:
42 - main
43lint-test-job:
44 stage: test
45 script:
46 - echo "Linting code... This will take about 10 seconds."
47 - sleep 10
48 - echo "No lint issues found."
49 only:
50 - main
51deploy-job:
52 stage: deploy
53 script:
54 - az login --service-principal -u $appId -p $password -t $tenant
55 - az account set -s $subId
56 - az group list
57 - az deployment group create -g rg-group -f ./bicep/main.bicep
58 only:
59 - dev
60sast:
61 stage: test
Few remarks:
- Microsoft offers docker image with latest and greatest Azure CLI;
- Variables are not available automatically after adding them in GUI, we have to assign them to environment variables, that’s why we have
variables
block in the YAML. az account set -s $subId
is used to make sure that the proper target subscription is set for our operations (important in case of multiple subscriptions within tenant).
Feel free to explore this public repo to see the entire example. Structure of the repo is quite simple:
1
2tree
3.
4├── .gitlab-ci.yml <== example of pipeline
5├── README.md
6└── bicep
7 └── main.bicep <== example of template to execute by the pipeline
Until next post! 👋