Skip to content

Commit 17bcd1f

Browse files
committed
New tutorial for github actions
1 parent 1689aa5 commit 17bcd1f

File tree

2 files changed

+292
-0
lines changed

2 files changed

+292
-0
lines changed

articles/iot-dps/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ items:
5050
href: tutorial-custom-allocation-policies.md
5151
- name: Provision for geolatency
5252
href: how-to-provision-multitenant.md
53+
- name: Automate provisioning with GitHub Actions
54+
href: tutorial-automation-github-actions.md
5355
- name: Concepts
5456
items:
5557
- name: DPS terminology
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
---
2+
title: Tutorial - Automate Azure Device Provisioning Service with GitHub Actions
3+
description: Tutorial - Use GitHub Actions to automate the steps for creating and managing Azure Device Provisioning Service (DPS) resources
4+
author: kgremban
5+
ms.author: kgremban
6+
manager: lizross
7+
ms.date: 12/13/2022
8+
ms.topic: tutorial
9+
ms.service: iot-dps
10+
services: iot-dps
11+
ms.custom: mvc
12+
---
13+
14+
# Tutorial: Automate Azure Device Provisioning Service processes with GitHub Actions
15+
16+
17+
TODO: Add your introductory paragraph
18+
19+
20+
In this tutorial, you learn how to:
21+
22+
> [!div class="checklist"]
23+
> * [All tutorials include a list summarizing the steps to completion]
24+
> * [Each of these bullet points align to a key H2]
25+
> * [Use these green checkboxes in a tutorial]
26+
27+
## Prerequisites
28+
29+
* An Azure subscription
30+
31+
If you don't have an Azure subscription, create a [free account](https://azure.microsoft.com/free/?ref=microsoft.com&utm_source=microsoft.com&utm_medium=docs&utm_campaign=visualstudio) before you begin.
32+
33+
* Azure CLI
34+
35+
* A GitHub account with either a repository that you own or a repository where you have admin access. For more information, see [Get started with GitHub](https://docs.github.com/en/get-started).
36+
37+
## 1 - Create a workflow
38+
39+
A GitHub Actions *workflow* defines the tasks that will run once it's triggered by an *event*. A workflow contains one or more *jobs* which can run in parallel or sequentially. For more information, see [Understanding GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions).
40+
41+
For this tutorial, we'll create one workflow that contains jobs for each of the following tasks:
42+
43+
* Provision an IoT Hub instance and a DPS instance.
44+
* Link the IoT Hub and DPS instances to each other.
45+
* Create an individual enrollment on the DPS instance, and register a device to the IoT hub via the DPS enrollment.
46+
* Simulate the device for five minutes and monitor the IoT hub events.
47+
48+
Workflows are YAML files that are located in the `.github/workflows/` directory of a repository.
49+
50+
1. In your GitHub repository, navigate to the **Actions** tab.
51+
1. In the **Actions** pane, select **New workflow**.
52+
1. On the **Choose a workflow page**, you can choose prebuilt templates to use. We're going to create out own workflow for this tutorial, so select **Set up a workflow yourself**.
53+
1. GitHub creates a new workflow file for you. Notice that it's in the `.github/workflows/` directory. Give the new file a meaningful name, like `dps-tutorial.yml`.
54+
1. Add the [name](https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions#name) parameter to give your workflow a name.
55+
56+
```yml
57+
name: DPS Tutorial
58+
```
59+
60+
1. Add the [on.workflow_dispatch.inputs](https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions#onworkflow_dispatchinputs) parameter. The `on` parameter defines when a workflow will run. The `workflow_dispatch` parameter indicates that we want to manually trigger the workflow after providing inputs to the workflow. The `inputs` parameter lets you define the inputs that will be passed to the workflow.
61+
62+
```yml
63+
on:
64+
workflow_dispatch:
65+
inputs:
66+
```
67+
68+
1. Define the input parameters for the workflow. You'll manually provide these parameters any time you run the workflow.
69+
70+
```yml
71+
hubName:
72+
type: string
73+
description: Desired IoT hub name
74+
required: true
75+
dpsName:
76+
type: string
77+
description: Desired Device Provisioning Service name
78+
required: true
79+
deviceName:
80+
type: string
81+
description: Desired device name
82+
required: true
83+
resourceGroup:
84+
type: string
85+
description: Solution resource group
86+
required: true
87+
```
88+
89+
1. Add the [jobs](https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions#jobs) parameter to the workflow file.
90+
91+
```yml
92+
jobs:
93+
```
94+
95+
1. Define the first job for our workflow, which we'll call the `provision` job. This job provisions the IoT Hub and DPS instances.
96+
97+
```yml
98+
provision:
99+
runs-on: ubuntu-latest
100+
steps:
101+
- name: Provision Infra
102+
env:
103+
spUser: ${{ secrets.APP_ID }}
104+
spSecret: ${{ secrets.SECRET }}
105+
spTenant: ${{ secrets.TENANT }}
106+
run: |
107+
az --version
108+
az login --service-principal -u "$spUser" -p "$spSecret" --tenant "$spTenant"
109+
az iot hub create -n "${{ github.event.inputs.hubName }}" -g "${{ github.event.inputs.resourceGroup }}"
110+
az iot dps create -n "${{ github.event.inputs.dpsName }}" -g "${{ github.event.inputs.resourceGroup }}"
111+
```
112+
113+
1. Define a job to `configure` the DPS and IoT Hub instances. Notice that this job uses the [needs](https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idneeds) parameter, which means that the `configure` job won't run until listed job completes its own run successfully.
114+
115+
```yml
116+
configure:
117+
runs-on: ubuntu-latest
118+
needs: provision
119+
steps:
120+
- name: Configure Infra
121+
env:
122+
spUser: ${{ secrets.APP_ID }}
123+
spSecret: ${{ secrets.SECRET }}
124+
spTenant: ${{ secrets.TENANT }}
125+
run: |
126+
az login --service-principal -u "$spUser" -p "$spSecret" --tenant "$spTenant"
127+
az iot dps linked-hub create --dps-name "${{ github.event.inputs.dpsName }}" --hub-name "${{ github.event.inputs.hubName }}"
128+
```
129+
130+
1. Define a job called `register` that will create an individual enrollment and then use that enrollment to register a device to IoT Hub.
131+
132+
```yml
133+
register:
134+
runs-on: ubuntu-latest
135+
needs: configure
136+
steps:
137+
- name: Create enrollment
138+
env:
139+
spUser: ${{ secrets.APP_ID }}
140+
spSecret: ${{ secrets.SECRET }}
141+
spTenant: ${{ secrets.TENANT }}
142+
run: |
143+
az login --service-principal -u "$spUser" -p "$spSecret" --tenant "$spTenant"
144+
az extension add --name azure-iot
145+
az iot dps enrollment create -n "${{ github.event.inputs.dpsName }}" --eid "${{ github.event.inputs.deviceName }}" --attestation-type symmetrickey --auth-type login
146+
- name: Register device
147+
run: |
148+
az iot device registration create -n "${{ github.event.inputs.dpsName }}" --rid "${{ github.event.inputs.deviceName }}" --auth-type login
149+
```
150+
151+
1. Define a job to `simulate` an IoT device that will connect to the IoT hub and send sample telemetry messages.
152+
153+
```yml
154+
simulate:
155+
runs-on: ubuntu-latest
156+
needs: register
157+
steps:
158+
- name: Simulate device
159+
env:
160+
spUser: ${{ secrets.APP_ID }}
161+
spSecret: ${{ secrets.SECRET }}
162+
spTenant: ${{ secrets.TENANT }}
163+
run: |
164+
az login --service-principal -u "$spUser" -p "$spSecret" --tenant "$spTenant"
165+
az extension add --name azure-iot
166+
az iot device simulate -n "${{ github.event.inputs.hubName }}" -d "${{ github.event.inputs.deviceName }}"
167+
```
168+
169+
1. Define a job to `monitor` the IoT hub endpoint for events, and watch messages coming in from the simulated device. Notice that the **simulate** and **monitor** jobs both define the **register** job in their `needs` parameter. This configuration means that once the **register** job completes successfuly, both these jobs will run in parallel.
170+
171+
```yml
172+
monitor:
173+
runs-on: ubuntu-latest
174+
needs: register
175+
steps:
176+
- name: Monitor d2c telemetry
177+
env:
178+
spUser: ${{ secrets.APP_ID }}
179+
spSecret: ${{ secrets.SECRET }}
180+
spTenant: ${{ secrets.TENANT }}
181+
run: |
182+
az login --service-principal -u "$spUser" -p "$spSecret" --tenant "$spTenant"
183+
az extension add --name azure-iot
184+
az iot hub monitor-events -n "${{ github.event.inputs.hubName }}" -y
185+
```
186+
187+
1. Save, commit, and push this new file to your GitHub repository.
188+
189+
## 2 - Create repository secrets
190+
191+
The workflow that you defined in the previous section requires access to your Azure subscription to create and manage resources. You don't want to put that information in an unprotected file where it could be discovered, so instead we'll use repository secrets to store this information but still make it accessible as an environment variable in the workflow. For more information, see [Encrypted secrets](https://docs.github.com/actions/security-guides/encrypted-secrets).
192+
193+
Only repository owners and admins can manage repository secrets.
194+
195+
### Create a service principal
196+
197+
Rather than providing your personal access credentials, we'll create a service principal and then add those credentials as repository secrets. Use the Azure CLI to create a new service principal. For more information, see [Create an Azure service principal](/cli/azure/create-an-azure-service-principal-azure-cli).
198+
199+
The following command creates a service principal with *contributor* access to a specific resource group. Replace **<SUBSCRIPTION_ID>** and **<RESOURCE_GROUP_NAME>** with your own information.
200+
201+
This command requires owner or user access administrator roles in the subscription.
202+
203+
```azurecli
204+
az ad sp create-for-rbac --name github-actions-sp --role contributor --scopes /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP_NAME>
205+
```
206+
207+
The output for this command includes a generated password for the service principal. Copy this password to use in the next section. You won't be able to access the password again.
208+
209+
### Save service principal credentials as secrets
210+
211+
1. On [GitHub.com](https://github.com), navigate to the **Settings** for your repository.
212+
213+
1. Select **Secrets** from the navigation menu, then select **Actions**.
214+
215+
1. Select **New repository secret**.
216+
217+
1. Create a secret for your service principal ID.
218+
219+
* **Name**: `APP_ID`
220+
* **Secret**: `github-actions-sp`, or the value you used for the service principal name if you used a different value.
221+
222+
1. Select **Add secret**, then select **New repository secret** to add a second secret.
223+
224+
1. Create a secret for your service principal password.
225+
226+
* **Name**: `SECRET`
227+
* **Secret**: Paste the password that you copied from the output of the service principal creation command.
228+
229+
1. Select **Add secret**, then select **New repository secret** to add the final secret.
230+
231+
1. Create a secret for your Azure tenant.
232+
233+
* **Name**: `TENANT`
234+
* **Secret**: Provide your Azure tenant. The value of this argument can either be an .onmicrosoft.com domain or the Azure object ID for the tenant.
235+
236+
1. Select **Add secret**.
237+
238+
## 3 - Run the workflow
239+
240+
1. Navigate to the **Actions** tab of your GitHub repository.
241+
1. In the **Actions** pane, select **DPS Tutorial**, which is the name that we defined in the workflow file.
242+
1. Select the **Run workflow** drop-down box.
243+
1. The **Run workflow** box provides text fields for each of the input parameters that we defined in the workflow file. Provide values for each of them:
244+
245+
* **Desired IoT hub name**: Provide a globally unique name for your IoT Hub instance.
246+
* **Desired Device Provisioning Service name**: Provide a unique name for your Device Provisioning Service instance.
247+
* **Desired device name**: Provide a name for your device.
248+
* **Solution resource group**: Provide the name of the resource group where the IoT hub and DPS instance will be created. This is the same resource group that your service principal has access to.
249+
250+
1. Select **Run workflow**.
251+
252+
1. A new workflow run appears in progress. Select the name to view details of the run.
253+
254+
## Clean up resources
255+
256+
If you're not going to continue to use this resources created in this tutorial, delete
257+
them with the following steps.
258+
259+
Use the Azure CLI:
260+
261+
1. List the resources in your resource group.
262+
263+
```azurecli
264+
az resource list --resource-group <RESOURCE_GROUP_NAME>
265+
```
266+
267+
1. To delete individual resources, use the resource ID.
268+
269+
```azurecli
270+
az resource delete --resource-group <RESOURCE_GROUP_NAME> --ids <RESOURCE_ID>
271+
```
272+
273+
1. If you want to delete the whole resource group and all resources within it, run the following command:
274+
275+
```azurecli
276+
az group delete --resource-group <RESOURCE_GROUP_NAME>
277+
```
278+
279+
Use the Azure portal:
280+
281+
1. In the [Azure portal](https://portal.azure.com), navigate to the resource group where you created the new resources.
282+
1. You can either delete the entire resource group or select the individual resources that you want to remove, then select **Delete**.
283+
284+
## Next steps
285+
286+
Learn how to provision DPS instances with other automation tools.
287+
288+
> [!div class="nextstepaction"]
289+
> [Set up DPS with Bicep](tutorial-custom-allocation-policies.md)
290+

0 commit comments

Comments
 (0)