|
| 1 | +# Federating Coder's control plane to Azure |
| 2 | + |
| 3 | +<div> |
| 4 | + <a href="https://github.com/ericpaulsen" style="text-decoration: none; color: inherit;"> |
| 5 | + <span style="vertical-align:middle;">Eric Paulsen</span> |
| 6 | + <img src="https://github.com/ericpaulsen.png" width="24px" height="24px" style="vertical-align:middle; margin: 0px;"/> |
| 7 | + </a> |
| 8 | +</div> |
| 9 | +January 26, 2024 |
| 10 | + |
| 11 | +--- |
| 12 | + |
| 13 | +This guide will walkthrough how to authenticate a Coder Provisioner to Microsoft |
| 14 | +Azure, using a Service Principal with a client certificate. You can use this |
| 15 | +guide for authenticating Coder to Azure, regardless of where Coder is run, |
| 16 | +either on-premise or in a non-Azure cloud. This method is one of several |
| 17 | +[recommended by Terraform](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs#authenticating-to-azure). |
| 18 | + |
| 19 | +## Step 1: Generate Client Certificate & PKCS bundle |
| 20 | + |
| 21 | +We'll need to create the certificate Coder will use for authentication. Run the |
| 22 | +below command to generate a private key and self-signed certificate: |
| 23 | + |
| 24 | +```console |
| 25 | +openssl req -subj '/CN=myclientcertificate/O=MyCompany, Inc./ST=CA/C=US' \ |
| 26 | + -new -newkey rsa:4096 -sha256 -days 730 -nodes -x509 -keyout client.key -out client.crt |
| 27 | +``` |
| 28 | + |
| 29 | +Next, generate a `.pfx` file to be used by Coder's Provisioner to authenticate |
| 30 | +the AzureRM provider: |
| 31 | + |
| 32 | +```console |
| 33 | +openssl pkcs12 -export -password pass:"Pa55w0rd123" -out client.pfx -inkey client.key -in client.crt |
| 34 | +``` |
| 35 | + |
| 36 | +## Step 2: Create Azure Application & Service Principal |
| 37 | + |
| 38 | +Navigate to the Azure portal, and into the Microsoft Entra ID section. Select |
| 39 | +the App Registration blade, and register a new application. Fill in the |
| 40 | +following fields: |
| 41 | + |
| 42 | +- **Name**: this is a friendly identifier and can be anything (e.g. "Coder") |
| 43 | +- **Supported Account Types**: - set to "Accounts in this organizational |
| 44 | + directory only (single-tenant)" |
| 45 | + |
| 46 | +The **Redirect URI** field does not need to be set in this case. Take note of |
| 47 | +the `Application (client) ID` and `Directory (tenant) ID` values, which will be |
| 48 | +used by Coder. |
| 49 | + |
| 50 | +## Step 3: Assign Client Certificate to the Azure Application |
| 51 | + |
| 52 | +To upload the certificate we created in Step 1, select **Certificates & |
| 53 | +secrets** on the left-hand side, and select **Upload Certificate**. Upload the |
| 54 | +public key file, which is `service-principal.crt` from the example above. |
| 55 | + |
| 56 | +## Step 4: Set Permissions on the Service Principal |
| 57 | + |
| 58 | +Now that the Application is created in Microsoft Entra ID, we need to assign |
| 59 | +permissions to the Service Principal so it can provision Azure resources for |
| 60 | +Coder users. Navigate to the Subscriptions blade in the Azure Portal, select the |
| 61 | +**Subscription > Access Control (IAM) > Add > Add role assignment**. |
| 62 | + |
| 63 | +Set the **Role** that grants the appropriate permissions to create the Azure |
| 64 | +resources you need for your Coder workspaces. `Contributor` will provide |
| 65 | +Read/Write on all Subscription resources. For more information on the available |
| 66 | +roles, see the |
| 67 | +[Microsoft documentation](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles). |
| 68 | + |
| 69 | +## Step 5: Configure Coder to use the Client Certificate |
| 70 | + |
| 71 | +Now that the client certificate is uploaded to Azure, we need to mount the |
| 72 | +certificate files into the Coder deployment. If running Coder on Kubernetes, you |
| 73 | +will need to create the `.pfx` file as a Kubernetes secret, and mount it into |
| 74 | +the Helm chart. |
| 75 | + |
| 76 | +Run the below command to create the secret: |
| 77 | + |
| 78 | +```console |
| 79 | +kubectl create secret generic -n coder azure-client-cert-secret --from-file=client.pfx=/path/to/your/client.pfx |
| 80 | +``` |
| 81 | + |
| 82 | +In addition, create secrets for each of the following values from your Azure |
| 83 | +Application: |
| 84 | + |
| 85 | +- Client ID |
| 86 | +- Tenant ID |
| 87 | +- Subscription ID |
| 88 | +- Certificate password |
| 89 | + |
| 90 | +Next, set the following values in Coder's Helm chart: |
| 91 | + |
| 92 | +```yaml |
| 93 | +coder: |
| 94 | + env: |
| 95 | + - name: ARM_CLIENT_ID |
| 96 | + valueFrom: |
| 97 | + secretKeyRef: |
| 98 | + key: id |
| 99 | + name: arm-client-id |
| 100 | + - name: ARM_CLIENT_CERTIFICATE_PATH |
| 101 | + value: /home/coder/az/ |
| 102 | + - name: ARM_CLIENT_CERTIFICATE_PASSWORD |
| 103 | + valueFrom: |
| 104 | + secretKeyRef: |
| 105 | + key: password |
| 106 | + name: arm-client-cert-password |
| 107 | + - name: ARM_TENANT_ID |
| 108 | + valueFrom: |
| 109 | + secretKeyRef: |
| 110 | + key: id |
| 111 | + name: arm-tenant-id |
| 112 | + - name: ARM_SUBSCRIPTION_ID |
| 113 | + valueFrom: |
| 114 | + secretKeyRef: |
| 115 | + key: id |
| 116 | + name: arm-subscription-id |
| 117 | + volumes: |
| 118 | + - name: "azure-client-cert" |
| 119 | + secret: |
| 120 | + secretName: "azure-client-cert-secret" |
| 121 | + volumeMounts: |
| 122 | + - name: "azure-client-cert" |
| 123 | + mountPath: "/home/coder/az/" |
| 124 | + readOnly: true |
| 125 | +``` |
| 126 | +
|
| 127 | +Upgrade the Coder deployment using the following `helm` command: |
| 128 | + |
| 129 | +```console |
| 130 | +helm upgrade coder coder-v2/coder -n coder -f values.yaml |
| 131 | +``` |
0 commit comments