Skip to content

Latest commit

 

History

History
1085 lines (795 loc) · 34.2 KB

File metadata and controls

1085 lines (795 loc) · 34.2 KB
marp title description header author footer theme transition paginate _paginate html
true
Getting Started with Compliance & Governance using Azure Policy
Presentation slides for Getting Started with Compliance & Governance using Azure Policy
Leonard Sheng Sheng Lee
[Leonard Sheng Sheng Lee](https://github.com/sheeeng) / Made with [Marp](https://marp.app/)
uncover
fade
true
true
true

bg opacity:.2 blur:5px 50%

Getting Started with
Compliance & Governance
using Azure Policy

<style scoped>a { color: #36d; }</style>

🙋‍♂️ 🙋 🙋‍♀️


Agenda

  • Recapitulation of DevOps Journey
  • Compliance & Governance
  • Basics of Azure Policy

👨🏻‍💻 DevOps, DevSecOps, GitOps 👩‍💻


bg fit bg fit bg fit bg fit


image

<style scoped>img[alt="image"] { border: 3px solid #008AD7; width: 80%; } </style>

image

<style scoped>img[alt="image"] { border: 3px solid #008AD7; width: 80%; } </style>

DevOps, DevSecOps, GitOps

👨🏽‍💻 Site Reliability Engineering (SRE) 👩🏽‍💻


DevOps, DevSecOps, GitOps
Site Reliability Engineering (SRE)

👨🏻‍💻 Platform Engineering 👩🏻‍💻


DevOps, DevSecOps, GitOps
Site Reliability Engineering (SRE)
Platform Engineering

Governance Engineering


bg left:30% fit

“Good strategy and good governance are the grease and guide rails for success.” - Bill Bensing


Governance Engineering (SRE)

Applying SRE Principles to Regulated Software
Bill Bensing


Governance Eng. (Cloud Native)

Under Control: Why Governance Engineering
is Coming to Cloud Native

Ian Miell


"To put it plainly, regulators are going to expect compliance and audit functions to have the ability to report on their controls regularly, efficiently and clearly." - Ian Miell


Controlling Controls (Description)

Description vs. Implementation


  • Azure resources must exist only in allowed locations.
    For example, Norway or Europe regions.

Controlling Controls (Implementation)

Description vs. Implementation


  • A Cloud Service Provider policy written in a product.
    For example, Azure Policy.

Governance Engineering

  • Efficiency and Speed
  • Accuracy and Consistency
  • Transparency, Scalability
  • Adaptability
    - Ian Miell

bg right:35% 55%

Enforce Standards
& Assess Compliance

h:1.5em


bg height:80% bg height:80%


bg right:35% 55%

Establishes conventions for resources.

h:1.5em


bg right:35% 55%

What happens when the policy rule is matched?

h:1.5em


bg right:35% 55%

Demonstration:
Built-In Azure Policy Definition on Azure Portal


image

<style scoped>img[alt="image"] { border: 3px solid #008AD7; width: 90%; } </style>
Get-AzPolicyDefinition -BuiltIn `
    | Where-Object {$_.Properties.metadata.category -eq 'Tags'} `
    | Select-Object -ExpandProperty properties `
    | Select-Object -Property DisplayName `
    | Format-List

# OR

    | Where-Object {$_.Properties.metadata.category -eq 'Storage'} `

# OR

    | Where-Object {$_.Properties.metadata.category -eq 'Regulatory Compliance'} `

$policyDefinition = Get-AzPolicyDefinition `
    -BuiltIn | Where-Object `
    {$_.Properties.DisplayName -eq 'Require a tag on resources'}

# OR

    {$_.Properties.DisplayName -eq 'Allowed locations for resource groups'}

# OR

    {$_.Properties.DisplayName -eq 'Allowed locations'}

{
    "properties": {
        "displayName": "AuditResourcesTags",
        "policyType": "Custom",
        "mode": "All",
        "description": "Enforces required tags and its value on resources.",
        "metadata": {
            "version": "1.0.0",
            "category": "Tags"
        },
        //...

        //... tagName1, tagValue1, tagName2, tagValue2, etc.
        "parameters": {
            //...
            "tagName5": {
                "type": "String",
                "metadata": {
                    "displayName": "Fifth Tag Name",
                    "description": "Name of the tag, such as 'environment'."
                }
            },
            "tagValue5": {
                "type": "String",
                "metadata": {
                    "displayName": "Fifth Tag Value",
                    "description": "Value of the tag, such as 'production'."
                }
            }
        },
        //...

        //...
        "policyRule": {
            "if": {
                "not": {
                    "anyOf": [
                        //... tagName1, tagName2, etc.
                        {
                            "field": "[concat('tags[', parameters('tagName5'), ']')]",
                            "equals": "[parameters('tagValue5')]"
                        }
                    ]
                }
            },
            "then": { "effect": "audit" }
        }
    }
}

What about Resource Groups?


        //...
        "policyRule": {
            "if": {
                "allOf": [
                    {
                        "field": "type",
                        "equals": "Microsoft.Resources/subscriptions/resourceGroups"
                    },
                    {
                        "not": {
                            "anyOf": [
                                //... tagName1, tagName2, etc.
                                {
                                    "field": "[concat('tags[', parameters('tagName5'), ']')]",
                                    "equals": "[parameters('tagValue5')]"
                                }
                            ]
                        }
                    }
                ]
            },
            "then": { "effect": "audit" }
        }
    }
}

{
    "properties": {
        "displayName": "DenyActionDelete",
        "policyType": "Custom",
        "mode": "Indexed",
        "description": "Deny action delete for critical resources.",
        "metadata": {
            "version": "1.0.0",
            "category": "DenyAction"
        },
        //...

        // ...
        "parameters": {},
        "policyRule": {
            "if": {
                "anyOf": [
                    {
                        "field": "type",
                        "equals": "Microsoft.DocumentDB/databaseAccounts"
                    },
                    {
                        "field": "type",
                        "equals": "Microsoft.Storage/storageAccounts"
                    },
                    {
                        "field": "type",
                        "equals": "Microsoft.KeyVault/vaults"
                    }
                ]
            },
            // ...

            // ...
            "then": {
                "effect": "DenyAction",
                "details": {
                    "actionNames": [
                        "delete"
                    ],
                    "cascadeBehaviors": {
                        "resourceGroup": "deny"
                    }
                }
            }
        }
    }
}

New-AzPolicyDefinition `
        -Name $name `
        -Policy $policyFilePath `
        -SubscriptionId $subscriptionId

bg right:35% 55%

Determines the resources to which a policy definition is applied.

h:1.5em


bg right:35% 55%

Demonstration:
Azure Policy Assignments on Azure Portal


image

<style scoped>img[alt="image"] { border: 3px solid #008AD7; width: 90%; } </style>

image

<style scoped>img[alt="image"] { border: 3px solid #008AD7; width: 90%; } </style>

Exhibit: Azure Policy Assignment Require resources to have a 'Creator` tag.

$policyParameterObject = @{ 'tagName' = 'Creator' }

$message="Creator tag is required for resources."
$nonComplianceMessages = @( @{Message=$message} )

$policyAssignment = New-AzPolicyAssignment `
        -Name $REQUIRE_RESOURCES_CREATOR_TAG `
        -Scope "/subscriptions/$($azContext.Subscription.Id)" `
        -PolicyDefinition $policyDefinition `
        -PolicyParameterObject $policyParameterObject `
        -NonComplianceMessage $nonComplianceMessages

Exhibit: Azure Policy Assignment Require resources reside in allowed locations.

$allowedLocations = Get-AzLocation `
    | Where-Object `
    {($_.DisplayName -like '*europe*') -or ($_.DisplayName -like '*norway*')}

$policyParameterObject = @{'listOfAllowedLocations'=($allowedLocations.location)}

$message="The selected locations are not allowed for resources."
$nonComplianceMessages = @( @{Message=$message} )

$policyAssignment = New-AzPolicyAssignment `
    -Name $REQUIRE_RESOURCES_ALLOWED_LOCATIONS `
    -Scope "/subscriptions/$($azContext.Subscription.Id)" `
    -PolicyDefinition $policyDefinition `
    -PolicyParameterObject $policyParameterObject `
    -NonComplianceMessage $nonComplianceMessages
}

Exhibit: Azure Policy Assignment Audit resources to have the five tags. (Part 1/2)

$policyParameterObject = @{
    'tagName1' = 'Organization'
    'tagValue1' = 'Acme Corporation'
    'tagName2' = 'BusinessUnit'
    'tagValue2' = 'Road Runner'
    'tagName3' = 'ProjectOwner'
    'tagValue3' = 'Wile E. Coyote'
    'tagName4' = 'Application'
    'tagValue4' = 'Beep-Beep!'
    'tagName5' = 'Environment'
    'tagValue5' = 'Fast and Furry-ous'
}

Exhibit: Azure Policy Assignment Audit resources to have the five tags. (Part 2/2)

$message="Required tags and its values are needed for resources."
$nonComplianceMessages = @( @{Message=$message} )

$policyAssignment = New-AzPolicyAssignment `
    -Name $AUDIT_RESOURCES_TAGS `
    -Scope "/subscriptions/$($azContext.Subscription.Id)" `
    -PolicyDefinition $policyDefinition `
    -PolicyParameterObject $policyParameterObject `
    -NonComplianceMessage $nonComplianceMessages

Exhibit: Azure Policy Assignment DenyAction Delete

$message="Deny action delete for critical resources."
$nonComplianceMessages = @( @{Message=$message} )

$policyAssignment = New-AzPolicyAssignment `
    -Name $policyDefinition.Name `
    -Scope "/subscriptions/$($azContext.Subscription.Id)" `
    -PolicyDefinition $policyDefinition `
    -NonComplianceMessage $nonComplianceMessages

bg right:35% 55%

Demonstration:
Create resources that violates Azure Policy on Azure Portal.


Exhibit: Missing Required Tag

image

<style scoped>img[alt="image"] { border: 3px solid #008AD7; width: 70%; } </style>

Exhibit: Missing Allowed Locations

image

<style scoped>img[alt="image"] { border: 3px solid #008AD7; width: 65%; } </style>

Exhibit: DenyAction Delete

image

<style scoped>img[alt="image"] { border: 3px solid #008AD7; width: 65%; } </style>

bg right:35% 55%

Demonstration:
Create resources that violates Azure Policy through Infrastructure as Code.


💪


Exhibit: Azure Resource Manager (ARM) Templates

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",

  //...

  "resources": [
    {
      "name": "[format('store{0}', uniqueString(resourceGroup().id))]",
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2022-09-01",
      "tags": {},
      "location": "[resourceGroup().location]",
      "kind": "StorageV2",
      "sku": {
        "name": "[parameters('storageAccountType')]"
      }
    }
  ],
  "outputs": {}
}

giffiti

<style scoped>img[alt="giffiti"] { border: 3px solid #008AD7; width: 80%; } </style>

bg 55%


Exhibit: Azure Bicep Storage Account Without Tags

resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' = {
  name: uniqueStorageName
  location: location
  sku: {
    name: storageSKU
  }
  kind: 'StorageV2'
  properties: {
    supportsHttpsTrafficOnly: true
  }
  tags: null
}

Exhibit: Terraform Storage Account Without Tags

resource "azurerm_storage_account" "deleteme654" {
  name                     = "deleteme654"
  resource_group_name      = azurerm_resource_group.example.name
  location                 = azurerm_resource_group.example.name
  account_tier             = "Standard"
  account_replication_type = "LRS"
  tags                     = null
}

[
    {
        "info": {
            "evaluationDetails": {
                "evaluatedExpressions": [
                    {
                        "expression": "tags[Creator]",
                        "expressionKind": "Field",
                        "operator": "Exists",
                        "path": "tags[Creator]",
                        "result": "True",
                        "targetValue": "false"
                    }
                ],
                "reason": "Creator tag is required for resources."
            },
            "policyAssignmentId": ".../policyAssignments/RequireResourcesCreatorTag",
            "policyAssignmentName": "RequireResourcesCreatorTag",
            "policyAssignmentParameters": {
                "tagName": "Creator"
            },
            "policyAssignmentScope": "/subscriptions/***",
            "policyDefinitionDisplayName": "Require a tag on resources",
            "policyDefinitionEffect": "deny",
            "policyDefinitionId": "...",
            "policyDefinitionName": "871b6d14-10aa-478d-b590-94f262ecfa99",
            "policyExemptionIds": []
        },
        "type": "PolicyViolation"
    }
]

Exhibit: Azure Bicep

Resource Group not in Allowed Locations

resource newRG 'Microsoft.Resources/resourceGroups@2021-01-01' = {
  name: resourceGroupName
  location: 'Taiwan North'
}

Exhibit: Terraform

Resource Group not in Allowed Locations

resource "azurerm_resource_group" "deleteme987" {
  name     = "deleteme987"
  location = "Taiwan North"
}

[
  {
    "info": {
      "evaluationDetails": {
        "evaluatedExpressions": [
          {
            "expression": "type",
            "expressionKind": "Field",
            "expressionValue": "Microsoft.Resources/subscriptions/resourcegroups",
            "operator": "Equals",
            "path": "type",
            "result": "True",
            "targetValue": "Microsoft.Resources/subscriptions/resourceGroups"
          },
          {
            "expression": "location",
            "expressionKind": "Field",
            "expressionValue": "taiwannorth",
            "operator": "NotIn",
            "path": "location",
            "result": "True",
            "targetValue": [
              "northeurope",
              "westeurope",
              "norwayeast",
              "europe",
              "norway",
              "norwaywest"
            ]
          }
        ],
        "reason": "The selected locations are not allowed for resource groups."
      },
      //...

      //...
      "policyAssignmentId": ".../policyAssignments/RequireResourceGroupsAllowedLocations",
      "policyAssignmentName": "RequireResourceGroupsAllowedLocations",
      "policyAssignmentParameters": {
        "listOfAllowedLocations": [
          "northeurope",
          "westeurope",
          "norwayeast",
          "europe",
          "norway",
          "norwaywest"
        ]
      },
      "policyAssignmentScope": "/subscriptions/***",
      "policyDefinitionDisplayName": "Allowed locations for resource groups",
      "policyDefinitionEffect": "deny",
      "policyDefinitionId": "...",
      "policyDefinitionName": "e765b5de-1225-4ba3-bd56-1ac6695af988",
      "policyExemptionIds": []
    },
    "type": "PolicyViolation"
  }
]

Exhibit: DenyAction Delete for Storage Account

[
    {
        "info": {
            "evaluationDetails": {
                "evaluatedExpressions": [
                    {
                        "expression": "type",
                        "expressionKind": "Field",
                        "expressionValue": "Microsoft.Storage/storageAccounts",
                        "operator": "Equals",
                        "path": "type",
                        "result": "True",
                        "targetValue": "Microsoft.Storage/storageAccounts"
                    }
                ],
                "reason": "Deny action delete for critical resources."
            },
            // ...

            // ...
            "policyAssignmentId": ".../policyAssignments/DenyActionDelete",
            "policyAssignmentName": "DenyActionDelete",
            "policyAssignmentParameters": {},
            "policyAssignmentScope": "/subscriptions/***",
            "policyDefinitionDisplayName": "DenyActionDelete",
            "policyDefinitionEffect": "DenyAction",
            "policyDefinitionId": "/...",
            "policyDefinitionName": "DenyActionDelete",
            "policyExemptionIds": []
        },
        "type": "PolicyViolation"
    }
]

Agility

image

Governance

<style scoped>img[alt="image"] { width: 35%; float: center; } </style>

🤔 ❓


Marp bg 60%


bg 60% opacity:.2 blur:10px

🙏


bg 40%


This page intentionally left blank.