Skip to content

 

Secured Development Environment Requirements in Azure

give me examples of requirements required to build out a Secured Development Environment in an Azure Landing Zone

Here are key requirements for building a Secured Development Environment (SDE) within an Azure Landing Zone:

  1. Identity & Access Management Requirements
  • Requirement: Implement Azure AD Conditional Access policies requiring MFA and device compliance for all developer access
  • Requirement: Enforce Just-In-Time (JIT) and Just-Enough-Access (JEA) principles through Privileged Identity Management
  • Requirement: Segregate duties using Azure AD groups (Dev, Test, Ops) with RBAC assignments
  • Requirement: Require service principals with certificates (not secrets) for pipeline identities
  1. Network Security Requirements
  • Requirement: Implement hub-spoke architecture with Azure Firewall/NVA in hub
  • Requirement: Enforce NSG rules limiting east-west traffic between environments
  • Requirement: Require Private Endpoints for PaaS services (Azure SQL, Storage, Key Vault)
  • Requirement: Deploy Azure Bastion for secure administrative access to VMs
  • Requirement: Implement DDoS Protection Standard on perimeter networks
  1. Environment Isolation Requirements
  • Requirement: Separate subscriptions for Development, Test, and Production environments
  • Requirement: Implement resource grouping by application/team with clear naming conventions
  • Requirement: Enforce network peering only through hub, no direct spoke-to-spoke connections
  • Requirement: Deploy dedicated Key Vault instances per environment with appropriate access policies
  1. Data Protection Requirements
  • Requirement: Encrypt all data at rest using customer-managed keys (CMK) via Azure Key Vault
  • Requirement: Enable Transparent Data Encryption for all SQL databases
  • Requirement: Classify data using Microsoft Purview and apply appropriate protection labels
  • Requirement: Implement Azure Storage encryption with infrastructure encryption (double encryption)
  1. Compliance & Governance Requirements
  • Requirement: Apply Azure Policy initiatives for regulatory standards (ISO 27001, NIST, SOC 2)
  • Requirement: Deploy Microsoft Defender for Cloud with enhanced security features enabled
  • Requirement: Implement Azure Blueprints for consistent environment deployment
  • Requirement: Enforce tagging standards (CostCenter, ApplicationOwner, Environment, DataClassification)
  1. Development Tools & Pipeline Security Requirements
  • Requirement: Secure Azure DevOps/GitHub repositories with branch policies and required reviews
  • Requirement: Implement pipeline scanning for secrets, vulnerabilities, and IaC misconfigurations
  • Requirement: Require container image scanning in ACR before deployment
  • Requirement: Deploy Azure DevOps self-hosted agents in dedicated network with restricted egress
  1. Monitoring & Threat Detection Requirements
  • Requirement: Centralize logs in Azure Monitor/Log Analytics workspace with 1-year retention
  • Requirement: Configure Microsoft Sentinel for SIEM/SOAR with playbooks for common threats
  • Requirement: Implement Azure Activity Log alerts for critical operations (RBAC changes, network modifications)
  • Requirement: Deploy Microsoft Defender for Cloud continuous assessment with auto-remediation workflows
  1. Operational Security Requirements
  • Requirement: Implement Azure Automation for patch management on IaaS resources
  • Requirement: Configure backup and disaster recovery for critical development assets
  • Requirement: Deploy Azure Policy to prevent public endpoints on storage accounts and SQL servers
  • Requirement: Enforce private DNS zones for all internal name resolution
  1. Secret Management Requirements
  • Requirement: Prohibit secrets in code repositories; mandate Azure Key Vault integration
  • Requirement: Implement automatic secret rotation for service accounts and certificates
  • Requirement: Configure Key Vault firewall and disable public network access
  • Requirement: Enable Key Vault logging and alerts for access patterns
  1. Container & Kubernetes Security Requirements (if applicable)
  • Requirement: Deploy AKS with Azure AD integration and Kubernetes RBAC
  • Requirement: Enable AKS security features (network policies, pod security standards)
  • Requirement: Implement Azure Policy for AKS to enforce baseline configurations
  • Requirement: Restrict container capabilities and require non-root user execution

Success Criteria Metrics:

  • Security Posture Score in Defender for Cloud > 90%
  • Zero high-severity vulnerabilities in CI/CD pipeline scans
  • 100% compliance with assigned Azure Policy initiatives
  • Mean Time to Detect (MTTD) < 1 hour for critical security events
  • All developer access authenticated via Azure AD with MFA

These requirements should be implemented progressively, starting with identity and network security foundations, then layering additional controls as maturity increases.

please provide actual requirements statements for the above

Azure Secured Development Environment (SDE) Requirements Document

Section 1: Identity & Access Management

IDM-001: The system shall require Azure AD Conditional Access policies that mandate multi-factor authentication (MFA) for all interactive user logins to Azure portal, Azure DevOps, and development resources.

IDM-002: The system shall implement Privileged Identity Management (PIM) to enforce Just-In-Time elevation for all administrative Azure roles, with maximum activation duration not exceeding 8 hours.

IDM-003: The system shall require Azure RBAC role assignments only through Azure AD security groups, prohibiting direct user-to-role assignments, with groups structured by function (e.g., “App1-Dev-Contributors”, “Platform-KeyVault-Admins”).

IDM-004: The system shall require all service principals used by CI/CD pipelines to authenticate using X.509 certificates stored in Azure Key Vault, prohibiting the use of client secrets or passwords.

Section 2: Network Security

NET-001: The system shall deploy a hub-spoke topology where all outbound internet traffic from spoke virtual networks routes through the centralized Azure Firewall in the hub virtual network.

NET-002: The system shall enforce Network Security Groups (NSGs) that deny all traffic between development, testing, and production environments at the network layer.

NET-003: The system shall require Private Endpoints for all Azure PaaS services (Azure SQL, Storage Accounts, Container Registry, etc.) with public network access disabled.

NET-004: The system shall deploy Azure Bastion as the exclusive method for Secure Shell (SSH) and Remote Desktop Protocol (RDP) access to virtual machines in the development environment.

NET-005: The system shall enable Azure DDoS Protection Standard on all virtual networks containing public-facing endpoints.

Section 3: Environment Isolation

ENV-001: The system shall provision separate Azure subscriptions for each environment type (Development, Testing, Production), managed under a single Azure AD tenant.

ENV-002: The system shall require resource naming convention: {appcode}-{env}-{region}-{resource-type}-{instance} (e.g., hris-dev-eastus2-kv-01) for all provisioned resources.

ENV-003: The system shall prohibit direct virtual network peering between spoke networks; all connectivity shall route through the hub network only.

ENV-004: The system shall deploy dedicated Azure Key Vault instances per application per environment, with access policies granting only necessary permissions to specified identities.

Section 4: Data Protection

DATA-001: The system shall encrypt all Azure Storage accounts and Azure SQL databases using Customer-Managed Keys stored in Azure Key Vault.

DATA-002: The system shall require Transparent Data Encryption (TDE) with customer-managed keys for all Azure SQL databases and Synapse workspaces.

DATA-003: The system shall deploy Microsoft Purview to automatically classify sensitive data and apply Azure Information Protection labels to documents containing PII, PCI, or PHI data.

DATA-004: The system shall enable infrastructure double encryption for all Azure Storage accounts containing sensitive data.

Section 5: Compliance & Governance

GOV-001: The system shall assign Azure Policy initiatives for ISO 27001:2013 to all subscriptions, achieving at least 95% compliance within 30 days of resource deployment.

GOV-002: The system shall enable Microsoft Defender for Cloud enhanced security features (including Defender plans for Servers, App Service, SQL, and Storage) on all subscriptions.

GOV-003: The system shall deploy environment definitions through Azure Blueprints that include mandatory resource locks, policies, and ARM templates for consistent deployments.

GOV-004: The system shall require the following tags on all resources: CostCenter, ApplicationOwner, Environment, DataClassification, and RetentionPeriod.

Section 6: Development Pipeline Security

DEVPIPE-001: The system shall require Azure DevOps branch policies that mandate at least one pull request review, successful build validation, and no secret detection alerts before merging to main branches.

DEVPIPE-002: The system shall integrate static application security testing (SAST), software composition analysis (SCA), and infrastructure as code (IaC) scanning into all CI/CD pipelines, blocking deployments on high-severity findings.

DEVPIPE-003: The system shall require vulnerability scanning of all container images in Azure Container Registry prior to deployment, with critical/high vulnerabilities resulting in deployment failure.

DEVPIPE-004: The system shall deploy Azure DevOps self-hosted agents within a dedicated subnet, restricting outbound internet access to required endpoints via Azure Firewall application rules.

Section 7: Monitoring & Threat Detection

MON-001: The system shall forward all Azure resource logs, Azure AD sign-in logs, and Azure Activity logs to a centralized Log Analytics workspace with a retention period of 365 days.

MON-002: The system shall deploy Microsoft Sentinel with playbooks to automatically respond to security incidents, including disabling compromised accounts and isolating affected resources.

MON-003: The system shall configure Azure Monitor alerts for the following activities: creation of owner/contributor role assignments, modification of network security groups, and changes to Key Vault access policies.

MON-004: The system shall enable Microsoft Defender for Cloud auto-provisioning of Log Analytics agents and vulnerability assessment solutions, with automated remediation workflows for high-severity findings.

Section 8: Operational Security

OPS-001: The system shall deploy Azure Automation Update Management to apply OS patches to all virtual machines within 14 days of critical security update release.

OPS-002: The system shall implement Azure Backup with geo-redundant storage (GRS) for all virtual machines, SQL databases, and file shares, with retention policies meeting organizational RPO/RTO requirements.

OPS-003: The system shall enforce Azure Policy that denies creation of Storage Accounts and Azure SQL servers with public network access enabled.

OPS-004: The system shall deploy Azure Private DNS zones for all internal name resolution, prohibiting the use of public DNS for internal service discovery.

Section 9: Secret Management

SECRET-001: The system shall require all application secrets, credentials, and connection strings to be stored in Azure Key Vault, with automated scanning to detect and alert on secrets committed to source code repositories.

SECRET-002: The system shall implement automatic rotation of certificates, storage account keys, and service principal credentials using Azure Automation or Azure Functions, with rotation intervals not exceeding 90 days.

SECRET-003: The system shall configure Azure Key Vault firewall rules to allow access only from specific virtual networks and Azure services, with public network access disabled.

SECRET-004: The system shall enable Key Vault diagnostic logging and alert on: VaultAccessPolicyChanged, SecretNearExpiry, and SecretAccessed events.

Section 10: Container Security (Conditional Requirements)

CONTAINER-001: If Azure Kubernetes Service (AKS) is deployed, the system shall integrate AKS with Azure AD for Kubernetes RBAC, requiring Azure AD authentication for kubectl access.

CONTAINER-002: The system shall enable AKS network policies using Azure Network Policy or Calico to enforce pod-to-pod communication rules.

CONTAINER-003: The system shall apply Azure Policy for Kubernetes to enforce: disallowed privilege escalation, read-only root filesystems, and dropping all capabilities for all pod deployments.

CONTAINER-004: The system shall configure AKS clusters with managed identities instead of service principals, and enable Azure RBAC for Kubernetes authorization.

Compliance & Verification Requirements

VERIFY-001: The system shall generate weekly compliance reports showing Azure Policy compliance state, with automated notifications for resources out of compliance for more than 72 hours.

VERIFY-002: The system shall conduct monthly security posture assessments using Microsoft Secure Score and Defender for Cloud Secure Score, with target scores of 90% or higher.

VERIFY-003: The system shall perform quarterly penetration testing on development environments, with all critical findings remediated within 14 business days.

VERIFY-004: The system shall maintain an audit trail of all changes to the SDE configuration, including Azure Policy assignments, network rule modifications, and permission changes, retained for 7 years.

These requirements statements follow the “The system shall…” format commonly used in technical requirements documentation, providing clear, testable, and implementable specifications for your Azure Secured Development Environment.

please provide the biceps code to configure the above

I’ll provide Bicep modules for key components of the Secured Development Environment. Due to the extensive nature of the requirements, I’ll focus on the foundational modules.

  1. Main Deployment File (main.bicep)

bicep

targetScope = ‘subscription’

 

@description(‘Location for all resources’)

param location string = ‘eastus2’

 

@description(‘Tags for resources’)

param tags object = {

  CostCenter: ‘IT001’

  ApplicationOwner: ‘DevelopmentTeam’

  Environment: ‘Development’

  DataClassification: ‘Internal’

}

 

@description(‘Hub virtual network CIDR’)

param hubVnetAddressPrefix string = ‘10.0.0.0/16’

 

@description(‘Development spoke network CIDR’)

param devSpokeVnetAddressPrefix string = ‘10.1.0.0/16’

 

// Deploy Resource Groups

module devRg ‘resourceGroup.bicep’ = {

  name: ‘devResourceGroup’

  params: {

    location: location

    environment: ‘dev’

    tags: tags

  }

}

 

module hubRg ‘resourceGroup.bicep’ = {

  name: ‘hubResourceGroup’

  params: {

    location: location

    environment: ‘hub’

    tags: tags

  }

}

 

// Deploy Hub Network with Azure Firewall

module hubNetwork ‘hub-network.bicep’ = {

  name: ‘hubNetworkDeployment’

  scope: resourceGroup(hubRg.outputs.resourceGroupName)

  params: {

    location: location

    vnetAddressPrefix: hubVnetAddressPrefix

    tags: union(tags, { VNetType: ‘Hub’ })

  }

  dependsOn: [

    hubRg

  ]

}

 

// Deploy Development Spoke Network

module devNetwork ‘spoke-network.bicep’ = {

  name: ‘devNetworkDeployment’

  scope: resourceGroup(devRg.outputs.resourceGroupName)

  params: {

    location: location

    vnetAddressPrefix: devSpokeVnetAddressPrefix

    hubVnetId: hubNetwork.outputs.vnetId

    environment: ‘dev’

    tags: union(tags, { VNetType: ‘Spoke’ })

  }

  dependsOn: [

    devRg

    hubNetwork

  ]

}

 

// Deploy Log Analytics Workspace for centralized logging

module logAnalytics ‘log-analytics.bicep’ = {

  name: ‘logAnalyticsDeployment’

  scope: resourceGroup(hubRg.outputs.resourceGroupName)

  params: {

    location: location

    retentionInDays: 365

    tags: tags

  }

  dependsOn: [

    hubRg

  ]

}

 

// Deploy Key Vault with private endpoint

module keyVault ‘keyvault.bicep’ = {

  name: ‘keyVaultDeployment’

  scope: resourceGroup(devRg.outputs.resourceGroupName)

  params: {

    location: location

    keyVaultName: ‘dev-kv-${uniqueString(resourceGroup().id)}’

    vnetId: devNetwork.outputs.vnetId

    subnetId: devNetwork.outputs.privateEndpointSubnetId

    tags: tags

  }

  dependsOn: [

    devNetwork

  ]

}

 

// Deploy Azure Bastion

module bastion ‘bastion.bicep’ = {

  name: ‘bastionDeployment’

  scope: resourceGroup(hubRg.outputs.resourceGroupName)

  params: {

    location: location

    bastionSubnetAddressPrefix: ‘10.0.1.0/27’

    vnetId: hubNetwork.outputs.vnetId

    tags: tags

  }

  dependsOn: [

    hubNetwork

  ]

}

 

// Assign Azure Policies

module policies ‘policies.bicep’ = {

  name: ‘policyAssignments’

  params: {

    location: location

    logAnalyticsWorkspaceId: logAnalytics.outputs.workspaceId

    keyVaultId: keyVault.outputs.keyVaultId

    tags: tags

  }

}

 

// Output important information

output hubVnetId string = hubNetwork.outputs.vnetId

output devVnetId string = devNetwork.outputs.vnetId

output logAnalyticsWorkspaceId string = logAnalytics.outputs.workspaceId

output keyVaultUri string = keyVault.outputs.keyVaultUri

output bastionPublicIp string = bastion.outputs.bastionPublicIp

  1. Resource Group Module (resourceGroup.bicep)

bicep

param location string

param environment string

param tags object

 

var resourceGroupName = ‘rg-sde-${environment}-${location}’

 

resource rg ‘Microsoft.Resources/resourceGroups@2021-04-01’ = {

  name: resourceGroupName

  location: location

  tags: tags

}

 

output resourceGroupName string = rg.name

output resourceGroupId string = rg.id

  1. Hub Network Module (hub-network.bicep)

bicep

param location string

param vnetAddressPrefix string

param tags object

 

// Subnet CIDRs

var subnets = {

  AzureFirewallSubnet: ‘10.0.0.0/26’

  AzureBastionSubnet: ‘10.0.1.0/27’

  GatewaySubnet: ‘10.0.2.0/27’

  ManagementSubnet: ‘10.0.3.0/27’

  PrivateEndpointSubnet: ‘10.0.4.0/27’

}

 

// Create Hub Virtual Network

resource hubVnet ‘Microsoft.Network/virtualNetworks@2021-05-01’ = {

  name: ‘vnet-hub-${location}’

  location: location

  tags: tags

  properties: {

    addressSpace: {

      addressPrefixes: [

        vnetAddressPrefix

      ]

    }

    subnets: [

      {

        name: ‘AzureFirewallSubnet’

        properties: {

          addressPrefix: subnets.AzureFirewallSubnet

          delegations: []

        }

      }

      {

        name: ‘AzureBastionSubnet’

        properties: {

          addressPrefix: subnets.AzureBastionSubnet

        }

      }

      {

        name: ‘GatewaySubnet’

        properties: {

          addressPrefix: subnets.GatewaySubnet

        }

      }

      {

        name: ‘ManagementSubnet’

        properties: {

          addressPrefix: subnets.ManagementSubnet

          networkSecurityGroup: {

            id: hubNsg.id

          }

        }

      }

      {

        name: ‘PrivateEndpointSubnet’

        properties: {

          addressPrefix: subnets.PrivateEndpointSubnet

          privateEndpointNetworkPolicies: ‘Enabled’

        }

      }

    ]

  }

}

 

// Network Security Group for Management Subnet

resource hubNsg ‘Microsoft.Network/networkSecurityGroups@2021-05-01’ = {

  name: ‘nsg-hub-management-${location}’

  location: location

  tags: tags

  properties: {

    securityRules: [

      {

        name: ‘AllowAzureCloud’

        properties: {

          description: ‘Allow Azure Cloud Services’

          protocol: ‘*’

          sourcePortRange: ‘*’

          destinationPortRange: ‘*’

          sourceAddressPrefix: ‘AzureCloud’

          destinationAddressPrefix: ‘*’

          access: ‘Allow’

          priority: 100

          direction: ‘Inbound’

        }

      }

      {

        name: ‘DenyAllInbound’

        properties: {

          description: ‘Deny all other inbound’

          protocol: ‘*’

          sourcePortRange: ‘*’

          destinationPortRange: ‘*’

          sourceAddressPrefix: ‘*’

          destinationAddressPrefix: ‘*’

          access: ‘Deny’

          priority: 4096

          direction: ‘Inbound’

        }

      }

    ]

  }

}

 

// Azure Firewall

resource azureFirewall ‘Microsoft.Network/azureFirewalls@2021-05-01’ = {

  name: ‘afw-hub-${location}’

  location: location

  tags: tags

  properties: {

    sku: {

      name: ‘AZFW_VNet’

      tier: ‘Standard’

    }

    threatIntelMode: ‘Alert’

    additionalProperties: {

      Network.SNAT.PrivateRanges: vnetAddressPrefix

    }

    ipConfigurations: [

      {

        name: ‘azureFirewallIpConfiguration’

        properties: {

          subnet: {

            id: ‘${hubVnet.id}/subnets/AzureFirewallSubnet’

          }

          publicIPAddress: {

            id: firewallPublicIp.id

          }

        }

      }

    ]

  }

  dependsOn: [

    hubVnet

  ]

}

 

resource firewallPublicIp ‘Microsoft.Network/publicIPAddresses@2021-05-01’ = {

  name: ‘pip-afw-${location}’

  location: location

  tags: tags

  sku: {

    name: ‘Standard’

  }

  properties: {

    publicIPAllocationMethod: ‘Static’

  }

}

 

// Route Table for forced tunneling through firewall

resource hubRouteTable ‘Microsoft.Network/routeTables@2021-05-01’ = {

  name: ‘rt-hub-${location}’

  location: location

  tags: tags

  properties: {

    disableBgpRoutePropagation: true

    routes: [

      {

        name: ‘DefaultToFirewall’

        properties: {

          addressPrefix: ‘0.0.0.0/0’

          nextHopType: ‘VirtualAppliance’

          nextHopIpAddress: azureFirewall.properties.ipConfigurations[0].properties.privateIPAddress

        }

      }

    ]

  }

}

 

output vnetId string = hubVnet.id

output firewallPrivateIp string = azureFirewall.properties.ipConfigurations[0].properties.privateIPAddress

output routeTableId string = hubRouteTable.id

  1. Spoke Network Module (spoke-network.bicep)

bicep

param location string

param vnetAddressPrefix string

param hubVnetId string

param environment string

param tags object

 

// Subnet CIDRs for development environment

var subnets = {

  AppSubnet: ‘10.1.1.0/24’

  DataSubnet: ‘10.1.2.0/24’

  PrivateEndpointSubnet: ‘10.1.3.0/24’

  AzureDevOpsSubnet: ‘10.1.4.0/24’

}

 

// Create Spoke Virtual Network

resource spokeVnet ‘Microsoft.Network/virtualNetworks@2021-05-01’ = {

  name: ‘vnet-${environment}-${location}’

  location: location

  tags: tags

  properties: {

    addressSpace: {

      addressPrefixes: [

        vnetAddressPrefix

      ]

    }

    subnets: [

      {

        name: ‘AppSubnet’

        properties: {

          addressPrefix: subnets.AppSubnet

          networkSecurityGroup: {

            id: spokeNsg.id

          }

        }

      }

      {

        name: ‘DataSubnet’

        properties: {

          addressPrefix: subnets.DataSubnet

          networkSecurityGroup: {

            id: spokeNsg.id

          }

        }

      }

      {

        name: ‘PrivateEndpointSubnet’

        properties: {

          addressPrefix: subnets.PrivateEndpointSubnet

          privateEndpointNetworkPolicies: ‘Enabled’

        }

      }

      {

        name: ‘AzureDevOpsSubnet’

        properties: {

          addressPrefix: subnets.AzureDevOpsSubnet

          networkSecurityGroup: {

            id: devOpsNsg.id

          }

        }

      }

    ]

  }

}

 

// NSG for Development Subnets

resource spokeNsg ‘Microsoft.Network/networkSecurityGroups@2021-05-01’ = {

  name: ‘nsg-${environment}-default-${location}’

  location: location

  tags: tags

  properties: {

    securityRules: [

      {

        name: ‘DenyCrossEnvironment’

        properties: {

          description: ‘Deny traffic to/from other environments’

          protocol: ‘*’

          sourcePortRange: ‘*’

          destinationPortRange: ‘*’

          sourceAddressPrefix: ‘VirtualNetwork’

          destinationAddressPrefix: ‘*’

          access: ‘Deny’

          priority: 100

          direction: ‘Outbound’

        }

      }

      {

        name: ‘AllowAzureDevOps’

        properties: {

          description: ‘Allow Azure DevOps Services’

          protocol: ‘*’

          sourcePortRange: ‘*’

          destinationPortRange: ‘*’

          sourceAddressPrefix: ‘AzureDevOps’

          destinationAddressPrefix: ‘*’

          access: ‘Allow’

          priority: 110

          direction: ‘Outbound’

        }

      }

    ]

  }

}

 

// NSG for Azure DevOps Agents

resource devOpsNsg ‘Microsoft.Network/networkSecurityGroups@2021-05-01’ = {

  name: ‘nsg-${environment}-devops-${location}’

  location: location

  tags: tags

  properties: {

    securityRules: [

      {

        name: ‘AllowHttpsOutbound’

        properties: {

          protocol: ‘Tcp’

          sourcePortRange: ‘*’

          destinationPortRange: ‘443’

          sourceAddressPrefix: ‘*’

          destinationAddressPrefix: ‘Internet’

          access: ‘Allow’

          priority: 100

          direction: ‘Outbound’

        }

      }

    ]

  }

}

 

// VNet Peering to Hub

resource peeringToHub ‘Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2021-05-01’ = {

  parent: spokeVnet

  name: ‘peer-to-hub’

  properties: {

    allowVirtualNetworkAccess: true

    allowForwardedTraffic: true

    allowGatewayTransit: false

    useRemoteGateways: false

    remoteVirtualNetwork: {

      id: hubVnetId

    }

  }

}

 

output vnetId string = spokeVnet.id

output privateEndpointSubnetId string = ‘${spokeVnet.id}/subnets/PrivateEndpointSubnet’

output appSubnetId string = ‘${spokeVnet.id}/subnets/AppSubnet’

  1. Key Vault Module (keyvault.bicep)

bicep

param location string

param keyVaultName string

param vnetId string

param subnetId string

param tags object

 

// Create Key Vault with private endpoint

resource kv ‘Microsoft.KeyVault/vaults@2021-06-01-preview’ = {

  name: keyVaultName

  location: location

  tags: tags

  properties: {

    sku: {

      name: ‘standard’

      family: ‘A’

    }

    tenantId: subscription().tenantId

    accessPolicies: []

    enabledForDeployment: false

    enabledForDiskEncryption: false

    enabledForTemplateDeployment: false

    enableRbacAuthorization: true

    enableSoftDelete: true

    softDeleteRetentionInDays: 90

    enablePurgeProtection: true

    publicNetworkAccess: ‘Disabled’

    networkAcls: {

      defaultAction: ‘Deny’

      bypass: ‘AzureServices’

      ipRules: []

      virtualNetworkRules: [

        {

          id: subnetId

        }

      ]

    }

  }

}

 

// Private DNS Zone for Key Vault

resource kvPrivateDnsZone ‘Microsoft.Network/privateDnsZones@2020-06-01’ = {

  name: ‘privatelink.vaultcore.azure.net’

  location: ‘global’

  tags: tags

}

 

// Link Private DNS Zone to VNet

resource kvDnsLink ‘Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01’ = {

  parent: kvPrivateDnsZone

  name: ‘link-${replace(vnetId, ‘/’, ‘-‘)}’

  location: ‘global’

  properties: {

    registrationEnabled: false

    virtualNetwork: {

      id: vnetId

    }

  }

}

 

// Private Endpoint for Key Vault

resource kvPrivateEndpoint ‘Microsoft.Network/privateEndpoints@2021-05-01’ = {

  name: ‘pe-${keyVaultName}’

  location: location

  tags: tags

  properties: {

    subnet: {

      id: subnetId

    }

    privateLinkServiceConnections: [

      {

        name: ‘pls-${keyVaultName}’

        properties: {

          privateLinkServiceId: kv.id

          groupIds: [

            ‘vault’

          ]

        }

      }

    ]

  }

}

 

// Private DNS Record

resource kvPrivateDnsRecord ‘Microsoft.Network/privateDnsZones/A@2020-06-01’ = {

  parent: kvPrivateDnsZone

  name: ‘@’

  properties: {

    ttl: 300

    aRecords: [

      {

        ipv4Address: kvPrivateEndpoint.properties.networkInterfaces[0].properties.ipConfigurations[0].properties.privateIPAddress

      }

    ]

  }

  dependsOn: [

    kvPrivateEndpoint

  ]

}

 

output keyVaultId string = kv.id

output keyVaultUri string = kv.properties.vaultUri

output privateEndpointIp string = kvPrivateEndpoint.properties.networkInterfaces[0].properties.ipConfigurations[0].properties.privateIPAddress

  1. Log Analytics Module (log-analytics.bicep)

bicep

param location string

param retentionInDays int

param tags object

 

resource logAnalyticsWorkspace ‘Microsoft.OperationalInsights/workspaces@2021-06-01’ = {

  name: ‘log-sde-${uniqueString(resourceGroup().id)}’

  location: location

  tags: tags

  properties: {

    sku: {

      name: ‘PerGB2018’

    }

    retentionInDays: retentionInDays

    features: {

      searchVersion: 1

    }

    workspaceCapping: {

      dailyQuotaGb: -1

    }

    publicNetworkAccessForIngestion: ‘Enabled’

    publicNetworkAccessForQuery: ‘Enabled’

  }

}

 

// Enable Defender for Cloud

resource defenderSettings ‘Microsoft.Security/autoProvisioningSettings@2017-08-01-preview’ = {

  name: ‘default’

  properties: {

    autoProvision: ‘On’

  }

}

 

// Enable all Defender plans

resource defenderPricing ‘Microsoft.Security/pricings@2018-06-01’ = {

  name: ‘VirtualMachines’

  properties: {

    pricingTier: ‘Standard’

  }

}

 

resource defenderPricingStorage ‘Microsoft.Security/pricings@2018-06-01’ = {

  name: ‘StorageAccounts’

  properties: {

    pricingTier: ‘Standard’

  }

}

 

resource defenderPricingSql ‘Microsoft.Security/pricings@2018-06-01’ = {

  name: ‘SqlServers’

  properties: {

    pricingTier: ‘Standard’

  }

}

 

resource defenderPricingAppService ‘Microsoft.Security/pricings@2018-06-01’ = {

  name: ‘AppServices’

  properties: {

    pricingTier: ‘Standard’

  }

}

 

output workspaceId string = logAnalyticsWorkspace.id

output workspaceName string = logAnalyticsWorkspace.name

  1. Azure Policy Module (policies.bicep)

bicep

param location string

param logAnalyticsWorkspaceId string

param keyVaultId string

param tags object

 

// Custom Policy Definition: Require Private Endpoints for PaaS

resource requirePrivateEndpointPolicy ‘Microsoft.Authorization/policyDefinitions@2021-06-01’ = {

  name: ‘require-private-endpoint-for-paas’

  properties: {

    displayName: ‘Require Private Endpoints for PaaS Services’

    description: ‘Ensures that PaaS services use private endpoints’

    mode: ‘Indexed’

    parameters: {}

    policyRule: {

      if: {

        allOf: [

          {

            field: ‘type’

            in: [

              ‘Microsoft.Storage/storageAccounts’

              ‘Microsoft.Sql/servers’

              ‘Microsoft.KeyVault/vaults’

              ‘Microsoft.ContainerRegistry/registries’

            ]

          }

        ]

      }

      then: {

        effect: ‘Deny’

        details: {

          type: ‘Microsoft.Network/privateEndpoints’

          existenceCondition: {

            field: ‘Microsoft.Network/privateEndpoints/privateLinkServiceConnections[*].privateLinkServiceId’

            equals: ‘[field(‘id’)]’

          }

        }

      }

    }

  }

}

 

// Custom Policy Definition: Require CMK Encryption

resource requireCmkEncryptionPolicy ‘Microsoft.Authorization/policyDefinitions@2021-06-01’ = {

  name: ‘require-customer-managed-keys’

  properties: {

    displayName: ‘Require Customer Managed Keys for Encryption’

    description: ‘Ensures resources use customer-managed keys for encryption’

    mode: ‘Indexed’

    parameters: {

      keyVaultId: {

        type: ‘String’

        defaultValue: keyVaultId

        metadata: {

          displayName: ‘Key Vault Resource ID’

        }

      }

    }

    policyRule: {

      if: {

        anyOf: [

          {

            field: ‘type’

            equals: ‘Microsoft.Storage/storageAccounts’

          }

          {

            field: ‘type’

            equals: ‘Microsoft.Sql/servers/databases’

          }

        ]

      }

      then: {

        effect: ‘Deny’

        details: {

          type: ‘Microsoft.KeyVault/vaults/keys’

          existenceCondition: {

            field: ‘Microsoft.KeyVault/vaults/keys/keyUri’

            exists: ‘true’

          }

        }

      }

    }

  }

}

 

// Assign built-in policies

resource auditDenyPublicNetworkAccess ‘Microsoft.Authorization/policyAssignments@2021-06-01’ = {

  name: ‘audit-deny-public-network-access’

  properties: {

    displayName: ‘Audit/Deny Public Network Access’

    description: ‘Audit or deny resources with public network access enabled’

    policyDefinitionId: ‘/providers/Microsoft.Authorization/policyDefinitions/bb91dfba-c30d-4263-9add-9c2384e659a6’

    parameters: {

      effect: {

        value: ‘Audit’

      }

    }

    enforcementMode: ‘Default’

  }

}

 

resource enableMonitoring ‘Microsoft.Authorization/policyAssignments@2021-06-01’ = {

  name: ‘enable-monitoring’

  properties: {

    displayName: ‘Enable Azure Monitor for VMs’

    description: ‘Enable Azure Monitor for Virtual Machines’

    policyDefinitionId: ‘/providers/Microsoft.Authorization/policyDefinitions/6352569f-6888-4c90-99ba-6356a5caf6d3’

    parameters: {

      logAnalytics_1: {

        value: logAnalyticsWorkspaceId

      }

    }

    enforcementMode: ‘Default’

  }

}

 

// Initiative for ISO 27001

resource iso27001Initiative ‘Microsoft.Authorization/policySetDefinitions@2021-06-01’ = {

  name: ‘iso27001-initiative’

  properties: {

    displayName: ‘ISO 27001 Compliance Initiative’

    description: ‘Policies to achieve ISO 27001 compliance’

    metadata: {

      category: ‘Regulatory Compliance’

      version: ‘1.0.0’

    }

    policyDefinitions: [

      {

        policyDefinitionId: auditDenyPublicNetworkAccess.properties.policyDefinitionId

      }

      {

        policyDefinitionId: requirePrivateEndpointPolicy.id

      }

      {

        policyDefinitionId: requireCmkEncryptionPolicy.id

      }

      // Add more policy definitions as needed

    ]

  }

}

  1. Azure Bastion Module (bastion.bicep)

bicep

param location string

param bastionSubnetAddressPrefix string

param vnetId string

param tags object

 

// Create Bastion Public IP

resource bastionPublicIp ‘Microsoft.Network/publicIPAddresses@2021-05-01’ = {

  name: ‘pip-bastion-${location}’

  location: location

  tags: tags

  sku: {

    name: ‘Standard’

  }

  properties: {

    publicIPAllocationMethod: ‘Static’

  }

}

 

// Deploy Azure Bastion

resource azureBastion ‘Microsoft.Network/bastionHosts@2021-05-01’ = {

  name: ‘bastion-${location}’

  location: location

  tags: tags

  properties: {

    ipConfigurations: [

      {

        name: ‘bastionIpConfig’

        properties: {

          subnet: {

            id: ‘${vnetId}/subnets/AzureBastionSubnet’

          }

          publicIPAddress: {

            id: bastionPublicIp.id

          }

        }

      }

    ]

  }

}

 

output bastionPublicIp string = bastionPublicIp.properties.ipAddress

output bastionId string = azureBastion.id

  1. Deployment Script for Additional Configuration (deploy.ps1)

powershell

# PowerShell script to deploy and configure additional components

 

param(

    [string]$Location = “eastus2”,

    [string]$Environment = “dev”,

    [string]$SubscriptionId

)

 

# Connect to Azure

Connect-AzAccount

 

# Set subscription

Set-AzContext -SubscriptionId $SubscriptionId

 

# Deploy Bicep templates

New-AzSubscriptionDeployment `

    -Name “SDE-Deployment” `

    -Location $Location `

    -TemplateFile “./main.bicep” `

    -location $Location

 

# Configure Azure AD Conditional Access (requires Azure AD Premium P2)

Write-Host “Configure Conditional Access Policies manually in Azure AD Portal”

Write-Host “1. Create policy requiring MFA for all users”

Write-Host “2. Create policy requiring compliant devices for admin roles”

Write-Host “3. Enable Privileged Identity Management”

 

# Configure Microsoft Sentinel

$Workspace = Get-AzOperationalInsightsWorkspace | Where-Object {$_.Name -like “log-sde-*”}

Enable-AzSentinel -WorkspaceName $Workspace.Name -ResourceGroupName $Workspace.ResourceGroupName

 

# Enable Microsoft Purview (if available in region)

# New-AzPurviewAccount -Name “purview-sde” -ResourceGroupName “rg-sde-hub-$Location” -Location $Location

 

# Output deployment summary

Write-Host “`n=== Deployment Complete ===”

Write-Host “Next Steps:”

Write-Host “1. Configure Azure AD Conditional Access Policies”

Write-Host “2. Set up Azure DevOps Service Connections”

Write-Host “3. Configure application-specific Key Vault access policies”

Write-Host “4. Deploy Azure DevOps agents in AzureDevOpsSubnet”

  1. Parameters File (parameters.json)

json

{

  “$schema”: “https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#”,

  “contentVersion”: “1.0.0.0”,

  “parameters”: {

    “location”: {

      “value”: “eastus2”

    },

    “hubVnetAddressPrefix”: {

      “value”: “10.0.0.0/16”

    },

    “devSpokeVnetAddressPrefix”: {

      “value”: “10.1.0.0/16”

    },

    “tags”: {

      “value”: {

        “CostCenter”: “IT001”,

        “ApplicationOwner”: “DevelopmentTeam”,

        “Environment”: “Development”,

        “DataClassification”: “Internal”,

        “Compliance”: “ISO27001”,

        “ManagedBy”: “PlatformTeam”

      }

    }

  }

}

Deployment Instructions

  1. Prerequisites:

bash

# Install Bicep

az bicep install

 

# Install Azure PowerShell modules

Install-Module -Name Az -AllowClobber -Force

  1. Deploy the environment:

bash

# Login to Azure

az login

 

# Deploy using Bicep

az deployment sub create \

  –name “SDE-Deployment” \

  –location eastus2 \

  –template-file main.bicep \

  –parameters parameters.json

  1. Post-deployment configuration:

powershell

# Run the configuration script

.\deploy.ps1 -SubscriptionId “your-subscription-id”

This Bicep code provides the infrastructure foundation for your Secured Development Environment. Additional modules would be needed for:

  • AKS clusters (if using Kubernetes)
  • Azure DevOps project configuration
  • Application-specific deployments
  • Custom monitoring and alerting rules

The architecture follows Azure Well-Architected Framework principles and implements the security requirements specified in your document.

 

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.