Skip to content

Commit d5784a3

Browse files
committed
Add a user and rg to box in ASO
1 parent 6a9a405 commit d5784a3

File tree

5 files changed

+120
-16
lines changed

5 files changed

+120
-16
lines changed

Cluster.bicep

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,28 @@ module iam_flux_crypto 'modules/resourceRoleAssignment.bicep' = {
381381
}
382382
}
383383

384+
// module rg 'modules/resourceGroup.bicep' = {
385+
// scope: subscription()
386+
// params: {
387+
// name: '${resourceGroup().name}-aso'
388+
// location: location
389+
// tags: tags
390+
// }
391+
// }
392+
393+
module aso 'modules/azureServiceOperator.bicep' = {
394+
name: '${deploymentName}_aso'
395+
scope: resourceGroup('${resourceGroup().name}-aso')
396+
params: {
397+
deploymentNamePrefix: take(deploymentName, 47)
398+
baseName: 'aso'
399+
location: location
400+
tags: tags
401+
oidcIssuerUrl: aks.outputs.oidcIssuerUrl
402+
}
403+
}
404+
405+
384406
// @description('Flux release namespace')
385407
// output fluxReleaseNamespace string = flux.outputs.fluxReleaseNamespace
386408

Initialize-Azure.ps1

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ param(
2323
)
2424

2525
# The resource group to create. E.g. "rg-cluster"
26-
$resourceGroupName = "rg-${BaseName}"
26+
$resourceGroupName = @(
27+
# The first one should be the one where the cluster will be deployed
28+
"rg-${BaseName}"
29+
"rg-${BaseName}-aso"
30+
)
2731

2832
# The service name to use. E.g. "rg-cluster-deploy"
2933
$serviceName = "rg-${BaseName}-deploy"
@@ -46,20 +50,24 @@ foreach ($feature in "FluxConfigurations") {
4650
}
4751

4852

53+
$app = (Get-AzADApplication -DisplayName $serviceName) ??
54+
(New-AzADApplication -DisplayName $serviceName)
55+
$service = (Get-AzADServicePrincipal -ApplicationId $app.AppId) ??
56+
(New-AzADServicePrincipal -ApplicationId $app.AppId)
57+
4958
# Create resource group
50-
New-AzResourceGroup -Name $resourceGroupName -Location $location -Force -Tag @{
51-
Repository = $Repository;
52-
Purpose = "aks";
53-
Created = Get-Date -Format "O"
59+
foreach ($name in $resourceGroupName) {
60+
(Get-AzResourceGroup -Name $name -ErrorAction SilentlyContinue) ??
61+
(New-AzResourceGroup -Name $name -Location $location -Force -Tag @{
62+
Repository = $Repository;
63+
Purpose = "aks";
64+
Created = Get-Date -Format "O"
65+
})
66+
$role = (Get-AzRoleAssignment -ResourceGroupName $name -RoleDefinitionName Owner -ObjectId $service.Id) ??
67+
(New-AzRoleAssignment -ResourceGroupName $name -RoleDefinitionName Owner -ObjectId $service.Id)
5468
}
5569

56-
$app = (Get-AzADApplication -DisplayName $serviceName) ??
57-
(New-AzADApplication -DisplayName $serviceName)
58-
$service = (Get-AzADServicePrincipal -ApplicationId $app.AppId) ??
59-
(New-AzADServicePrincipal -ApplicationId $app.AppId)
60-
$role = (Get-AzRoleAssignment -ResourceGroupName $resourceGroupName -RoleDefinitionName Owner -ObjectId $service.Id) ??
61-
(New-AzRoleAssignment -ResourceGroupName $resourceGroupName -RoleDefinitionName Owner -ObjectId $service.Id)
62-
$fedcred = (Get-AzADAppFederatedCredential -ApplicationObjectId $app.id -Filter "Subject eq 'repo:${Repository}:ref:refs/heads/main'" -ErrorAction SilentlyContinue) ??
70+
$fedcred = (Get-AzADAppFederatedCredential -ApplicationObjectId $app.id -Filter "Subject eq 'repo:${Repository}:ref:refs/heads/main'" -ErrorAction SilentlyContinue) ??
6371
(New-AzADAppFederatedCredential -ApplicationObjectId $app.Id -Audience "api://AzureADTokenExchange" -Issuer "https://token.actions.githubusercontent.com" -Subject "repo:${Repository}:ref:refs/heads/main" -Name "$($Repository -replace '/','-')-main-gh")
6472

6573
$ctx = Get-AzContext
@@ -68,7 +76,7 @@ $ctx = Get-AzContext
6876
gh secret set --repo https://github.com/$Repository AZURE_CLIENT_ID -b $app.AppId
6977
gh secret set --repo https://github.com/$Repository AZURE_TENANT_ID -b $ctx.Tenant
7078
gh secret set --repo https://github.com/$Repository AZURE_SUBSCRIPTION_ID -b $ctx.Subscription.Id
71-
gh secret set --repo https://github.com/$Repository AZURE_RG -b $resourceGroupName
79+
gh secret set --repo https://github.com/$Repository AZURE_RG -b $resourceGroupName[0]
7280
# gh secret set --repo https://github.com/$Repository USER_OBJECT_ID -b $spId
7381

7482
# Create an AD Group to be administrators of the cluster:

README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,28 @@ I've written my own templates for deploying AKS in [Azure Bicep](https://docs.mi
66

77
## Azure Prerequisites
88

9-
These pre-requisites are not part of the CI/CD build, because they only have to be done once, but the [Initialize-Azure](./Initialize-Azure.ps1) script is essentially idempotent and re-runnable.
9+
These pre-requisites are not part of the CI/CD build, because they only have to be done once, but the [`Initialize-Azure`](./Initialize-Azure.ps1) script is essentially idempotent and re-runnable.
1010

1111
1. Enable some features in your Azure tenant (some of which are pre-release features as of this writing)
12-
2. Create a resource group in Azure to deploy to
12+
2. Create a resource group in Azure to deploy to (currently TWO resource groups, see [Azure Service Operator](#azure-service-operator) below)
1313
3. Create a service account in Azure for automation
1414
4. Assign the "owner" role on the resource group to the service account
1515
5. Create secrets in github for authentication as that service account
1616

1717
The first step, enabling features, only has to be done once per subscription. For best practices, the remaining steps should be done once for each cluster, for security purposes. The idea is that the subscription owner runs this script by hand, and then the automated service account is restricted to deploying to this single resource group.
1818

19-
See [Initialize-Azure](./Initialize-Azure.ps1)` for details. You might call it like this:
19+
See [`Initialize-Azure`](./Initialize-Azure.ps1) for details. You might call it like this:
2020

2121
```PowerShell
2222
./Initialize-Azure -BaseName $name
2323
```
2424

25+
### Azure Service Operator
26+
27+
I'm testing some things with the [Azure Service Operator](https://github.com/Azure/azure-service-operator), and for right now, this bicep creates a third resource group (i.e. if you create 'rg-poshcode' in Azure, AKS will create 'rg-poshcode-aks' and the bicep needs 'rg-poshcode-aso' to _contain_ the operator). That way it's creating a user assigned identity for the [Azure Service Operator](https://github.com/Azure/azure-service-operator) to use which has `Contributor` access just to the -aso resource group.
28+
29+
In order to avoid giving the github service account additional access, I modified the Initialize-Azure PowerShell script instead.
30+
2531
## Deploying Infrastructure
2632

2733
Each time the IAC templates change, we're going to run New-AzResourceGroupDeployment, but we have a [workflow for that](.github/workflows/deploy.yaml), of course.

modules/azureServiceOperator.bicep

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
targetScope = 'resourceGroup'
2+
3+
// *** This template deploys the cluster for poshcode.org. See README.md before making changes ***
4+
@description('Required. The AKS OIDC IssuerUrl')
5+
param oidcIssuerUrl string
6+
7+
@description('Optional. This template deploys the cluster for poshcode.org. See README.md before making changes')
8+
param baseName string = 'aso'
9+
10+
@description('Optional. The location to deploy. Defaults to resourceGroup().location')
11+
param location string = resourceGroup().location
12+
13+
@description('Optional. Tags for the resource. Defaults to resourceGroup().tags')
14+
param tags object = resourceGroup().tags
15+
16+
// 64 is the max deployment name, and the longest name in our sub-deployments is 17 characters, 64-17 = 47
17+
@description('Optional. Provide unique deployment name prefix for the module references. Defaults to take(deploymentName().name, 47)')
18+
@maxLength(47)
19+
param deploymentNamePrefix string = take(deployment().name, 64-17)
20+
21+
22+
module asoId 'userAssignedIdentity.bicep' = {
23+
name: '${deploymentNamePrefix}_uai_asoId'
24+
params: {
25+
baseName: baseName
26+
location: location
27+
tags: tags
28+
federatedIdentitySubjectIssuerDictionary: {
29+
// For creating Azure resources
30+
'system:serviceaccount:azure:operator': oidcIssuerUrl
31+
}
32+
}
33+
}
34+
35+
36+
module iam_azure_owner 'resourceRoleAssignment.bicep' = {
37+
name: '${deploymentNamePrefix}_iam_aso_operator'
38+
params: {
39+
principalIds: [ asoId.outputs.principalId ]
40+
resourceId: asoId.outputs.id
41+
roleName: 'Contributor'
42+
}
43+
}

modules/resourceGroup.bicep

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
targetScope = 'subscription'
2+
3+
@description('Required. The base name of the resource group (will be prefixed with "rg-")')
4+
param name string
5+
6+
@description('The location to deploy')
7+
param location string
8+
9+
@description('Tags for the resource')
10+
param tags object
11+
12+
resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' = {
13+
name: name
14+
location: location
15+
tags: tags
16+
}
17+
18+
@description('The resource ID of the resource group')
19+
output id string = rg.id
20+
21+
@description('The name of the resource group')
22+
output name string = rg.name
23+
24+
@description('The location of the resource group')
25+
output location string = rg.location

0 commit comments

Comments
 (0)