- Create a Resource Group for entire project
- Create an API Management Service
- Create an Function App
- Create a Web App
- Create an AKS Cluster
- Create an Azure Container Registry
- Create a Blob Storage
- Create an Active Directory B2C Tenant and App
- Prerequisites
- Create a Resource Group
- Create API Management Service
- Create Students Microservice
- Create Teachers Microservice
- Create Workers Microservice
- Hosting Serverless UI on Azure Blob Storage
- Securing EMR Application
- Azure Subscription
- Azure CLI
- kubectl CLI
- Docker CLI
- Donet 6
- Node 16
- Visual Studio (Community/Enterprise)
- Go to Azure Portal
- Create a resource group - schoolapp in your subscription
- Go to Azure Portal
- Create a resource - API Management
- In Project Details
Subscription
- Choose your subscriptionResource Group
- Choose schoolapp resource groupRegion
- Choose West EuropeResource name
- Choose schoolappapimanagement # Must be globally uniqueOrganization name
- Choose your organization nameAdministrator email
- Choose your administrator emailPricing tier
- Choose Consumption tierSystem assigned managed identity
- Mark the StatusConnectivity type
- None
- Review + create
- Create
NOTE: API creation may take around 40-50 minutes.
- Go to Azure Portal
- Create a resource - Azure Cosmos DB
- Choose - Azure Cosmos DB for NoSQL
Subscription
- Choose your subscriptionResource Group
- Choose schoolapp resource groupAccount Name
- Choose unique account nameLocation
- Choose your locationCapacity mode
- Provisioned throughputApply Free Tier Discount
- Apply if you want discount
- Review + create
- Create
- Go to your CosmosDB account
- Go to Data Explorer.
- Create a Container
Database id
- studentdbDatabase throughput
- Manual - 400Container id
- studentsdbcontainerPartition key
- /email
- Go to studentsdbcontainer -> Items
- New Item
{
"Email": "student1@mtc.com",
"Name": "Student One",
"Age": 22,
"Gender": "Male",
"Class": "History"
}
- Save
Create Function App for Students api
- Go to your API management - schoolappapimanagement
- Select APIs
- In Define a new API select Function App
NOTE: If you don't see your function app in the functions list, create a managed identity and give a contributor role to your function app
- Check all your functions and hit Select
API URL suffix
- Choose students.- Hit Create.
- Go to deleteStudent and getStudent functions.
- Edit Frontend.
. - Under Query add an email parameter and check required box.
- Hit Save.
- Test the APIs.
NOTE: To test your API in API clients like POSTMAN, you need to add a Header with key - Ocp-Apim-Subscription-Key and value of Subscriptions key from the Subscription section in the API blade
- Go to Azure Portal
- Create a resource - SQL Database
Subscription
- Choose your subscriptionResource Group
- Choose schoolapp resource groupDatabase Name
- Choose teachersdbServer
- Hit Create newServer name
- Choose unique server name for exampleLocation
- Choose West EuropeAuthentication method
- Use SQL authentication and choose admin login and password- Hit Ok
Compute + storage
- Choose Configure databaseService tier
- select DTU-based purchasing model - Basic- Hit Apply
Backup storage redundancy
- Choose Locally-redundant backup storageConnectivity method
- Select Public endpoint (For this demo only)- Allow Azure services and resource to access this tier - Yes.
- Add current client IP address - Yes.
- Review + create
- Create
Location
- Choose your locationCapacity mode
- Provisioned throughputApply Free Tier Discount
- Apply if you want discount- Go to your SQL server blade
Public network access
- Selected networks -> Add your ip addressAllow Azure services and resources to access this server
- Check
- Go to teachersdb database
- Choose Query editor in database blade
- Login with sql server admin credentials
- In Query Editor create teachers table:
CREATE TABLE Teachers ( Id int IDENTITY(1,1) PRIMARY KEY, Email varchar(255) UNIQUE, Name varchar(255), Age int, Gender varchar(255), Class varchar(255) );
- In Query Editor create few rows:
INSERT INTO Teachers (Email, Name, Age, Gender, Class) VALUES ('Teacher1@mtc.com', 'Teacher One', 45, 'Male', 'History') INSERT INTO Teachers (Email, Name, Age, Gender, Class) VALUES ('Teacher2@mtc.com', 'Teacher Two', 32, 'Female', 'Math') INSERT INTO Teachers (Email, Name, Age, Gender, Class) VALUES ('Teacher3@mtc.com', 'Teacher Three', 29, 'Female', 'Computer Science')
Create AppService for Teachers API
-
Go to your API management - schoolappapimanagement
-
Select APIs
-
Select Add API
-
From the API list select OpenAPI
-
OpenAPI specification
- Paste the swagger url -
Hit Create
-
Your API is going to look like this:
-
Test the routes from the API management
- Go to Azure Portal
- Create a resource - SQL Database
Subscription
- Choose your subscriptionResource Group
- Choose schoolapp resource groupDatabase Name
- Choose workersdbServer
- Choose the same server you created in teachers microservice for exampleCompute + storage
- Choose Configure databaseService tier
- select DTU-based purchasing model - Basic- Hit Apply
Capacity mode
- Provisioned throughputApply Free Tier Discount
- Apply if you want discount- Go to your SQL server blade
Public network access
- Selected networks -> Add your ip addressAllow Azure services and resources to access this server
- Check
- Go to workersdb database
- Choose Query editor in database blade
- Login with sql server admin credentials
- In Query Editor create teachers table:
CREATE TABLE Workers ( Id int IDENTITY(1,1) PRIMARY KEY, Email varchar(255) UNIQUE, Name varchar(255), Age int, Gender varchar(255), );
- In Query Editor create few rows:
INSERT INTO Workers (Email, Name, Age, Gender) VALUES ('Worker1@mtc.com', 'Worker One', 27, 'Male') INSERT INTO Workers (Email, Name, Age, Gender) VALUES ('Worker2@mtc.com', 'Worker Two', 23, 'Female') INSERT INTO Workers (Email, Name, Age, Gender) VALUES ('Worker3@mtc.com', 'Worker Three', 35, 'Female') INSERT INTO Workers (Email, Name, Age, Gender) VALUES ('Worker4@mtc.com', 'Worker Four', 51, 'Male')
NOTE: We recommend the use of Azure Cloud Shell for all command line operations below.
-
Create AD service principal.
az ad sp create-for-rbac -o json > auth.json appId=$(jq -r ".appId" auth.json) password=$(jq -r ".password" auth.json)
-
Create Environment variables:
objectId=$(az ad sp show --id $appId --query "id" -o tsv) location="westeurope" kubernetesVersion=$(az aks get-versions --location $location --query "orchestrators[-1].orchestratorVersion" -o tsv)
-
Paste the entire command below (It is a single command on multiple lines) in Cloud Shell to create the
parameters.json
file. It will be used in the ARM template deployment.cat <<EOF > parameters.json { "aksServicePrincipalAppId": { "value": "$appId" }, "aksServicePrincipalClientSecret": { "value": "$password" }, "aksServicePrincipalObjectId": { "value": "$objectId" }, "aksEnableRBAC": { "value": false }, "kubernetesVersion":{"value":"$kubernetesVersion"} } EOF
To deploy an RBAC enabled cluster, set the
aksEnabledRBAC
field totrue
. View the contents of the newly created file withcat parameters.json
. It will contain the values of theappId
,password
, andobjectId
bash variables from the previous steps. -
Deploy Components
The next few steps will add the following list of components to your Azure subscription:
- Azure Kubernetes Service
- Application Gateway v2
- Virtual Network with 2 subnets
- Public IP Address
- Managed Identity, which will be used by AAD Pod Identity
-
Download the ARM template into
template.json
file. Paste the following in your shell:wget https://raw.githubusercontent.com/Azure/application-gateway-kubernetes-ingress/master/deploy/azuredeploy.json -O template.json
-
Deploy the ARM template via Azure Cloud Shell and the
az
tool. Modify the name of the resource group and region/location, then paste each of the following lines into your shell:resourceGroupName="schoolapp" deploymentName="school-ingress-appgw" az group create -n $resourceGroupName -l $location # Use only if you want to deploy in a new resource group. az deployment group create -g $resourceGroupName -n $deploymentName --template-file template.json --parameters parameters.json
Note: The last command may take a few minutes to complete.
3. Once the deployment finished, download the deployment output into a file nameddeployment-outputs.json
.az deployment group show -g $resourceGroupName -n $deploymentName --query "properties.outputs" -o json > deployment-outputs.json
View the content of the newly created file with:
cat deployment-outputs.json
. The file will have the following shape (example):{ "aksApiServerAddress": { "type": "String", "value": "aks-abcd41e9.hcp.westus2.azmk8s.io" }, "aksClusterName": { "type": "String", "value": "aksabcd" }, "applicationGatewayName": { "type": "String", "value": "applicationgatewayabcd" }, "identityClientId": { "type": "String", "value": "7b1a3378-8abe-ab58-cca9-a8ef624db293" }, "identityResourceId": { "type": "String", "value": "/subscriptions/a6466a81-bf0d-147e-2acb-a0ba50f6456e/resourceGroups/MyResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/appgwContrIdentityabcd" }, "resourceGroupName": { "type": "String", "value": "MyResourceGroup" }, "subscriptionId": { "type": "String", "value": "a6466a81-bf0d-147e-2acb-a0ba50f6456e" } }
-
Set up Application Gateway Ingress Controller
With the instructions in the previous section we created and configured a new AKS cluster and an App Gateway. We are now ready to deploy a workers app and an ingress controller to our new Kubernetes infrastructure.-
Setup Kubernetes Credentials
For the following steps we need setup kubectl command, which we will use to connect to our new Kubernetes cluster. Cloud Shell haskubectl
already installed. We will useaz
CLI to obtain credentials for Kubernetes.Get credentials for your newly deployed AKS (read more):
# use the deployment-outputs.json created after deployment to get the cluster name and resource group name aksClusterName=$(jq -r ".aksClusterName.value" deployment-outputs.json) resourceGroupName=$(jq -r ".resourceGroupName.value" deployment-outputs.json) az aks get-credentials --resource-group $resourceGroupName --name $aksClusterName
Test the connection:
kubectl get nodes
-
Install AAD Pod Identity
Azure Active Directory Pod Identity provides token-based access to Azure Resource Manager (ARM).
AAD Pod Identity will add the following components to your Kubernetes cluster:
- Kubernetes CRDs:
AzureIdentity
,AzureAssignedIdentity
,AzureIdentityBinding
- Managed Identity Controller (MIC) component
- Node Managed Identity (NMI) component
To install AAD Pod Identity to your cluster:
-
RBAC enabled AKS cluster
kubectl apply -f https://raw.githubusercontent.com/Azure/aad-pod-identity/v1.8.6/deploy/infra/deployment-rbac.yaml
-
RBAC disabled AKS cluster
kubectl apply -f https://raw.githubusercontent.com/Azure/aad-pod-identity/v1.8.6/deploy/infra/deployment.yaml
Note: AAD Pod Identity introduced a breaking change after v1.5.5 regarding CRD fields become case sensitive, for any AAD Pod Identity version >= 1.6.0 or you plan to apply from master branch such as https://raw.githubusercontent.com/Azure/aad-pod-identity/master/deploy/infra/deployment-rbac.yaml, AGIC version at least v1.2.0-rc2 will be required, more details please refer to troubleshooting.
Check if all pods are running:
kubectl get pods
- Kubernetes CRDs:
-
Install AGIC with Helm
Helm is a package manager for Kubernetes. This document will use version 3 of helm, which is not backwards compatible with previous versions.
-
Add the AGIC Helm repository:
helm repo add application-gateway-kubernetes-ingress https://appgwingress.blob.core.windows.net/ingress-azure-helm-package/ helm repo update
-
Install Ingress Controller Helm Chart
-
Use the
deployment-outputs.json
file created above and create the following variables.applicationGatewayName=$(jq -r ".applicationGatewayName.value" deployment-outputs.json) resourceGroupName=$(jq -r ".resourceGroupName.value" deployment-outputs.json) subscriptionId=$(jq -r ".subscriptionId.value" deployment-outputs.json) identityClientId=$(jq -r ".identityClientId.value" deployment-outputs.json) identityResourceId=$(jq -r ".identityResourceId.value" deployment-outputs.json)
-
-
Download sample-helm-config.yaml, which will configure AGIC:
wget https://raw.githubusercontent.com/Azure/application-gateway-kubernetes-ingress/master/docs/examples/sample-helm-config.yaml -O helm-config.yaml
-
Edit the newly downloaded helm-config.yaml and fill out the sections
appgw
andarmAuth
.sed -i "s|<subscriptionId>|${subscriptionId}|g" helm-config.yaml sed -i "s|<resourceGroupName>|${resourceGroupName}|g" helm-config.yaml sed -i "s|<applicationGatewayName>|${applicationGatewayName}|g" helm-config.yaml sed -i "s|<identityResourceId>|${identityResourceId}|g" helm-config.yaml sed -i "s|<identityClientId>|${identityClientId}|g" helm-config.yaml
-
Install the Application Gateway ingress controller package:
Check the latest stable versionhelm install ingress-azure \ -f helm-config.yaml \ application-gateway-kubernetes-ingress/ingress-azure \ --version 1.5.2
Note: Use at least version 1.4.0, i.e.
--version 1.4.0
, when installing on k8s version >= 1.16. Kubernetes >= 1.22 requires version 1.5.0 (or higher).
-
-
az aks update --name <aksClusterName> --resource-group schoolapp --enable-oidc-issuer
az aks addon list -g schoolapp -n <aksClusterName> # show addon list
- Open Cloud Shell
- Run:
az aks enable-addons --addons azure-keyvault-secrets-provider --name $aksClusterName --resource-group $resourceGroupName
- Verify the Azure Key Vault Provider for Secrets Store CSI Driver installation:
kubectl get pods -n kube-system -l 'app in (secrets-store-csi-driver, secrets-store-provider-azure)' NAME READY STATUS RESTARTS AGE aks-secrets-store-csi-driver-4vpkj 3/3 Running 2 4m25s aks-secrets-store-csi-driver-ctjq6 3/3 Running 2 4m21s aks-secrets-store-csi-driver-tlvlq 3/3 Running 2 4m24s aks-secrets-store-provider-azure-5p4nb 1/1 Running 0 4m21s aks-secrets-store-provider-azure-6pqmv 1/1 Running 0 4m24s aks-secrets-store-provider-azure-f5qlm 1/1 Running 0 4m25s
Create a Key Vault and store the secrets for database connection - Optional ( Need to configure an aks cluster for key-vault connection )
- Go to Azure Portal
- Create a resource - Key Vault
- In Key Vault details:
Subscription
- Choose your subscriptionResource Group
- Choose schoolapp resource groupKey vault name
- Choose a unique nameRegion
- Choose West EuropePricing tier
- Standard
- Review + create
- Create
- Go to Azure Portal
- Create a Container Registry
- In Registry details:
Subscription
- Choose your subscriptionResource Group
- Choose schoolapp resource groupRegistry Name
- Choose a unique nameLocation
- Choose West EuropeSKU
- Standard
- Review + create
- Create
- Configure ACR integration with our AKS cluster
- Open Cloud Shell
- Integrate an existing ACR with existing AKS clusters by supplying valid values for acr-name or acr-resource-id as below.
acrId=$(az acr show -n <registryName> -g schoolapp --query id) az aks update -n $aksClusterName -g $resourceGroupName --attach-acr $acrId
-
Open Cloud Shell
-
Clone the git repo
-
Open the project - ./nodejs_aks_backend_workers_api/
-
Change the configuration in config.js file to connect to the DB
-
Build the image and push it to your ACR:
az acr build --image workers:0.1 --registry <registryName> --file Dockerfile .
-
In the workers-k8s.yaml file, replace the image name with yours, the file will have the following shape (exmaple):
- image: "<registryName>.azurecr.io/workers:0.1" name: workersapp ports: - containerPort: 8080 protocol: TCP
-
To create Pod, Service and Ingress resources run:
kubectl create -f workers-k8s.yaml
-
To show your ingress ip run:
kubectl get ingress
-
Open a web browser and check the app - http://ingressIpAddress:80
-
Clone the git repo
-
Open the project - multienvapponazure/nodejs_aks_backend_workers/swagger_output.json
-
Go to your API management - schoolappapimanagement
-
Select APIs
-
Select Add API
-
From the API list select OpenAPI
-
OpenAPI specification
- Paste the swagger file -
Hit Create
-
Your API is going to look like this:
-
Go to Settings
-
Change
Web service URL
- http://ingressIp/api -
Hit Save
-
Go to Azure Portal
-
Create a resource - Storage account
-
In Storage account details:
Subscription
- Choose your subscriptionResource Group
- Choose schoolapp resource groupStorage account name
- Choose a unique nameRegion
- Choose West EuropeRedundancy
- LRS
-
Hit Review
-
Hit Create
-
Go to resource
-
In left navigation panel choose Static website
-
in Static Website details:
Static website
- Enabledindex document name
- index.htmlError document path
- index.html
-
Hit Save
-
Go your storage account and select Storage browser
-
In Blob containers select $web - It is the place where you upload a website.
-
Clone the git repo
-
Open the project - ./react_frontend_website_no_authentication
-
Edit Api.js file and configure a baseUrl and Ocp-Apim-Subscription-Key
-
Run
npm install
-
Run
npm run build
- Build a project and store it in a build directory -
Upload all files to $web directory in a storage account
-
In left navigation panel choose Static website
-
Copy the Primary endpoint url and test in your web browser
- Identity management service
- Sign up and sign in using email address
- Sign in using social identity providers like Facebook, Google, Linkedin, etc.
- ADB2C Suppots OpenID Connect, OAuth 2.0 and SAML authentication protocols
- ADB2C manages user passwords
- Default sign up/sign in and password reset authentication flows
- Bring your own branding
- Serverless
- Azure ADB2C tenant different from Azure AD tenant
- Documentation: ADB2C , Pricing
Create Azure ADB2C:
-
Go to Azure Portal
-
Create a resource - Azure Active Directory B2C
-
Select Create a new Azure AD B2C Tenant
-
In Create a tenant details:
Organization name
- abschooltenantInitial domain name
- abschooltenantCountry/Region
- IrelandSubscription
- Choose your subscriptionResource Group
- Choose schoolapp resource group
-
Hit Review + Create
-
Hit Create
NOTE: Tenant creation may take around 5 minutes. -
To switch to your new directory select the directories + subscriptions icon:
-
Select your new directory and click Switch
-
In new created tenant go to Azure AD B2C Main page
-
In left side menu go to App registrations
-
Hit New registration
-
In Register an application:
Name
- schoolappSupported account types
- Select Accounts in any identity provider or organizational directory
-
Hit Register
-
In Overview click Add a Redirect URI
-
Hit +Add a platform
-
Select Web
-
In Configure Web:
Redirect URIs
- https://jwt.msImplicit grant and hybrid flows
- Check the Access tokens(used for implicit flows)
-
Hit Configure
-
Go to Azure AD B2C Home Page
-
In left side menu go to User flows
-
Hit +New user flow
-
Select Sign up and sign in User flow
-
Hit Create
-
In Create:
B2C_1_
- SignUpSigninLocal accounts
- Check Email signup
-
Hit Create
-
Select the user flow your create - B2C_1_SignUpSignin
-
In left side menu go to User attributes
-
Check a Email Address User attribute
-
Hit Save
-
Hit Run user flow
-
You can create a temporary email account here
-
Go to Azure B2C Home Page
-
In left side menu go to Users
-
Check if a new user you created exists in the list
- Switch back to your default directory
- Open your API service
- Select APIs
- Select a API
- In All operations under Inbound processing click +Add policy
- Choose Validate JWT
- Choose full to expand all the options
- Fill:
Header name
- AuthorizationFailed validation error message
- Missing or invalid tokenRequire expiration time
- YesRequire signed tokens?
- YesAudiences
- Go to AD B2C and copy your application (client) IDIssuers
- Go to AD B2C User flow -> Run user flow -> Open OpenID configuration url and copy the issuer urlOpen ID URLs
- Go to AD B2C User flow -> Run user flow -> Open OpenId configuration url and copy the url
- Hit Save
- Repeat the steps for all APIs