티스토리 뷰

핸즈온2 : Azure Policy와 DevOps 연계 – 배포 전 Azure Policy 준수 검사

Azure DevOps 파이프라인 내에서 Azure Policy 준수 여부를 자동으로 확인하고, 비준수 시 배포를 중단하는 보안/거버넌스 실습을 시행해 보자.

 

사전 준비 사항

 

 

항목 설명
Azure DevOps 프로젝트 Azure DevOps 프로젝트가 있어야 하며 Service Connection 구성 필요
프로젝트 만들기 참조 및 Service Connection 참조
Azure Policy 정의 하나 이상의 정책 정의 및 할당 필요 (예: NSG에 모든 포트를 열지 말 것)
Service Principal 권한 DevOps의 Service Connection에 Policy Insights Reader 권한 필요
Azure CLI 설치 DevOps Agent에 설치되어 있어야 함
 

Azure CLI 환경에서 진행할 예정이니, Azure SA 업무 환경 구성 - Part 1, Azure SA 업무 환경 구성 - Part 2를 참조하여 환경을 작업 구성한다.

 

 

예시 시나리오

  • 배포 대상 region: eastus (정책에 의해 차단됨)
  • policyAssignmentName과 subscriptionId를 기준으로 정책 상태 쿼리 → 파이프라인에서 정책 위반 시 즉시 배포 중단
  • az policy state list 명령으로 비정상 리소스 탐지 → exit 1로 배포 중단

 

이 시나리오는 단순한 실습을 넘어 클라우드 거버넌스 자동화(Governance as Code), 보안 및 거버넌스 조기 검증(Shift-Left), DevOps와 정책의 통합(Policy-as-Code)이라는 큰 의미를 가진다.

 

 

1. Azure Policy 정의

1. 먼저 "Allowed locations" 정책의 Policy Definition ID를 확인한다.

az policy definition list --query "[?displayName=='Allowed locations'].{name:name, id:id}" -o table​
Azure-HandsOn-Demo# az policy definition list --query "[?displayName=='Allowed locations'].{name:name, id:id}" -o table
Name
------------------------------------
e56962a6-4747-49cd-b67b-bf8b01975c4c

 

 

2. koreacentral만 리소스 배포 허용하는 내용의 Azure Policy를 할당한다.

 
az policy assignment create \
  --name 'allow-koreacentral-only' \
  --display-name 'Allow only koreacentral location' \
  --policy <YOUR_Policy_Definition_ID> \
  --params '{ "listOfAllowedLocations": { "value": ["koreacentral"] } }' \
  --scope "/subscriptions/<YOUR_SUBSCRIPTION_ID>"

 

Azure-HandsOn-Demo# az policy assignment create \
> --name 'allow-koreacentral-only' \
> --display-name 'Allow only koreacentral location' \
> --policy e56962a6-4747-49cd-b67b-bf8b01975c4c \
> --params '{ "listOfAllowedLocations": { "value": ["koreacentral"] } }' \
> --scope "/subscriptions/3864xxxx-xxxx-xxxxx-xxxx-4a08ac96xxxx"
Readonly attribute scope will be ignored in class <class 'azure.mgmt.resource.policy.v2021_06_01.models._models_py3.PolicyAssignment'>
{
  "description": null,
  "displayName": "Allow only koreacentral location",
  "enforcementMode": "Default",
  "id": "/subscriptions/3864xxxx-xxxx-xxxxx-xxxx-4a08ac96xxxx/providers/Microsoft.Authorization/policyAssignments/allow-koreacentral-only",
  "identity": null,
  "location": null,
  "metadata": {
    "createdBy": "6b1063b6-302b-4141-afe1-82917f102a7b",
    "createdOn": "2025-08-03T08:46:06.4521179Z",
    "updatedBy": null,
    "updatedOn": null
  },
  "name": "allow-koreacentral-only",
  "nonComplianceMessages": null,
  "notScopes": null,
  "parameters": {
    "listOfAllowedLocations": {
      "value": [
        "koreacentral"
      ]
    }
  },
  "policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4c",
  "scope": "/subscriptions/3864xxxx-xxxx-xxxxx-xxxx-4a08ac96xxxx",
  "systemData": {
    "createdAt": "2025-08-03T08:46:06.220901+00:00",
    "createdBy": "zerobig.kim@gmail.com",
    "createdByType": "User",
    "lastModifiedAt": "2025-08-03T08:46:06.220901+00:00",
    "lastModifiedBy": "zerobig.kim@gmail.com",
    "lastModifiedByType": "User"
  },
  "type": "Microsoft.Authorization/policyAssignments"
}
Azure-HandsOn-Demo#

 

 

 

2. Azure DevOps 파이프라인 구성 (YAML)

Service Connection 생성

1. 프로젝트 만들기 참여 새 프로젝트를 생성한다.

2. 좌측 하단의 Project Settings > Service connections을 선택하고 Create service connection을 선택한다.

 

3. New service connection에서 Azure Resource Manager 체크하고 Next를 선택한다.

4. New Azure service connection 에서 대상 구독을 선택하고 로그인 수행 후, Service Connection Name을 입력하고 하단 SecurityGrant access permission to all pipelines를 체크하고 Save 한다.

 

 

Azure Repos 구성

Repos > Files에서 화면 하단에 Initialize를 클릭하여 초기화 한다.

 

 

Azure Pipeline 구성

1. 좌측 하단의 Pipelines을 선택 후 Create Pipeline을 선택한다.

2. Connect 화면에서 Azure Repos GIT을 선택한다.

3. Select 화면에서 앞에서 생성한 리포지토리를 선택한다. 예) PRJ-ADO-AzurePolicy-Demo

4. Configure 화면에서 Starter pipeline을 선택한다.

5. 기본 제공되는 코드를 삭제하고 다음 코드를 붙여넣는다.

trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

variables:
  subscriptionId: '3864b016-4594-40ad-a96b-4a08ac96b537'
  azureRegion: 'eastus'  # koreacentral이 아니므로 정책 위반 예상
  policyAssignmentName: 'allow-koreacentral-only'

steps:
- task: AzureCLI@2
  displayName: 'Check Azure Policy Compliance'
  inputs:
    azureSubscription: 'Azure-MVP-Subscription'
    scriptType: 'bash'
    scriptLocation: 'inlineScript'
    inlineScript: |
      echo "INFO: Checking Azure Policy compliance for assignment: $(policyAssignmentName)"
      
      # az cli 쿼리를 통해 지난 하루 전에 비준수 리소스의 '개수'만 직접 가져오기
      # 지난 30일간 조회
      NON_COMPLIANT=$(az policy state list \
        --subscription ${{ variables.subscriptionId }} \
        --policy-assignment "allow-koreacentral-only" \
        --from $(date -u -d '1 days ago' +%Y-%m-%dT%H:%M:%SZ) \
        --to $(date -u +%Y-%m-%dT%H:%M:%SZ) \
        --query "[?complianceState=='NonCompliant']" \
        --output json)
      
      echo "$NON_COMPLIANT" > policy_check.json
      COUNT=$(jq length policy_check.json)
      
      echo "INFO: Non-compliant resource count: $COUNT"
      
      # 개수가 0보다 큰지 비교하여 파이프라인 실패 처리
      if [ "$COUNT" -gt 0 ]; then
        echo "Azure Policy violation detected. Blocking deployment."
        exit 1
      else
        echo "Azure Policy compliance check passed. Proceeding with deployment."
      fi

 

  • 8행 <YOUR_SERVICE_CONNECTION_NAME>를 자신의 구독 ID로 대체한다.
  • 12행 근처에 Settings를 클릭하면 Azure CLI assistant 창이 전시된다.

5. 우측 상단의 Save and run을 선택하고 다음 화면에서 다시 Save and run을 선택한다.

 

6. Authorize resource를 선택하고 우측 상단에 Run new를 선택하여 다시 파이프라인을 실행한다.

 

 

 

3. 실행 결과 확인

파이프라인을 클릭하여 Job을 선택한다.

 

 

실행 결과 로그를 확인한다.

 

  • 54 행 정책 체크(az policy state list) 수행 결과 정책 위반을 감지하고 exit 1로 배포가 중단됨을 확인한다.

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/10   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함