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:
- 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
- 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
- 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
- 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)
- 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)
- 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
- 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
- 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
- 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
- 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.
- 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
- 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
- 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
- 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’
- 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
- 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
- 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
]
}
}
- 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
- 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”
- 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
- Prerequisites:
bash
# Install Bicep
az bicep install
# Install Azure PowerShell modules
Install-Module -Name Az -AllowClobber -Force
- 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
- 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.