Last active
April 1, 2019 19:16
-
-
Save kevinhillinger/630bd1089aff2fbd83bed39205e30f9e to your computer and use it in GitHub Desktop.
Azure API Management to Key Vault Integration - Client Certificate Authentication
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
rg=apim | |
location=eastus2 | |
vnet=apim-vnet | |
az group create --name $rg --location $location | |
az network vnet create -n $vnet -g $rg -l $location \ | |
--address-prefixes 10.0.0.0/16 \ | |
--subnet-name default \ | |
--subnet-prefixes 10.0.0.0/24 | |
# there is no cli support for azure APIM :( | |
# create it from the portal with developer tier, join to vnet | |
keyvault=apim-vault-$((1 + RANDOM % 10000)) | |
az keyvault create --name $keyvault -g $rg -l $location | |
# secure the key vault | |
az network vnet subnet update --resource-group $rg \ | |
--vnet-name $vnet \ | |
--name default \ | |
--service-endpoints "Microsoft.KeyVault" | |
subnetid=$(az network vnet subnet show --resource-group $rg --vnet-name $vnet --name default --query id --output tsv) | |
az keyvault network-rule add --resource-group $rg --name $keyvault --subnet $subnetid | |
az keyvault network-rule add --resource-group $rg --name $keyvault --ip-address "10.0.0.0/16" | |
# azure services allow | |
az keyvault update --resource-group $rg --name $keyvault --bypass AzureServices | |
# enable the service endpoint rules | |
az keyvault update --resource-group $rg --name $keyvault --default-action Deny | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Resources | |
# https://docs.microsoft.com/en-us/azure/key-vault/key-vault-manage-with-cli2 | |
keyvault=$(az keyvault list -g $rg --query '[?name.starts_with(@, `apim`)].name' --output tsv) | |
# create the service principal | |
sp_name="apim-${keyvault}" | |
sp=$(az ad sp create-for-rbac -n $sp_name --skip-assignment --output json) | |
sp_id=$(echo $sp | jq .appId -r) | |
# assign the service principal to the vault to allow read permission on the certificates | |
az keyvault set-policy --name $keyvault \ | |
--spn $sp_id \ | |
--certificate-permissions get \ | |
--secret-permissions get | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# references | |
# https://www.noelbundick.com/posts/importing-certificates-to-key-vault/ | |
keyvault=$(az keyvault list -g $rg --query '[?name.starts_with(@, `apim`)].name' --output tsv) | |
cert=cert1 | |
pfx=cert1.pfx | |
# Tell Key Vault to create a certificate with the default policy | |
az keyvault certificate create --vault-name $keyvault -n $cert -p "$(az keyvault certificate get-default-policy -o json)" | |
# Download the secret (private key information) associated with the cert | |
az keyvault secret download --vault-name $keyvault -n $cert -e base64 -f $pfx |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
Create the following named values in APIM: | |
- aad-endpoint | |
- aad-clientid | |
- aad-clientsecret | |
- aad-scope | |
--> | |
<policies> | |
<inbound> | |
<base /> | |
<!-- to get a request to AAD, use https://login.microsoftonline.com/<tenant id>/oauth2/token --> | |
<send-request ignore-error="true" timeout="20" response-variable-name="bearerToken" mode="new"> | |
<set-url>{{aad.endpoint}}</set-url> | |
<set-method>POST</set-method> | |
<set-header name="Content-Type" exists-action="override"> | |
<value>application/x-www-form-urlencoded</value> | |
</set-header> | |
<set-body> | |
@{ | |
return "client_id={{aad.clientid}}&resource={{aad.scope}}&client_secret={{aad.clientsecret}}&grant_type=client_credentials"; | |
} | |
</set-body> | |
</send-request> | |
<set-variable name="keyVaultToken" | |
value="@((String)((IResponse)context.Variables["bearerToken"]).Body.As<JObject>()["access_token"])" /> | |
<!-- get certificate from key vault | |
https://docs.microsoft.com/en-us/azure/key-vault/authentication-requests-and-responses | |
https://docs.microsoft.com/en-us/rest/api/keyvault/getcertificate/getcertificate | |
{vaultBaseUrl}/certificates/{certificate-name}/{certificate-version}?api-version=7.0 | |
--> | |
<send-request ignore-error="true" timeout="20" response-variable-name="clientCertificate" mode="new"> | |
<set-url>{{keyvault.url}}/certificates/{{keyvault.cert.name}}?api-version=7.0</set-url> | |
<set-method>GET</set-method> | |
<set-header name="Content-Type" exists-action="override"> | |
<value>application/json</value> | |
</set-header> | |
<set-header name="Authorization" exists-action="override"> | |
<value>@("Bearer" + context.Variables["bearerToken"])</value> | |
</set-header> | |
</send-request> | |
</inbound> | |
<backend> | |
<base /> | |
</backend> | |
<outbound> | |
<base /> | |
<set-header name="x-client-cert" exists-action="override"> | |
<value>@(context.Variables["clientCertificate"])</value> | |
</set-header> | |
<set-body> | |
@{ | |
string cert = context.Variables["clientCertificate"]; | |
return "x-client-cert: " + cert; | |
} | |
</set-body> | |
</outbound> | |
<on-error> | |
<base /> | |
</on-error> | |
</policies> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment