- About this sample
- Prerequisites
- Creating Azure Resources
- Step 1 - Create Github Secrets
- Step 2 - Run Github Action Deploy APIM Infra
- Step 3 - Upload your certificate in Azure Key Vault
- Step 4 - Configure the Gateway of APIM
- Step 5 - Configure the developer portal
- Step 6 - Publish Developer Portal
- Step 7 - Run the next Github Action
- Step 8 - Configure in Azure Public DNS the IP of Application Gateway
- Error during deploying KeyVault
- Optional
This sample provide two Github action that will create all the infrastructure in place to have a private APIM exposed to public Internet using Application Gateway with WAF.
3 samples application are available in the Github repository but are not deployed today with the Github Actions, this need to be done manually if desired.
First step is to Fork this repository.
Here the tool you need to installe on your machine.
-
Install the official Powershell Let's Encrypt client
-
Dotnet 3.1 SDK
Here the list of all supported clients if you want to implement your own logic for the Let's Encrypt Certificate.
This demo is using Azure Public DNS Zone, you will need to have a domain that you own from any register. Once is done you need to configure your DNS in your domain register with Azure DNS Public Zone entry.
It's all explain here.
Be sure you already configured your Azure Public DNS Zone.
First create a service principal running the following command.
$ az ad sp create-for-rbac --name <ServicePrincipalName> --sdk-auth --role contributor
Take note of the output you will need it to create Github Secrets.
Now go to the folder scripts, there you have a powershell called letsEncrypt.ps1.
This script will connect to your Azure Subscription passed in parameters and create a TXT challenge in your Azure DNS Public Zone.
First run this command in a PowerShell terminal
$ Set-PAServer LE_PROD
Now with the information retrieved when you created the service principal you can create your certificate.
Be sure your Service Principal have access to modify your Azure Public DNS Zone. If you want to use least priviledge refer to this doc.
$ .\letsEncrypt.ps1 -certNames *.contoso.com -acmeContact [email protected] -aZSubscriptionId <subId> -aZTenantId <tenantId> -aZAppUsername "<sp_clientId>" -aZAppPassword "<sp_password>" -pfxPassword "<pfxPassword>"
Be sure the username, password and certificate password are in double quotes
When the command is finished, a new folder called pa will be created inside the scripts folder.
If you browse in it inside the last child folder of acme-v02.api.letsencrypt.org you will see those files. We want cert.pfx
Here are the steps to upload the cert you created in your project directory to your certificate store:
- In your folder explorer, navigate to the location of your cert:
C:\Users\myUser\source\repos\apimPrivateVnet\scripts\pa\acme-v02.api.letsencrypt.org\...
- Right click on cert.cer -> Install Certificate
To create the architecture and all Azure resources you need to setup some Github Secrets before.
Here the list of all Github secrets that need to create before running the Github Action.
Secret Name | Description | Link |
---|---|---|
ADMIN_VAULT_OBJECT_ID | This is the object ID of the super admin that you want to give access to KeyVault. In the Azure portal, go to Azure AD ➡️ Users ➡️ choose the admin user which you will be using to deploy the resources in this repo ➡️ Copy "Object ID" value | |
PA_TOKEN | You will need to have a Personal Access Token to write secrets after running the first GitHub Action. You can find the information here. The PA needs the public_repo scope. This is needed for this specific GitHub Action | |
SP_AZURE_CREDENTIALS | Secret that contains the credential to run Az Login. Paste the entire JSON output from service principal creation above. The JSON object includes clientId, clientSecret, etc. | GitHub Action |
SP_PRINCIPAL_OBJECT_ID | The object ID of the service principal created above. This is the service principal that will enable you to run the GitHub Action and log into Azure | |
PUBLISHER_NAME | The publisher name associated to APIM (e.g. Contoso) | |
PUBLISHER_EMAIL | The publisher email associated to APIM (e.g. [email protected]) | |
ADMIN_USERNAME_SQL | The admin username for the SQL Azure Database (e.g. azureadmin) | |
ADMIN_PASSWORD_SQL | The password for the SQL Azure Database | |
HOSTNAME | The hostname of your domain (e.g. contoso.com) | |
ADMIN_USERNAME | The admin username of the Jumpbox and on-premises VM (e.g. azureadmin) | |
ADMIN_PASSWORD | The password of the Jumpbox and on-premises VM | |
DEV_PORTAL_GW_HOSTNAME | The DNS name of the Developer Portal (e.g. dev.contoso.com) | |
MANAGEMENT_GW_HOSTNAME | The hostname of the management plane (e.g. mgt.contoso.com) | |
SUBSCRIPTION_ID | The subscription ID for the Azure subscription used to deploy the resources in this repo | |
SHARED_KEY | The shared key needed for the VPN connection. Provide a random key value here. | Azure VPN Gateway documentation |
Now go in the Actions Tab
Select Deploy APIM Infra
On the right menu click the Run workflow button and click the Run workflow green button.
The Github action will take around 45 minutes to complete. The Github action will create 3 new Github secrets needed to execute the next pipeline.
Now upload you generated or existing certificate in Azure KeyVault.
Go to the certificates tabs in your Azure KeyVault
From there click the Generate/Import button and import your pfx files from your certificate.
Once the certificate is imported in KeyVault click on it.
You will find a textbox with the label Secret Identifier.
Copy the value from that textbox you will need to create a Github secret.
Now you need to create a new Github secrets with the value copied before. The name of the secret is CERT_LINK.
Next go to your API Management and custom domains
Create a new hostname for the API Gateway related to your private DNS zone and select the certificate you uploaded in the KeyVault.
Now retrieve the private IP of the Api Management
Go to your Azure Private DNS Zone and create a new A record entry
Repeat the same step than before but this time is for the developer portal. Be sure to add the record in the Azure Private DNS Zone using the same private IP.
Do the same for the Management, at the end you should see something like this in your Domains for Azure API Management.
This will be what your Azure Private DNS Zone will look like at the end.
Login in to your jumpbox, from there go to the Azure Portal
Go to your APIM, and press the Developer Portal button.
From there, you will enter a designer, if an error occurs refresh the page.
In the designer you need to publish your website using the publish button.
Now you are ready to run the next Github Action, go back to Github Action and select Deploy Application Gateway Infra and run the worflow.
Once the Github Action is executed go to your Application Gateway and in the menu Backend health. Be sure the Application Gateway can reach the APIM Gateway.
Get the public ip of the App GW and add a record in your Azure Public DNS Zone.
Use the jumpbox to test the nslookup resolution like the example below.
Normally this should use the private IP
Now do a nslookup from your computer, this should use the public ip of the Application Gateway (it can take up to 24 hours to work depending of your DNS server).
Using again the public IP of the Application Gateway, you will do the same than the previous step but for the DNS name of the developer portal this time.
Now everything is setup.
Using again the public IP of the Application Gateway, you will do the same than the previous step but for the DNS name of the management plane this time.
This sample create two resources group, each one with a VPN Gateway, you will need to create a connection between them to mock cloud to on premise environment.
For more details how to do this click here
If an error of Keyvault soft delete occurs when running the Github action this mean you have some keyvault pending because of the soft delete.
In this case you need to run those commands in the proper subscription using Azure CLI.
$ az keyvault list-deleted
$ az keyvault purge --name <name of the vault>
Those steps are only required if you want to deploy the web application provided in this sample.
This Github contains 3 app used for the demo
The TodoWeb is the front end MVC app, the TodoApi is the one hosted in the cloud and Weather API is the one hosted in the Virtual Machine.
How to deploy those applications are out of this scope, but the next section will show you what you need to register in your Azure Active Directory to be able to run those sample apps.
You will need to create 3 applications registration in Azure AD, the flow used here is this one.
What is really important is the scope you create in TodoApi and WeatherApi.
For TodoApi you need to create one scope called Todo.Api.All and for WeatherApi the scope is Weather.Get.All.
Once you have those the two APIs created with the proper scope just give permission to those scope to TodoWeb.
Be sure next to create the Application Secret for the TodoWeb app.
For more details about using Azure Active Directory with .Net Application refer to the officiel Microsoft documentation.
Important
In the manifest file of all three application be sure to set the version of the property accessTokenAcceptedVersion to the value 2.
Here the appsettings of TodoApi that you need to configure in the WebApp in the Azure Portal.
[
{
"name": "AzureAd:ClientId",
"value": "<ClientID of the TodoApi in Azure AD>",
"slotSetting": false
},
{
"name": "AzureAd:Instance",
"value": "https://login.microsoftonline.com/",
"slotSetting": false
},
{
"name": "AzureAd:TenantId",
"value": "<Your AzureAD Tenant ID>",
"slotSetting": false
},
{
"name": "ConnectionStrings:Sql",
"value": "<Sql Connection string of the SQL Azure>",
"slotSetting": false
},
{
"name": "WEBSITE_NODE_DEFAULT_VERSION",
"value": "6.9.1",
"slotSetting": false
}
]
Now you can publish the TodoWeb to Azure using Visual Studio or Azure CLI.
You can now configure the TodoApi in APIM with the policy you want to test.
This application is different and hosted in the virtual machine called win1api. You will need to connect to this virtual machine with RDP and first install IIS from the server role.
Once is done you will need to install .Net Core 3.1 hosting bundle
You can find the Microsoft .Net core here
Now you can install your .Net Core application in ISS, once is done modify the appsettings.json with those parameters.
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "<TenantId of your Azure AD>",
"ClientId": "<ClientId of Weather App in Azure AD>"
}
}
You can now configure the Weather in APIM with the policy you want to test.
Here the appsettings of TodoWeb that you need to configure in the WebApp in the Azure Portal.
[
{
"name": "AzureAd:CallbackPath",
"value": "/signin-oidc",
"slotSetting": false
},
{
"name": "AzureAd:ClientId",
"value": "<The ClientId of TodoWeb in AzureAD>",
"slotSetting": false
},
{
"name": "AzureAd:ClientSecret",
"value": "<The ClientSecret of TodoWeb in AzureAD>",
"slotSetting": false
},
{
"name": "AzureAd:Instance",
"value": "https://login.microsoftonline.com/",
"slotSetting": false
},
{
"name": "AzureAd:SignedOutCallbackPath",
"value": "/signout-callback-oidc",
"slotSetting": false
},
{
"name": "AzureAd:TenantId",
"value": "<Your Azure AD TenantId>",
"slotSetting": false
},
{
"name": "TodoList:ApiAccessKey",
"value": "<Subscription Key of APIM to call TodoApi>",
"slotSetting": false
},
{
"name": "TodoList:TodoListAppId",
"value": "<ClientId of TodoApi>",
"slotSetting": false
},
{
"name": "TodoList:TodoListBaseAddress",
"value": "<BaseUrl Of TodoApi from APIM>",
"slotSetting": false
},
{
"name": "TodoList:TodoListScope",
"value": "api://<ClientId of TodoApi>/Todo.Api.All",
"slotSetting": false
},
{
"name": "WeatherApp:ApiAccessKey",
"value": "<Subscription Key of APIM to call Weather Api>",
"slotSetting": false
},
{
"name": "WeatherApp:WeatherAppId",
"value": "<ClientId of WeatherApi>",
"slotSetting": false
},
{
"name": "WeatherApp:WeatherBaseAddress",
"value": "<BaseUrl of WeatherApi From APIM>",
"slotSetting": false
},
{
"name": "WeatherApp:WeathertScope",
"value": "api://<ClientId of WeatherApi>/Weather.Get.All",
"slotSetting": false
},
{
"name": "WEBSITE_NODE_DEFAULT_VERSION",
"value": "6.9.1",
"slotSetting": false
}
]
Now you can publish the TodoWeb to Azure using Visual Studio or Azure CLI.