179 строки
8.4 KiB
YAML
179 строки
8.4 KiB
YAML
name: 'IaC Deploy CARML based AKS Cluster'
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
ENVIRONMENT:
|
|
description: 'A GitHub Environment to pull action secrets from'
|
|
required: true
|
|
type: environment
|
|
REGION:
|
|
description: 'The Azure region to deploy to'
|
|
required: true
|
|
default: westus2
|
|
clusterAdminAadGroupObjectId:
|
|
description: 'K8S Admin Azure AAD Group ObjectID'
|
|
required: true
|
|
type: string
|
|
a0008NamespaceReaderAadGroupObjectId:
|
|
description: 'K8S Reader Azure AAD Group ObjectID'
|
|
required: true
|
|
type: string
|
|
|
|
env:
|
|
event_sha: +refs/pull/${{ github.event.issue.number }}/merge
|
|
|
|
permissions:
|
|
id-token: write
|
|
contents: read
|
|
|
|
jobs:
|
|
prereqs:
|
|
runs-on: ubuntu-latest
|
|
environment: ${{ github.event.inputs.ENVIRONMENT }}
|
|
name: Prerequisite Checks
|
|
steps:
|
|
- name: "Checkout"
|
|
uses: actions/checkout@v2
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: "Parameter Check"
|
|
run: |
|
|
echo "Environment : ${{ github.event.inputs.ENVIRONMENT }}"
|
|
echo "REGION : ${{ github.event.inputs.REGION }}"
|
|
|
|
- name: Azure Login
|
|
uses: Azure/login@v1.4.3
|
|
with:
|
|
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
|
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
|
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
|
|
|
- name: "Check Preview Features"
|
|
shell: pwsh
|
|
run: |
|
|
write-output "Verifying required Resource Providers Features are registered"
|
|
$aksfeatures = az feature list --query "[?contains(name, 'Microsoft.ContainerService')]" | ConvertFrom-Json
|
|
|
|
$featureName='AKS-ExtensionManager'
|
|
write-output "-- $featureName"
|
|
$feature = $aksfeatures | Where-Object {$_.name -like "*$featureName"}
|
|
$feature.properties.state
|
|
if ($feature.properties.state -ne 'Registered') {
|
|
Write-Output $feature
|
|
Write-Error "$featureName NOT registered"
|
|
}
|
|
|
|
$featureName='EnableOIDCIssuerPreview'
|
|
write-output "-- $featureName"
|
|
$feature = $aksfeatures | Where-Object {$_.name -like "*$featureName"}
|
|
$feature.properties.state
|
|
if ($feature.properties.state -ne 'Registered') {
|
|
Write-Output $feature
|
|
Write-Error "$featureName NOT registered"
|
|
}
|
|
|
|
$featureName='AKS-AzureDefender'
|
|
write-output "-- $featureName"
|
|
$feature = $aksfeatures | Where-Object {$_.name -like "*$featureName"}
|
|
$feature.properties.state
|
|
if ($feature.properties.state -ne 'Registered') {
|
|
Write-Output $feature
|
|
Write-Error "$featureName NOT registered"
|
|
}
|
|
|
|
deployment:
|
|
runs-on: ubuntu-latest
|
|
environment: ${{ github.event.inputs.ENVIRONMENT }}
|
|
name: Deployment
|
|
needs: [prereqs]
|
|
steps:
|
|
- name: "Checkout"
|
|
uses: actions/checkout@v2
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
# This step is just used for convenience as you won't be using self-signed certificate in your production environment.
|
|
# The certificate used in your environment will likely be generated and imported into KeyVault by your security team
|
|
- name: "Cert Generation"
|
|
id: cert
|
|
run: |
|
|
export DOMAIN_NAME_AKS_BASELINE="contoso.com"
|
|
export CN="bicycle"
|
|
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -out appgw.crt -keyout appgw.key -subj "/CN=${CN}.${DOMAIN_NAME_AKS_BASELINE}/O=Contoso Bicycle" -addext "subjectAltName = DNS:${CN}.${DOMAIN_NAME_AKS_BASELINE}" -addext "keyUsage = digitalSignature" -addext "extendedKeyUsage = serverAuth"
|
|
openssl pkcs12 -export -out appgw.pfx -in appgw.crt -inkey appgw.key -passout pass:
|
|
export APP_GATEWAY_LISTENER_CERTIFICATE_AKS_BASELINE=$(cat appgw.pfx | base64 | tr -d '\n')
|
|
echo "APP_GATEWAY_LISTENER_CERTIFICATE=$APP_GATEWAY_LISTENER_CERTIFICATE_AKS_BASELINE" >> $GITHUB_ENV
|
|
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -out traefik-ingress-internal-aks-ingress-tls.crt -keyout traefik-ingress-internal-aks-ingress-tls.key -subj "/CN=*.aks-ingress.${DOMAIN_NAME_AKS_BASELINE}/O=Contoso AKS Ingress"
|
|
export AKS_INGRESS_CONTROLLER_CERTIFICATE_BASE64_AKS_BASELINE=$(cat traefik-ingress-internal-aks-ingress-tls.crt | base64 | tr -d '\n')
|
|
echo "AKS_INGRESS_CONTROLLER_CERTIFICATE=$AKS_INGRESS_CONTROLLER_CERTIFICATE_BASE64_AKS_BASELINE" >> $GITHUB_ENV
|
|
|
|
- name: Azure Login
|
|
uses: Azure/login@v1.4.3
|
|
with:
|
|
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
|
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
|
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
|
|
|
- name: "Deploy AKS Landingzone"
|
|
id: akslz
|
|
uses: azure/arm-deploy@v1
|
|
with:
|
|
subscriptionId: ${{ secrets.SUBSCRIPTION_ID }}
|
|
region: ${{ github.event.inputs.REGION }}
|
|
scope: subscription
|
|
template: ./IaC/bicep/main.bicep
|
|
parameters: ./IaC/bicep/main.parameters.json clusterAdminAadGroupObjectId=${{ github.event.inputs.clusterAdminAadGroupObjectId }} a0008NamespaceReaderAadGroupObjectId=${{ github.event.inputs.a0008NamespaceReaderAadGroupObjectId }} appGatewayListenerCertificate=${{ env.APP_GATEWAY_LISTENER_CERTIFICATE }} aksIngressControllerCertificate=${{ env.AKS_INGRESS_CONTROLLER_CERTIFICATE }}
|
|
failOnStdErr: false
|
|
deploymentName: carml-aks-landingzone-${{ github.event.inputs.REGION }}
|
|
|
|
# Import core images hosted in public container registries to be used during bootstrapping
|
|
- name: "Import Images into ACR for flux"
|
|
id: image_import
|
|
run: |
|
|
az acr import --source docker.io/weaveworks/kured:1.10.1 -n ${{ steps.akslz.outputs.containerRegistryName }} --force
|
|
az acr import --source docker.io/library/traefik:v2.8.1 -n ${{ steps.akslz.outputs.containerRegistryName }} --force
|
|
|
|
# Temporary workaround until we figure out why steps.cluster.outputs.keyVaultName is blank
|
|
- name: "Get KeyVault Name"
|
|
id: akv_name
|
|
run: |
|
|
export AKV_NAME=$(az keyvault list -g rg-bu0001a0008 -o table | grep "kv-aks" | awk '{print $2}')
|
|
echo "AKV_NAME=${AKV_NAME}" >> $GITHUB_ENV
|
|
echo "AKV Name from bicep output is ${{ steps.akslz.outputs.keyVaultName }}"
|
|
echo "aksIngressControllerPodManagedIdentityResourceId from bicep output is ${{ steps.akslz.outputs.aksIngressControllerPodManagedIdentityResourceId }}"
|
|
echo "To prove that this should work: hubVnetId is ${{ steps.akslz.outputs.hubVnetId }}"
|
|
|
|
# Re-authentication is required for the commands that follow
|
|
- name: Azure Login
|
|
uses: Azure/login@v1.4.3
|
|
with:
|
|
client-id: ${{ secrets.AZURE_CLIENT_ID }}
|
|
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
|
|
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
|
|
|
|
# This step is just used for convenience as the certificate used in your environment will likely be generated and imported into KeyVault by your security team
|
|
# This step imports into KeyVault the same backend cert that was generated above for the App Gateway. This cert will be used by the Ingress Controller Traefik.
|
|
- name: "Cert Import into Key Vault for Traefik"
|
|
id: cert_import
|
|
run: |
|
|
ASSIGNEE_OBJ_ID=$(az ad sp show --id ${{ secrets.AZURE_CLIENT_ID }} --query id -o tsv)
|
|
AKV_RESOURCE_ID=$(az keyvault show -n ${{ env.AKV_NAME }} --query id -o tsv)
|
|
TEMP_ROLEASSIGNMENT_TO_UPLOAD_CERT=$(az role assignment create --role a4417e6f-fecd-4de8-b567-7b0420556985 --assignee-principal-type serviceprincipal --assignee-object-id $ASSIGNEE_OBJ_ID --scope $AKV_RESOURCE_ID | jq '.id' )
|
|
|
|
sleep 60
|
|
|
|
CURRENT_IP_ADDRESS=$(curl -s -4 https://ifconfig.io)
|
|
az keyvault network-rule add -n ${{ env.AKV_NAME }} --ip-address ${CURRENT_IP_ADDRESS}
|
|
|
|
sleep 30
|
|
|
|
cat traefik-ingress-internal-aks-ingress-tls.crt traefik-ingress-internal-aks-ingress-tls.key > traefik-ingress-internal-aks-ingress-tls.pem
|
|
az keyvault certificate import -f traefik-ingress-internal-aks-ingress-tls.pem -n traefik-ingress-internal-aks-ingress-tls --vault-name ${{ env.AKV_NAME }}
|
|
|
|
az keyvault network-rule remove -n ${{ env.AKV_NAME }} --ip-address ${CURRENT_IP_ADDRESS}
|
|
az role assignment delete --role a4417e6f-fecd-4de8-b567-7b0420556985 --assignee $ASSIGNEE_OBJ_ID --scope $AKV_RESOURCE_ID
|
|
|
|
|