Skip to content

Commit 353e7f6

Browse files
committed
Added a JSON array parameter to the ARM template for additional principals to be granted access to the lab resources
1 parent 9e1347d commit 353e7f6

File tree

3 files changed

+95
-40
lines changed

3 files changed

+95
-40
lines changed

.github/workflows/deploy.sh

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,9 @@ echo "Connection info:"
55
az account show | jq '. | {tenantId: .tenantId, subscriptionName: .name, userName: .user.name, userType: .user.type}'
66
echo
77

8-
echo "Configuring variables for secrets:"
98
echo "========================================================================================================================================================================================================"
10-
echo
11-
12-
# ls -a
13-
14-
15-
# # Can we run a shell script to tidy this up?
16-
# . ./.github/workflows/deploy_dev_test_lab.sh -?
17-
18-
# echo "========================================================================================================================================================================================================"
199

10+
echo "Configuring variables for secrets:"
2011

2112
ARTIFACT_SOURCE_NAME=$(az lab artifact-source list --resource-group $RESOURCE_GROUP \
2213
--lab-name $LAB_NAME \
@@ -39,16 +30,16 @@ echo "Service Principal Object Id: $SERVICEPRINCIPALID"
3930

4031
# Build a JSON snippet with the client/app id, object id and client secret for the devops SPN. This is used by the ARM template to grant permissions on resources so that the devops SPN
4132
# can deploy code into them. The ARM template generates the required .runsettings file for the integration tests as an output, which reuses the devops SPN to access resources to test.
42-
SERVICEPRINCIPALINFO=$( echo $SERVICEPRINCIPALCREDENTIALS | jq '{ tenantId, clientId, clientSecret, $clientObjectId }' --arg 'clientObjectId' $SERVICEPRINCIPALID -c )
43-
44-
echo "Service Principal Info: $SERVICEPRINCIPALINFO"
33+
SERVICE_PRINCIPAL_INFO=$( echo $SERVICE_PRINCIPAL_CREDENTIALS | jq '{ tenantId, clientId, clientSecret, $clientObjectId }' --arg 'clientObjectId' $SERVICEPRINCIPALID -c )
34+
echo "Service Principal Info: $SERVICE_PRINCIPAL_INFO"
4535

4636
echo "Building parameters file for ARM deployment..."
4737
PARAMETERS_FILE="$(pwd)/azuredeploy.parameters.json"
4838
echo $'[ { "name":"branch", "value":"'$BRANCH_NAME'" },' \
4939
' { "name":"commit", "value":"'$GITHUB_SHA'" },' \
5040
' { "name":"location", "value":"UK South" },' \
51-
' { "name":"devopsServicePrincipalCredentials", "value":' $SERVICEPRINCIPALINFO ' }' \
41+
' { "name":"devopsServicePrincipalCredentials", "value":' $SERVICE_PRINCIPAL_INFO ' },' \
42+
' { "name":"additionalPrincipals", "value":' "${ADDITIONAL_PRINCIPALS:=[]}" ' }' \
5243
']' \
5344
| jq '.' > "$PARAMETERS_FILE"
5445
#cat $PARAMETERS_FILE
@@ -84,20 +75,22 @@ echo "::error Error provisioning lab environment"
8475
exit 1
8576
fi
8677

87-
echo "========================================================================================================================================================================================================"
8878
DEPLOYMENTOUTPUT=$(az deployment group list --resource-group $ENVIRONMENT_INSTANCE_RESOURCE_GROUP_NAME --query '[0].properties.outputs')
8979

80+
echo "Setting Job Outputs"
81+
echo "========================================================================================================================================================================================================"
82+
83+
84+
# These don't show in the output, but we can view then in a yaml step as below
85+
# echo "ENVIRONMENT_INSTANCE_NAME: ${{ steps.create-devtest-labs-environment.outputs.ENVIRONMENT_INSTANCE_NAME }}"
86+
9087
# DEBUG: Use this to get the full deployment output JSON. If the ARM template outputs a full reference to a resource, we can find the bits we need easily.
91-
# echo "::set-output name=DEPLOYMENTOUTPUT::$DEPLOYMENTOUTPUT"
88+
#echo "::set-output name=DEPLOYMENTOUTPUT::$DEPLOYMENTOUTPUT"
9289

93-
echo "Deployment Outputs"
94-
#echo "::set-output name=STORAGE_ACCOUNTCONNECTION_STRING::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.storageAccountConnectionString.value')"
9590
echo "::set-output name=STORAGE_ACCOUNT_NAME::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.storageAccountName.value')"
9691
echo "::set-output name=STORAGE_CONTAINER_NAME::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.storageContainerName.value')"
9792
echo "::set-output name=FUNCTIONS_APP_NAME::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.functionsAppName.value')"
9893
echo "::set-output name=FUNCTIONS_APP_URI::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.functionsAppUri.value')"
9994
echo "::set-output name=KEY_VAULT_NAME::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.keyVaultName.value')"
100-
#echo "::set-output name=FUNCTIONS_APP_KEY::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.functionsAppKey.value')"
10195
echo "::set-output name=RUN_SETTINGS::$(echo $DEPLOYMENTOUTPUT | jq --raw-output '.runSettings.value')"
10296

103-
echo "========================================================================================================================================================================================================"

.github/workflows/test_azure_devtest_labs_integration.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ jobs:
7373
# This runs in a container, so all output is passed back using 'echo "::set-output name=OUTPUT_VAR_NAME::value here"', as files created won't persist.
7474
inlineScript: |
7575
# We need the secrets in an environment variable so they get passed to our shell script that does the work
76-
export SERVICEPRINCIPALCREDENTIALS=$'${{ secrets.AZURE_DEV_TEST_LABS_CREDENTIALS }}'
76+
export SERVICE_PRINCIPAL_CREDENTIALS=$'${{ secrets.AZURE_DEV_TEST_LABS_CREDENTIALS }}'
77+
export ADDITIONAL_PRINCIPALS=$'${{ secrets.ADDITIONAL_PRINCIPALS }}'
7778
7879
# Execute the script to create the dev test lab
7980
chmod +x ./.github/workflows/deploy.sh

Azure-DevTestLab/Environments/sqlcollaborative_AzureDataPipelineTools/azuredeploy.json

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
"devopsServicePrincipalCredentials": {
2828
"type": "object"
2929
},
30+
"additionalPrincipals": {
31+
"type": "array"
32+
},
3033
"adlsStorageAccountContainerName": {
3134
"type": "string",
3235
"defaultValue": "test"
@@ -80,23 +83,9 @@
8083
},
8184
"resources": [
8285
/********************************************************************************************************************************************
83-
**** Resource group permissions
86+
**** Dev-Ops Service Principal Permissions (Things not granted by owner/contributor at the RG level)
8487
********************************************************************************************************************************************/
8588

86-
// Add the devops service principal as a reader on the resource group (DevTest Labs is configured to create an RG for each lab).
87-
88-
// // 'Reader' scoped to the resource group. This already exists, here as an example
89-
// {
90-
// "type": "Microsoft.Authorization/roleAssignments",
91-
// "apiVersion": "[variables('authorizationApiVersion')]",
92-
// "name": "[guid(resourceGroup().id, 'devopsServicePrincipal_rg_reader')]",
93-
// "properties": {
94-
// "roleDefinitionId": "[variables('reader')]",
95-
// "principalId": "[parameters('devopsServicePrincipalCredentials').client_object_id]"
96-
// }
97-
// },
98-
99-
10089
// 'Storage Blob Data Contributor' scoped to the storage account container
10190
{
10291
"type": "Microsoft.Storage/storageAccounts/blobServices/containers/providers/roleAssignments",
@@ -143,10 +132,12 @@
143132

144133

145134

146-
147-
148-
// Add IAM access for functions app. See the following page for details of how to get the object id for the SPN
149-
// https://www.codeisahighway.com/there-is-a-new-way-to-reference-managed-identity-in-arm-template/
135+
/********************************************************************************************************************************************
136+
**** Functions App Service Principal Permissions (Allow the functions app to access resources)
137+
****
138+
**** Adds IAM access for functions app. See the following page for details of how to get the object id for the SPN
139+
**** https://www.codeisahighway.com/there-is-a-new-way-to-reference-managed-identity-in-arm-template/
140+
********************************************************************************************************************************************/
150141

151142
// 'Reader' scoped to the storage account
152143
{
@@ -180,6 +171,76 @@
180171
]
181172
},
182173

174+
175+
/********************************************************************************************************************************************
176+
**** Additional principals arte added using the additional principals array parameter
177+
****
178+
**** Use the copy() function to loop over the array and add permissions for those users / groups / service principals using their object
179+
**** id's.
180+
********************************************************************************************************************************************/
181+
182+
// 'Reader' scoped to the resource group. This already exists, here as an example
183+
{
184+
"type": "Microsoft.Authorization/roleAssignments",
185+
"apiVersion": "[variables('authorizationApiVersion')]",
186+
"name": "[guid(resourceGroup().id, parameters('additionalPrincipals')[copyIndex()])]",
187+
"properties": {
188+
"roleDefinitionId": "[variables('reader')]",
189+
"principalId": "[parameters('additionalPrincipals')[copyIndex()]]"
190+
},
191+
"copy": {
192+
"name": "principalCopy",
193+
"count": "[length(parameters('additionalPrincipals'))]"
194+
}
195+
},
196+
197+
// 'Storage Blob Data Contributor' scoped to the storage account container
198+
{
199+
"type": "Microsoft.Storage/storageAccounts/blobServices/containers/providers/roleAssignments",
200+
"name": "[concat(variables('adlsStorageAccountName'), '/default/', parameters('adlsStorageAccountContainerName'), '/Microsoft.Authorization/', guid(resourceGroup().id, parameters('additionalPrincipals')[copyIndex()], variables('adlsStorageAccountName'), parameters('adlsStorageAccountContainerName'), variables('storageBlobDataContributor')))]",
201+
"apiVersion": "[variables('authorizationApiVersion')]",
202+
"properties": {
203+
"roleDefinitionId": "[variables('storageBlobDataContributor')]",
204+
"principalId": "[parameters('additionalPrincipals')[copyIndex()]]"
205+
},
206+
"dependsOn": [
207+
"[concat('Microsoft.Storage/storageAccounts/', variables('adlsStorageAccountName'), '/blobServices/default/containers/', parameters('adlsStorageAccountContainerName'))]"
208+
],
209+
"copy": {
210+
"name": "principalCopy",
211+
"count": "[length(parameters('additionalPrincipals'))]"
212+
}
213+
},
214+
215+
// Assign access policies to the key vault. Need to test adding this to the KV template...
216+
{
217+
"type": "Microsoft.KeyVault/vaults/accessPolicies",
218+
"name": "[concat(variables('keyVaultName'), '/add')]",
219+
"apiVersion": "[variables('keyVaultApiVersion')]",
220+
"properties": {
221+
"copy": [
222+
{
223+
"name": "accessPolicies",
224+
"count": "[length(parameters('additionalPrincipals'))]",
225+
"input": {
226+
"tenantId": "[subscription().tenantId]",
227+
"objectId": "[parameters('additionalPrincipals')[copyIndex('accessPolicies')]]",
228+
"permissions": {
229+
"secrets": [
230+
"list",
231+
"get"
232+
]
233+
}
234+
}
235+
}
236+
]
237+
},
238+
"dependsOn": [
239+
"[concat('Microsoft.KeyVault/vaults/', variables('keyVaultName'))]"
240+
]
241+
},
242+
243+
183244
/********************************************************************************************************************************************
184245
**** ADLS storage
185246
********************************************************************************************************************************************/

0 commit comments

Comments
 (0)