Use Microsoft Entra authentication for the self-hosted gateway

APPLIES TO: Developer | Premium

The Azure API Management self-hosted gateway needs connectivity with its associated cloud-based API Management instance for reporting status, checking for and applying configuration updates, and sending metrics and events.

In addition to using a gateway access token (authentication key) to connect with its cloud-based API Management instance, you can enable the self-hosted gateway to authenticate to its associated cloud instance by using an Microsoft Entra app. With Microsoft Entra authentication, you can configure longer expiry times for secrets and use standard steps to manage and rotate secrets in Active Directory.

Scenario overview

The self-hosted gateway configuration API can check Azure RBAC to determine who has permissions to read the gateway configuration. After you create a Microsoft Entra app with those permissions, the self-hosted gateway can authenticate to the API Management instance using the app.

To enable Microsoft Entra authentication, complete the following steps:

  1. Create two custom roles to:
    • Let the configuration API get access to customer's RBAC information
    • Grant permissions to read self-hosted gateway configuration
  2. Grant RBAC access to the API Management instance's managed identity
  3. Create a Microsoft Entra app and grant it access to read the gateway configuration
  4. Deploy the gateway with new configuration options

Prerequisites

Limitations notes

  • Only system-assigned managed identity is supported.

Create custom roles

Create the following two custom roles that are assigned in later steps. You can use the permissions listed in the following JSON templates to create the custom roles using the Azure portal, Azure CLI, Azure PowerShell, or other Azure tools.

When configuring the custom roles, update the AssignableScopes property with appropriate scope values for your directory, such as a subscription in which your API Management instance is deployed.

API Management Configuration API Access Validator Service Role

{
  "Description": "Can access RBAC permissions on the API Management resource to authorize requests in Configuration API.",
  "IsCustom": true,
  "Name": "API Management Configuration API Access Validator Service Role",
  "Permissions": [
    {
      "Actions": [
        "Microsoft.Authorization/*/read"
      ],
      "NotActions": [],
      "DataActions": [],
      "NotDataActions": []
    }
  ],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/{subscriptionID}"
  ]
}

API Management Gateway Configuration Reader Role

{
  "Description": "Can read self-hosted gateway configuration from Configuration API",
  "IsCustom": true,
  "Name": "API Management Gateway Configuration Reader Role",
  "Permissions": [
    {
      "Actions": [],
      "NotActions": [],
      "DataActions": [
        "Microsoft.ApiManagement/service/gateways/getConfiguration/action"
      ],
      "NotDataActions": []
    }
  ],
  "NotDataActions": [],
  "AssignableScopes": [
    "/subscriptions/{subscriptionID}"
  ]
}

Add role assignments

Assign API Management Configuration API Access Validator Service Role

Assign the API Management Configuration API Access Validator Service Role to the managed identity of the API Management instance. For detailed steps to assign a role, see Assign Azure roles using the portal.

  • Scope: The resource group or subscription in which the API Management instance is deployed
  • Role: API Management Configuration API Access Validator Service Role
  • Assign access to: Managed identity of API Management instance

Assign API Management Gateway Configuration Reader Role

Step 1: Register Microsoft Entra app

Create a new Microsoft Entra app. For steps, see Create a Microsoft Entra application and service principal that can access resources. This app will be used by the self-hosted gateway to authenticate to the API Management instance.

  • Generate a client secret
  • Take note of the following application values for use in the next section when deploying the self-hosted gateway: application (client) ID, directory (tenant) ID, and client secret

Step 2: Assign API Management Gateway Configuration Reader Service Role

Assign the API Management Gateway Configuration Reader Service Role to the app.

  • Scope: The API Management instance (or resource group or subscription in which it's deployed)
  • Role: API Management Gateway Configuration Reader Role
  • Assign access to: Microsoft Entra app

Deploy the self-hosted gateway

Deploy the self-hosted gateway to Kubernetes, adding Microsoft Entra app registration settings to the data element of the gateways ConfigMap. In the following example YAML configuration file, the gateway is named mygw and the file is named mygw.yaml.

Important

If you're following the existing Kubernetes deployment guidance:

  • Make sure to omit the step to store the default authentication key using the kubectl create secret generic command.
  • Substitute the following basic configuration file for the default YAML file that's generated for you in the Azure portal. The following file adds Microsoft Entra configuration in place of configuration to use an authentication key.
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mygw-env
  labels:
    app: mygw
data:
  config.service.endpoint: "<service-name>.configuration.azure-api.net"
  config.service.auth: azureAdApp 
  config.service.auth.azureAd.authority: "https://login.microsoftonline.com"  
  config.service.auth.azureAd.tenantId: "<Azure AD tenant ID>" 
  config.service.auth.azureAd.clientId: "<Azure AD client ID>" 
  config.service.auth.azureAd.clientSecret: "<Azure AD client secret>"
  gateway.name: <gateway-id>
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mygw
  labels:
    app: mygw
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mygw
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 0
      maxSurge: 25%
  template:
    metadata:
      labels:
        app: mygw
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: mygw
        image: mcr.microsoft.com/azure-api-management/gateway:v2
        ports:
        - name: http
          containerPort: 8080
        - name: https
          containerPort: 8081
          # Container port used for rate limiting to discover instances
        - name: rate-limit-dc
          protocol: UDP
          containerPort: 4290
          # Container port used for instances to send heartbeats to each other
        - name: dc-heartbeat
          protocol: UDP
          containerPort: 4291
        readinessProbe:
          httpGet:
            path: /status-0123456789abcdef
            port: http
            scheme: HTTP
          initialDelaySeconds: 0
          periodSeconds: 5
          failureThreshold: 3
          successThreshold: 1
        envFrom:
        - configMapRef:
            name: mygw-env
---
apiVersion: v1
kind: Service
metadata:
  name: mygw-live-traffic
  labels:
    app: mygw
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  ports:
  - name: http
    port: 80
    targetPort: 8080
  - name: https
    port: 443
    targetPort: 8081
  selector:
    app: mygw
---
apiVersion: v1
kind: Service
metadata:
  name: mygw-instance-discovery
  labels:
    app: mygw
  annotations:
    azure.apim.kubernetes.io/notes: "Headless service being used for instance discovery of self-hosted gateway"
spec:
  clusterIP: None
  type: ClusterIP
  ports:
  - name: rate-limit-discovery
    port: 4290
    targetPort: rate-limit-dc
    protocol: UDP
  - name: discovery-heartbeat
    port: 4291
    targetPort: dc-heartbeat
    protocol: UDP
  selector:
    app: mygw

Deploy the gateway to Kubernetes with the following command:

kubectl apply -f mygw.yaml

Confirm that the gateway is running

  1. Run the following command to check if the deployment succeeded. It might take a little time for all the objects to be created and for the pods to initialize.

    kubectl get deployments
    

    It should return

    NAME             READY   UP-TO-DATE   AVAILABLE   AGE
    <gateway-name>   1/1     1            1           18s
    
  2. Run the following command to check if the services were successfully created. Your service IPs and ports will be different.

    kubectl get services
    

    It should return

    NAME                                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
    <gateway-name>-live-traffic         ClusterIP      None            <none>        4290/UDP,4291/UDP   9m1s
    <gateway-name>-instance-discovery   LoadBalancer   10.99.236.168   <pending>     80:31620/TCP,443:30456/TCP   9m1s
    
  3. Go back to the Azure portal and select Overview.

  4. Confirm that Status shows a green check mark, followed by a node count that matches the number of replicas specified in the YAML file. This status means the deployed self-hosted gateway pods are successfully communicating with the API Management service and have a regular "heartbeat." Screenshot showing status of self-hosted gateway in the portal.

Tip

  • Run the kubectl logs deployment/<gateway-name> command to view logs from a randomly selected pod if there's more than one.
  • Run kubectl logs -h for a complete set of command options, such as how to view logs for a specific pod or container.

Next steps