All skills
thomast1906 avatar

/apiops-deployment

@b198c92

Guides deployment of Azure API Management infrastructure using Infrastructure as Code (Bicep/Terraform), CI/CD pipelines (GitHub Actions/Azure DevOps), and APIOps workflows. Use when deploying APIM, creating pipelines, or implementing dev→test→prod promotion strategies.

Use this Skill: https://skilld.dev/gh/thomast1906/github-copilot-agent-skills/apiops-deployment

This session only. Nothing lands on disk.

referencesIaC_TEMPLATES.md

≈2.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Infrastructure as Code Templates

This reference file contains complete Bicep and Terraform templates for deploying Azure API Management in production configurations.

Bicep Templates

Complete Production APIM Instance

@description('Location for all resources')
param location string = 'uksouth'

@description('Environment name')
@allowed(['dev', 'staging', 'prod'])
param environment string

@description('Workload name')
param workloadName string

@description('Publisher email for APIM')
param publisherEmail string

@description('Publisher name for APIM')
param publisherName string

@description('VNet resource ID for VNet integration')
param vnetId string

@description('Subnet resource ID for APIM subnet')
param apimSubnetId string

var apimName = 'apim-${workloadName}-${environment}-${location}-001'
var logAnalyticsName = 'log-${workloadName}-${environment}-${location}-001'
var appInsightsName = 'appi-${workloadName}-${environment}-${location}-001'
var keyVaultName = 'kv-${workloadName}-${environment}-${location}-001'

var tags = {
  environment: environment
  project: workloadName
  'managed-by': 'bicep'
}

resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2022-10-01' = {
  name: logAnalyticsName
  location: location
  tags: tags
  properties: {
    sku: {
      name: 'PerGB2018'
    }
    retentionInDays: 90
  }
}

resource appInsights 'Microsoft.Insights/components@2020-02-02' = {
  name: appInsightsName
  location: location
  tags: tags
  kind: 'web'
  properties: {
    Application_Type: 'web'
    WorkspaceResourceId: logAnalytics.id
  }
}

resource apim 'Microsoft.ApiManagement/service@2023-05-01-preview' = {
  name: apimName
  location: location
  tags: tags
  sku: {
    name: environment == 'prod' ? 'Premium' : 'Developer'
    capacity: environment == 'prod' ? 2 : 1
  }
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    publisherEmail: publisherEmail
    publisherName: publisherName
    virtualNetworkType: 'Internal'
    virtualNetworkConfiguration: {
      subnetResourceId: apimSubnetId
    }
    customProperties: {
      'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Tls10': 'false'
      'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Tls11': 'false'
      'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Protocols.Ssl30': 'false'
      'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Tls10': 'false'
      'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Tls11': 'false'
      'Microsoft.WindowsAzure.ApiManagement.Gateway.Security.Backend.Protocols.Ssl30': 'false'
    }
  }
  zones: environment == 'prod' ? ['1', '2', '3'] : null
}

// Diagnostic settings
resource apimDiagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
  name: 'apim-diagnostics'
  scope: apim
  properties: {
    workspaceId: logAnalytics.id
    logs: [
      {
        categoryGroup: 'allLogs'
        enabled: true
        retentionPolicy: {
          days: 90
          enabled: true
        }
      }
    ]
    metrics: [
      {
        category: 'AllMetrics'
        enabled: true
      }
    ]
  }
}

// Application Insights logger
resource apimLogger 'Microsoft.ApiManagement/service/loggers@2022-08-01' = {
  name: 'appInsightsLogger'
  parent: apim
  properties: {
    loggerType: 'applicationInsights'
    credentials: {
      instrumentationKey: appInsights.properties.InstrumentationKey
    }
    isBuffered: true
    resourceId: appInsights.id
  }
}

output apimId string = apim.id
output apimName string = apim.name
output apimGatewayUrl string = apim.properties.gatewayUrl
output apimManagedIdentityPrincipalId string = apim.identity.principalId

APIM API Definition

param apimName string
param apiName string
param apiDisplayName string
param apiPath string
param backendUrl string

resource apim 'Microsoft.ApiManagement/service@2023-05-01-preview' existing = {
  name: apimName
}

resource api 'Microsoft.ApiManagement/service/apis@2022-08-01' = {
  name: apiName
  parent: apim
  properties: {
    displayName: apiDisplayName
    path: apiPath
    protocols: ['https']
    subscriptionRequired: true
    subscriptionKeyParameterNames: {
      header: 'Ocp-Apim-Subscription-Key'
      query: 'subscription-key'
    }
  }
}

resource backend 'Microsoft.ApiManagement/service/backends@2022-08-01' = {
  name: '${apiName}-backend'
  parent: apim
  properties: {
    url: backendUrl
    protocol: 'http'
    tls: {
      validateCertificateChain: true
      validateCertificateName: true
    }
  }
}

Terraform Templates

Provider Configuration

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "~> 4.0"
    }
  }
  required_version = ">= 1.9"
}

provider "azurerm" {
  features {}
}

APIM Resource

locals {
  apim_name = "apim-${var.workload_name}-${var.environment}-${var.location}-001"
  tags = {
    environment = var.environment
    project     = var.workload_name
    managed-by  = "terraform"
  }
}

resource "azurerm_api_management" "apim" {
  name                = local.apim_name
  location            = var.location
  resource_group_name = var.resource_group_name
  publisher_name      = var.publisher_name
  publisher_email     = var.publisher_email

  sku_name = var.environment == "prod" ? "Premium_2" : "Developer_1"

  identity {
    type = "SystemAssigned"
  }

  virtual_network_type = "Internal"
  virtual_network_configuration {
    subnet_id = var.apim_subnet_id
  }

  security {
    enable_backend_ssl30  = false
    enable_backend_tls10  = false
    enable_backend_tls11  = false
    enable_frontend_ssl30 = false
    enable_frontend_tls10 = false
    enable_frontend_tls11 = false
  }

  zones = var.environment == "prod" ? ["1", "2", "3"] : null

  tags = local.tags
}

resource "azurerm_monitor_diagnostic_setting" "apim" {
  name                       = "apim-diagnostics"
  target_resource_id         = azurerm_api_management.apim.id
  log_analytics_workspace_id = var.log_analytics_workspace_id

  enabled_log {
    category_group = "allLogs"
  }

  metric {
    category = "AllMetrics"
  }
}

Variables

variable "workload_name" {
  type        = string
  description = "Name of the workload"
}

variable "environment" {
  type        = string
  description = "Environment (dev, staging, prod)"
  validation {
    condition     = contains(["dev", "staging", "prod"], var.environment)
    error_message = "Must be dev, staging, or prod."
  }
}

variable "location" {
  type        = string
  description = "Azure region"
  default     = "uksouth"
}

variable "resource_group_name" {
  type        = string
  description = "Resource group name"
}

variable "publisher_name" {
  type        = string
  description = "APIM publisher name"
}

variable "publisher_email" {
  type        = string
  description = "APIM publisher email"
}

variable "apim_subnet_id" {
  type        = string
  description = "Subnet resource ID for APIM VNet integration"
}

variable "log_analytics_workspace_id" {
  type        = string
  description = "Log Analytics workspace resource ID"
}

GitHub Actions CI/CD Pipeline

Deploy APIM via Bicep

name: Deploy APIM Infrastructure

on:
  push:
    branches: [main]
    paths:
      - 'infrastructure/**'
  workflow_dispatch:
    inputs:
      environment:
        description: 'Target environment'
        type: choice
        options: [dev, staging, prod]

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ github.event.inputs.environment || 'dev' }}
    steps:
      - uses: actions/checkout@v4

      - name: Azure Login (OIDC)
        uses: azure/login@v2
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

      - name: Deploy Bicep
        uses: azure/arm-deploy@v2
        with:
          scope: resourcegroup
          resourceGroupName: rg-apim-${{ github.event.inputs.environment || 'dev' }}-001
          template: infrastructure/main.bicep
          parameters: >
            environment=${{ github.event.inputs.environment || 'dev' }}
            publisherEmail=${{ secrets.APIM_PUBLISHER_EMAIL }}
            publisherName=${{ secrets.APIM_PUBLISHER_NAME }}

Source: SKILL.md on GitHub

1 warning14d4 checks · Risk SAFE
  • Gen Agent Trust Hub14d

    The skill provides comprehensive Infrastructure as Code (IaC) templates and CI/CD patterns for deploying Azure API Management. It adheres to cloud security best practices by utilizing Managed Identities, OpenID Connect (OIDC) for authenticated workflows, and promotes the use of Microsoft's Azure Verified Modules (AVM). No malicious patterns such as credential exfiltration, obfuscation, or unauthorized command execution were detected.

  • Socket14d

    No alerts

  • Snyk14d

    Risk: LOW · No issues

  • Runlayer6mo

    1/1 file flagged

Signed by skilld at b198c92. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 5 months ago
Other metadata
metadata
{
  "author": "Thomas Thornton",
  "version": "1.0.0",
  "last-updated": "2026-01-29",
  "azure-services": "api-management, devops, github-actions",
  "iac-tools": "bicep, terraform"
}

README badge

README badge for thomast1906/github-copilot-agent-skills/apiops-deployment