Quickstart - Azure App Service API with Bicep

Welcome to the Quickstart series, where I dive into building practical Azure solutions using Bicep and setting up automated CI/CD pipelines with GitHub Actions. Each post in this series provides a guided approach to deploying essential cloud resources, complete with infrastructure as code (IaC) templates and seamless GitHub Actions workflows for continuous integration and deployment.

In this post, I’ll walk you through a project, where I deployed a sample API to Azure using Bicep. This solution leverages several Azure services like App Service, Azure Container Registry, and Role-Based Access Control (RBAC) to create a scalable and secure API environment. This approach highlights the advantages of automating deployments and configurations for consistent and repeatable infrastructure.

GitHub - Latzox/quickstart-azure-app-service-api: A template for your api built with docker on azure app service
A template for your api built with docker on azure app service - Latzox/quickstart-azure-app-service-api

Overview of the Project

This sample project deploys an API using Azure App Service with a managed identity and an Azure Container Registry (ACR) to manage and secure our container images. I created this setup to illustrate best practices for deploying containerized applications in Azure, including handling identity, role assignments, and modularized Bicep configurations.

Below, I'll break down the main steps and components within the Bicep template.

Project Goals

The primary objectives of this project were:

  • Deploy a sample containerized API on Azure App Service.
  • Use Azure Container Registry (ACR) to store and manage the container image.
  • Assign the necessary role to allow the App Service to pull from the ACR securely.
  • Modularize the Bicep template for reusability and flexibility.

Project Setup

Let’s dive into the main Bicep template that automates the deployment of all these resources. Here’s a breakdown of the parameters, resources, and modules involved.

Parameters Explained

Parameters make this Bicep template adaptable and easy to configure for various environments:

  • Deployment Location (deploymentLocation): Specifies the Azure region.
  • Web App Base Name (webAppNameBase): Base name for the web application, ensuring a consistent naming convention.
  • Container Registry Name (registryName): The name for the ACR where the container image is stored.
  • Deployment Toggles (deployAcr, deployRoleAssignment, deployApi): Boolean values to control which resources to deploy (ACR, role assignment, and API).
  • Role Definition ID (roleDefinitionId): Defines the role required for the App Service to pull from ACR.
  • Subscription IDs (subIdSharedServices, subIdSampleApi): IDs for separate subscriptions, enhancing security by segregating services.
  • SKU for App Service Plan (aspSkuName): Specifies the App Service Plan tier for scaling.
  • Docker Image (dockerImage): Image name and tag from the ACR to deploy to the App Service.
  • Resource Group Names (identityResourceGroup, apiResourceGroup, acrResourceGroup): Defines resource groups for different components to keep resources organized.

Resources and Modules

This template relies on several Azure resources and modules to handle the main components.

Resource Groups

Resource groups are created to manage the resources for identity and API separately, which helps with organization and lifecycle management.

  • Identity Resource Group (identityRg): Contains resources related to managed identities.
  • API Resource Group (apiRg): Hosts resources needed for the App Service API, like the App Service itself.

Modules

Breaking down deployments into modules enhances the readability and reusability of Bicep files. Here are the key modules in this setup:

1. Azure Container Registry (ACR)

The ACR module deploys the container registry if deployAcr is set to true. This module handles the configuration of the ACR, setting its location, name, and SKU:

module acr 'acr/acr.bicep' = if (deployAcr) {
  name: 'acr-deployment'
  scope: resourceGroup(subIdSharedServices, acrResourceGroup)
  params: {
    location: deploymentLocation
    registryName: registryName
    sku: 'Standard'
  }
}

2. Role Assignment

The Role Assignment module assigns the appropriate permissions for the App Service to access the ACR securely. This setup simplifies managing permissions by automating the RBAC process:

module roleAssignment 'roleassignment/role.bicep' = if (deployRoleAssignment) {
  name: 'roleassignment-deployment'
  scope: resourceGroup(subIdSampleApi, identityResourceGroup)
  params: {
    roleDefinitionId: roleDefinitionId
    webAppNameBase: webAppNameBase
  }
  dependsOn: [
    identityRg
    acr
  ]
}

3. Web Application (App Service)

Finally, the App Service module deploys the actual API if deployApi is true. It uses parameters for the App Service Plan SKU, Docker image, and managed identity details. This module is responsible for configuring the web application and linking it to the managed identity created in the Role Assignment module:

module app 'app/app.bicep' = if (deployApi) {
  name: 'app-deployment'
  scope: resourceGroup(subIdSampleApi, apiResourceGroup)
  params: {
    aspSkuName: aspSkuName
    dockerImage: dockerImage
    webAppNameBase: webAppNameBase
    managedIdentityId: roleAssignment.outputs.managedIdentityId
    managedIdentityClientId: roleAssignment.outputs.managedIdentityClientId
  }
  dependsOn: [
    apiRg
  ]
}

Deploying the Solution

To deploy this solution, I've set up a GitHub Actions pipeline that automates the deployment process. The pipeline, available in the project’s public GitHub repository, includes both preview and production jobs, providing flexibility and control over the deployment.

Ensure the required secrets are set up in the GitHub repository’s settings. Check out the blog post about creating service principal for RBAC with PowerShell to quickly prepare a secure identity for your workflow to authenticate to Azure Services.

Using PowerShell to Create Service Principals for RBAC
In this blog post, I’ll guide you through the process of creating a service principal using PowerShell, including steps for retrieving secrets and leveraging federated credentials for secure, secretless authentication in workflows like GitHub Actions. Managing programmatic access to your Azure resources securely is essential, and a service principal

This setup provides a streamlined, automated approach to deploy and manage infrastructure changes with Bicep, ensuring consistency and reliability across environments. You can follow the repository link to get started and customize it for your specific requirements.