Skip to content

Commit f735d16

Browse files
committed
Updated resource provisioning script with creation and assignment of Oauth roles associated with app registrations governing our function app and static website
1 parent 0eab1b7 commit f735d16

File tree

5 files changed

+126
-13
lines changed

5 files changed

+126
-13
lines changed

README.md

+34-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ Once the CSV has been uploaded to the storage blob, another, blob-triggered Azur
66
The computed statistics are then stored in a new blob container, which is used to serve the results to the user.
77
These two functions are defined in the python script [function_app.py](hvalfangst_function/function_app.py) - which is the main entrypoint of our Azure Function App instance.
88

9+
The SPA is protected with Oauth2.0 authorization code flow with PKCE and OIDC. The user is redirected to the Azure AD login page, where they must authenticate before being redirected back to the SPA.
10+
11+
912
The associated Azure infrastructure is deployed with a script (more on that below).
1013

1114
A branch-triggered pipeline has been set up to deploy our code to the respective Azure resources using a GitHub Actions Workflows [script](.github/workflows/deploy_to_azure.yml).
@@ -24,7 +27,7 @@ Thus, deploying the website is simply a matter of uploading the static files to
2427

2528
## Allocate resources
2629

27-
The shell script [allocate_resources](infra/allocate_resources.sh) creates Azure resources using the Azure CLI and a
30+
The shell script [allocate_resources](infra/allocate_resources.sh) creates Azure resources using the Azure CLI in conjunction with a
2831
[Bicep](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview?tabs=bicep) template [file](infra/main.bicep).
2932

3033
It will create the following hierarchy of resources:
@@ -47,6 +50,26 @@ graph TD
4750
B -->|Contains| F
4851
```
4952

53+
## Registrations
54+
In addition to the resources listed above, the script will also create a **service principal** and two Microsoft Entra ID **app registrations.**
55+
56+
### Service Principal for GitHub Actions
57+
The service principal has been assigned contributor role to our resource group, which is sufficient in order to deploy the static web app to the storage blob.
58+
It has been assigned a federated credential configured to work with this repository as it is utilized in our CI/CD [GitHub Actions Workflow script](.github/workflows/deploy_to_azure.yml).
59+
60+
### App Registration for Azure Function App
61+
62+
Exposes two scopes; **Csv.Writer** and **Csv.Reader**.
63+
64+
![img.png](img.png)
65+
66+
### App Registration for SPA
67+
68+
Has a redirect URI configured to the static web app's URL and the permissions **Csv.Writer** and the OIDC ones.
69+
70+
![img_1.png](img_1.png)
71+
72+
5073
## GitHub secrets
5174
Four secrets are required in order for the GitHub Actions Workflow script to deploy the code to the Azure resources.
5275
As may be observed in the [script](.github/workflows/deploy_to_azure.yml), these are:
@@ -56,4 +79,13 @@ As may be observed in the [script](.github/workflows/deploy_to_azure.yml), these
5679
- **AZURE_TENANT_ID**: Used to authenticate the service principal in order to deploy the static web app
5780
- **PUBLISH_PROFILE**: Used to deploy our two functions to the Azure Function App
5881

59-
![img_1.png](images/img_1.png)
82+
![secrets.png](images/secrets.png)
83+
84+
## Usage
85+
After provisioning resources, setting up secrets, and pushing the code to the repository, one
86+
may access the static web app by navigating to the following URL:
87+
88+
```plaintext
89+
https://<storage_account_name>.z6.web.core.windows.net
90+
```
91+
File renamed without changes.

img.png

93.6 KB
Loading

img_1.png

85.5 KB
Loading

infra/allocate_resources.sh

+92-11
Original file line numberDiff line numberDiff line change
@@ -108,37 +108,118 @@ if [ $? -ne 0 ]; then
108108
exit 1
109109
fi
110110

111-
# Set up app registration for function app
111+
112+
# Set up app registration for the function app
112113
echo -e "${YELLOW}Setting up app registration for function app...${RESET}"
113114
FUNCTION_APP_CLIENT_ID=$(az ad app create \
114115
--display-name "hvalfangst-function-app" \
116+
--identifier-uris "api://hvalfangst-function-app" \
115117
--query appId -o tsv)
116-
117118
if [ $? -ne 0 ] || [ -z "$FUNCTION_APP_CLIENT_ID" ]; then
118119
echo -e "${RED}Failed to set up app registration or retrieve the app ID.${RESET}"
119120
exit 1
120121
fi
121122

122-
# Set up app settings for the function app
123-
echo -e "${YELLOW}Setting up app settings for function app...${RESET}"
124-
az functionapp config appsettings set \
125-
--name ${FUNCTION_APP_NAME} \
126-
--resource-group ${RESOURCE_GROUP} \
127-
--settings TENANT_ID=${TENANT_ID} FUNCTION_APP_CLIENT_ID=${FUNCTION_APP_CLIENT_ID}
128-
if [ $? -ne 0 ]; then
129-
echo -e "${RED}Failed to set up app settings for function app.${RESET}"
123+
# Get the object ID of the app registration
124+
FUNCTION_APP_OBJECT_ID=$(az ad app show --id $FUNCTION_APP_CLIENT_ID --query id -o tsv)
125+
126+
# Get an access token for the Microsoft Graph API to be used for patching app regs associated with function app and static website
127+
TOKEN=$(az account get-access-token --resource https://graph.microsoft.com --query accessToken -o tsv)
128+
if [ $? -ne 0 ] || [ -z "$TOKEN" ]; then
129+
echo -e "${RED}Failed to get access token for Microsoft Graph API.${RESET}"
130130
exit 1
131131
fi
132132

133+
# Generate UUIDs for the permissions
134+
CSV_READER_UUID=$(python -c 'import uuid; print(str(uuid.uuid4()))')
135+
CSV_WRITER_UUID=$(python -c 'import uuid; print(str(uuid.uuid4()))')
136+
137+
# Add permissions to the app registration by calling the Microsoft Graph API with a PATCH request
138+
echo -e "${YELLOW}Creating scopes for the Function App...${RESET}"
139+
curl -X PATCH -H "Authorization: Bearer $TOKEN" \
140+
-H "Content-Type: application/json" \
141+
-d "{
142+
\"api\": {
143+
\"oauth2PermissionScopes\": [
144+
{
145+
\"id\": \"$CSV_READER_UUID\",
146+
\"adminConsentDescription\": \"Allows downloading of CSV files\",
147+
\"adminConsentDisplayName\": \"Allows downloading of CSV files\",
148+
\"isEnabled\": true,
149+
\"type\": \"Admin\",
150+
\"value\": \"Csv.Reader\"
151+
},
152+
{
153+
\"id\": \"$CSV_WRITER_UUID\",
154+
\"adminConsentDescription\": \"Allows uploading of CSV files\",
155+
\"adminConsentDisplayName\": \"Allows uploading of CSV files\",
156+
\"isEnabled\": true,
157+
\"type\": \"Admin\",
158+
\"value\": \"Csv.Writer\"
159+
}
160+
]
161+
}
162+
}" \
163+
"https://graph.microsoft.com/v1.0/applications/$FUNCTION_APP_OBJECT_ID"
164+
133165
# Set up app registration for the static web app
134166
echo -e "${YELLOW}Setting up app registration for static web app...${RESET}"
135167
STATIC_WEB_APP_CLIENT_ID=$(az ad app create \
136168
--display-name "hvalfangst-static-web-app" \
169+
--web-redirect-uris "http://localhost:3000" \
137170
--query appId -o tsv)
138-
139171
if [ $? -ne 0 ] || [ -z "STATIC_WEB_APP_CLIENT_ID" ]; then
140172
echo -e "${RED}Failed to set up app registration or retrieve the app ID.${RESET}"
141173
exit 1
142174
fi
143175

176+
STATIC_WEB_APP_OBJECT_ID=$(az ad app show --id $STATIC_WEB_APP_CLIENT_ID --query id -o tsv)
177+
if [ $? -ne 0 ] || [ -z "$STATIC_WEB_APP_OBJECT_ID" ]; then
178+
echo -e "${RED}Failed to retrieve the object ID of the static web app registration.${RESET}"
179+
exit 1
180+
fi
181+
182+
# Add permissions to the app registration associated with website by calling the Microsoft Graph API with a PATCH request
183+
echo -e "${YELLOW}Adding OpenID permissions for Microsoft Graph API to Static Website${RESET}"
184+
curl -X PATCH -H "Authorization: Bearer $TOKEN" \
185+
-H "Content-Type: application/json" \
186+
-d "{
187+
\"requiredResourceAccess\": [
188+
{
189+
\"resourceAppId\": \"00000003-0000-0000-c000-000000000000\",
190+
\"resourceAccess\": [
191+
{
192+
\"id\": \"e1fe6dd8-ba31-4d61-89e7-88639da4683d\",
193+
\"type\": \"Scope\"
194+
},
195+
{
196+
\"id\": \"14dad69e-099b-42c9-810b-d002981feec1\",
197+
\"type\": \"Scope\"
198+
}
199+
]
200+
},
201+
{
202+
\"resourceAppId\": \"$FUNCTION_APP_CLIENT_ID\",
203+
\"resourceAccess\": [
204+
{
205+
\"id\": \"$CSV_WRITER_UUID\",
206+
\"type\": \"Scope\"
207+
}
208+
]
209+
}
210+
]
211+
}" \
212+
"https://graph.microsoft.com/v1.0/applications/$STATIC_WEB_APP_OBJECT_ID"
213+
214+
# Set up app settings for the function app
215+
echo -e "${YELLOW}Setting up app settings for function app...${RESET}"
216+
az functionapp config appsettings set \
217+
--name ${FUNCTION_APP_NAME} \
218+
--resource-group ${RESOURCE_GROUP} \
219+
--settings TENANT_ID=${TENANT_ID} FUNCTION_APP_CLIENT_ID=${FUNCTION_APP_CLIENT_ID}
220+
if [ $? -ne 0 ]; then
221+
echo -e "${RED}Failed to set up app settings for function app.${RESET}"
222+
exit 1
223+
fi
224+
144225
echo -e "${GREEN}All resources have been provisioned.${RESET}"

0 commit comments

Comments
 (0)