다음을 통해 공유


Notation, Azure Key Vault 및 자체 서명된 인증서를 사용하여 컨테이너 이미지 서명

이 문서는 컨테이너 이미지 및 기타 OCI(Open Container Initiative) 아티팩트 무결성 및 신뢰성을 보장하는 시리즈의 일부입니다. 전체 그림의 경우 서명이 중요한 이유를 설명하고 다양한 시나리오를 간략하게 설명하는 개요부터 시작합니다.

컨테이너 이미지 서명은 해당 인증 및 무결성을 보장하는 데 도움이 되는 프로세스입니다. 컨테이너 이미지에 추가된 디지털 서명은 배포 중에 확인됩니다. 서명은 이미지가 신뢰할 수 있는 게시자의 이미지이며 수정되지 않는지 확인하는 데 도움이 됩니다.

이 문서에서는 서명 프로세스와 관련된 다음 도구에 대해 설명합니다.

  • 표기법공증 프로젝트 커뮤니티 에서 개발하여 Microsoft에서 지원되는 오픈 소스 공급망 보안 도구입니다. 컨테이너 이미지 및 기타 아티팩트 서명 및 확인을 지원합니다.

    CI/CD(지속적인 통합 및 지속적인 업데이트) 파이프라인에서 Notation을 사용하여 컨테이너 이미지에 서명하려면 Azure Pipelines 또는 GitHub Actions에 대한 지침을 따르세요.

  • Azure Key Vault는 서명 키를 사용하여 인증서를 저장하기 위한 서비스입니다. 해당 키를 사용한 표기법은 Key Vault 플러그 인(notation-azure-kv)을 통해 컨테이너 이미지와 기타 아티팩트를 서명하고 검증할 수 있습니다.

  • Azure Container Registry는 해당 서명을 보는 것과 함께 컨테이너 이미지 및 기타 아티팩트에 서명을 연결하는 데 사용할 수 있는 프라이빗 레지스트리입니다.

이 문서에서는 다음 방법을 알아봅니다.

  • 표기법 명령줄 인터페이스(Notation CLI) 및 Key Vault 플러그인을 설치합니다.
  • Key Vault에서 자체 서명된 인증서를 만듭니다.
  • Container Registry 작업을 사용하여 컨테이너 이미지를 빌드하고 푸시합니다.
  • Notation CLI 및 Key Vault 플러그 인을 사용하여 컨테이너 이미지에 서명합니다.
  • Notation CLI를 사용하여 서명에 대해 컨테이너 이미지의 유효성을 검사합니다.
  • 타임스탬핑을 사용합니다.

필수 구성 요소

Notation CLI 및 Key Vault 플러그인 설치

  1. Linux AMD64 환경에 표기법 v1.3.2를 설치합니다. 다른 환경에 대한 패키지를 다운로드하려면 표기법 설치 가이드를 따릅니다.

    # Download, extract, and install
    curl -Lo notation.tar.gz https://github.com/notaryproject/notation/releases/download/v1.3.2/notation_1.3.2_linux_amd64.tar.gz
    tar xvzf notation.tar.gz
    
    # Copy the Notation binary to the desired bin directory in $PATH, for example
    cp ./notation /usr/local/bin
    
  2. Linux AMD64 환경에 Key Vault 플러그 인(notation-azure-kv) v1.2.1을 설치합니다.

    참고

    플러그 인의 릴리스 페이지에서 플러그 인에 대한 URL 및 SHA256 체크섬을 찾을 수 있습니다.

    notation plugin install --url https://github.com/Azure/notation-azure-kv/releases/download/v1.2.1/notation-azure-kv_1.2.1_linux_amd64.tar.gz --sha256sum 67c5ccaaf28dd44d2b6572684d84e344a02c2258af1d65ead3910b3156d3eaf5
    
  3. 사용 가능한 플러그 인을 나열하고 버전 notation-azure-kv 이 포함된 플러그 인이 목록에 포함되어 있는지 1.2.1 확인합니다.

    notation plugin ls
    

환경 변수 구성

이 문서에서 명령을 쉽게 실행하려면 기존 Container Registry 및 Key Vault 리소스와 일치하도록 Azure 리소스에 대한 값을 제공합니다.

  1. Key Vault 리소스 이름 구성:

    AKV_SUB_ID=myAkvSubscriptionId
    AKV_RG=myAkvResourceGroup
    # Name of the existing key vault used to store the signing keys
    AKV_NAME=myakv
    # Name of the certificate created in the key vault
    CERT_NAME=wabbit-networks-io
    CERT_SUBJECT="CN=wabbit-networks.io,O=Notation,L=Seattle,ST=WA,C=US"
    CERT_PATH=./${CERT_NAME}.pem
    
  2. Container Registry 및 이미지 리소스 이름을 구성합니다.

    ACR_SUB_ID=myAcrSubscriptionId
    ACR_RG=myAcrResourceGroup
    # Name of the existing registry (example: myregistry.azurecr.io)
    ACR_NAME=myregistry
    # Existing full domain of the container registry
    REGISTRY=$ACR_NAME.azurecr.io
    # Container name inside the container registry where the image will be stored
    REPO=net-monitor
    TAG=v1
    IMAGE=$REGISTRY/${REPO}:$TAG
    # Source code directory that contains the Dockerfile to build
    IMAGE_SOURCE=https://github.com/wabbit-networks/net-monitor.git#main
    

Azure CLI를 사용하여 로그인

az login

자세한 내용은 Azure CLI를 사용하여 Azure에 인증을 참조하세요.

Container Registry 및 Key Vault에 액세스 권한 부여

Container Registry 및 Key Vault를 사용하는 경우 안전하고 제어된 액세스를 보장하기 위해 적절한 권한을 부여해야 합니다. 특정 시나리오에 따라 사용자 보안 주체, 서비스 주체 또는 관리 ID와 같은 다양한 엔터티에 대한 액세스 권한을 부여할 수 있습니다. 이 문서에서는 로그인한 Azure 사용자에 대한 액세스 권한이 부여됩니다.

Container Registry에 대한 액세스 권한 부여

Microsoft Entra 속성 기반 액세스 제어(ABAC)에 사용하도록 설정된 레지스트리의 경우, Container Registry에서 컨테이너 이미지를 빌드하고 서명하기 위해 Container Registry Repository ReaderContainer Registry Repository Writer 역할이 필요합니다.

ABAC가 활성화되지 않은 레지스트리의 경우, AcrPull 역할과 AcrPush 역할이 필요합니다.

ABAC에 대한 자세한 내용은 리포지토리 권한에 대한 Microsoft Entra 특성 기반 액세스 제어를 참조하세요.

  1. Container Registry 리소스가 포함된 구독을 설정합니다.

    az account set --subscription $ACR_SUB_ID
    
  2. 역할을 할당합니다. 역할 할당에 사용할 올바른 역할은 레지스트리가 ABAC 사용 여부에 따라 달라집니다.

    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    ROLE1="Container Registry Repository Reader" # For ABAC-enabled registries. Otherwise, use "AcrPull" for non-ABAC-enabled registries.
    ROLE2="Container Registry Repository Writer" # For ABAC-enabled registries. Otherwise, use "AcrPush" for non-ABAC-enabled registries.
    az role assignment create --role "$ROLE1" --role "$ROLE2" --assignee $USER_ID --scope "/subscriptions/$ACR_SUB_ID/resourceGroups/$ACR_RG/providers/Microsoft.ContainerRegistry/registries/$ACR_NAME"
    

Key Vault에 대한 액세스 권한 부여

이 섹션에서는 Key Vault에 대한 액세스 권한을 부여하는 두 가지 옵션을 살펴봅니다.

자체 서명된 인증서를 사용하여 서명하려면 다음 역할이 필요합니다.

  • 인증서를 만들고 읽기 위한 Key Vault Certificates Officer
  • Key Vault Certificates User 기존 인증서를 읽는 경우
  • Key Vault Crypto User - 작업에 서명

Azure RBAC(역할 기반 액세스 제어)를 사용한 Key Vault 액세스에 대한 자세한 내용은 Azure 역할 기반 액세스 제어를 사용하여 Key Vault 키, 인증서 및 비밀에 대한 액세스 제공을 참조하세요.

  1. Key Vault 리소스가 포함된 구독을 설정합니다.

    az account set --subscription $AKV_SUB_ID
    
  2. 역할을 할당합니다.

    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    az role assignment create --role "Key Vault Certificates Officer" --role "Key Vault Crypto User" --assignee $USER_ID --scope "/subscriptions/$AKV_SUB_ID/resourceGroups/$AKV_RG/providers/Microsoft.KeyVault/vaults/$AKV_NAME"
    

Key Vault에서 액세스 정책 할당(레거시)

ID에는 다음 권한이 필요합니다.

  • 인증서를 만들기 위한 Create 권한
  • 기존 인증서를 읽기 위한 Get 권한
  • 작업에 서명하기 위한 Sign 권한

주체에 정책을 할당하는 방법에 대해 자세히 알아보려면 Key Vault 액세스 정책 할당(레거시)을 참조하세요.

  1. Key Vault 리소스가 포함된 구독을 설정합니다.

    az account set --subscription $AKV_SUB_ID
    
  2. Key Vault에서 액세스 정책을 설정합니다.

    USER_ID=$(az ad signed-in-user show --query id -o tsv)
    az keyvault set-policy -n $AKV_NAME --certificate-permissions create get --key-permissions sign --object-id $USER_ID
    

중요합니다

이 예제에서는 인증서를 만들고 컨테이너 이미지에 서명하는 데 필요한 최소 권한을 보여 줍니다. 요구 사항에 따라 더 많은 권한을 부여해야 할 수 있습니다.

Key Vault에서 자체 서명된 인증서 만들기(Azure CLI)

다음 단계에서는 테스트를 위해 자체 서명된 인증서를 만드는 방법을 보여줍니다.

  1. 인증서 정책 파일 만들기

    인증서 정책 파일은 다음 코드를 통해 실행된 후 Key Vault의 공증 프로젝트 인증서 요구 사항 과 호환되는 유효한 인증서를 만듭니다. 값은 ekus의 코드 서명에 대한 값이지만, Notation에서 아티팩트를 서명하는 데 필요 없습니다. 주체는 나중에 확인 중에 신뢰할 수 있는 ID로 사용됩니다.

    cat <<EOF > ./my_policy.json
    {
        "issuerParameters": {
        "certificateTransparency": null,
        "name": "Self"
        },
        "keyProperties": {
          "exportable": false,
          "keySize": 2048,
          "keyType": "RSA",
          "reuseKey": true
        },
        "secretProperties": {
          "contentType": "application/x-pem-file"
        },
        "x509CertificateProperties": {
        "ekus": [
            "1.3.6.1.5.5.7.3.3"
        ],
        "keyUsage": [
            "digitalSignature"
        ],
        "subject": "$CERT_SUBJECT",
        "validityInMonths": 12
        }
    }
    EOF
    
  2. 인증서를 만듭니다.

    az keyvault certificate create -n $CERT_NAME --vault-name $AKV_NAME -p @my_policy.json
    

Notation CLI 및 Key Vault 플러그 인을 사용하여 컨테이너 이미지 서명

  1. 개별 Azure ID를 사용하여 컨테이너 레지스트리에 인증합니다.

    az acr login --name $ACR_NAME
    

    중요합니다

    시스템에 Docker가 설치되어 있고 az acr login 또는 docker login를 사용하여 컨테이너 레지스트리에 인증한 경우, 자격 증명이 이미 저장되어 Notation에서 사용할 수 있습니다. 이 경우 컨테이너 레지스트리에 인증하기 위해 다시 실행할 notation login 필요가 없습니다. 표기법의 인증 옵션에 대한 자세한 내용은 OCI 규격 레지스트리를 사용하여 인증을 참조하세요.

  2. Azure Container Registry 작업을 사용하여 새 이미지를 빌드하고 푸시합니다. 태그는 변경 가능하고 덮어쓸 수 있으므로 항상 다이제스트 값을 사용하여 서명 이미지를 식별합니다.

    DIGEST=$(az acr build -r $ACR_NAME -t $REGISTRY/${REPO}:$TAG $IMAGE_SOURCE --no-logs --query "outputImages[0].digest" -o tsv)
    IMAGE=$REGISTRY/${REPO}@$DIGEST
    

    이 문서에서 이미지가 이미 빌드되어 레지스트리에 저장된 경우 태그는 편의를 위해 해당 이미지의 식별자 역할을 합니다.

    IMAGE=$REGISTRY/${REPO}:$TAG
    
  3. 서명 키의 ID를 가져옵니다. Key Vault의 인증서에는 여러 버전이 있을 수 있습니다. 다음 명령은 최신 버전의 키 ID를 가져옵니다.

    KEY_ID=$(az keyvault certificate show -n $CERT_NAME --vault-name $AKV_NAME --query 'kid' -o tsv)
    
  4. 서명 키 ID를 사용하여 COSE(CBOR 개체 서명 및 암호화) 서명 형식으로 컨테이너 이미지에 서명합니다. 자체 서명된 인증서로 서명하려면 플러그 인 구성 값을 self_signed=true설정해야 합니다.

    notation sign --signature-format cose --id $KEY_ID --plugin azure-kv --plugin-config self_signed=true $IMAGE
    

    Key Vault를 사용하여 인증하려면 기본적으로 다음 자격 증명 형식(사용하도록 설정된 경우)을 순서대로 시도합니다.

    자격 증명 형식을 지정하려면 라는 credential_type추가 플러그 인 구성을 사용합니다. 예를 들어 다음 예제와 같이 Azure CLI 자격 증명을 사용하도록 명시적으로 설정할 credential_typeazurecli 수 있습니다.

    notation sign --signature-format cose --id $KEY_ID --plugin azure-kv --plugin-config self_signed=true --plugin-config credential_type=azurecli $IMAGE
    

    다음 표에서는 다양한 자격 증명 형식의 credential_type 값을 보여 있습니다.

    자격 증명 유형 credential_type에 대한 값
    환경 자격 증명 environment
    워크로드 ID 자격 증명 workloadid
    관리 ID 자격 증명 managedid
    Azure CLI 자격 증명 azurecli

    참고

    표기법 v1.2.0부터 표기법은 OCI 참조자 태그 스키마 를 사용하여 기본적으로 컨테이너 레지스트리에 서명을 저장합니다. 필요한 경우 플래그를 사용하여 --force-referrers-tag false를 사용하도록 설정할 수도 있습니다. 컨테이너 레지스트리 기능은 CMK(고객 관리형 키)를 통해 암호화된 레지스트리를 제외하고 OCI 참조자 API를 지원합니다.

  5. 서명된 이미지 및 연결된 서명의 그래프를 봅니다.

    notation ls $IMAGE
    

Notation CLI를 사용하여 컨테이너 이미지 확인

컨테이너 이미지를 확인하려면 리프 인증서에 서명하는 루트 인증서를 트러스트 저장소에 추가하고 확인을 위한 트러스트 정책을 만듭니다. 이 문서에서 사용하는 자체 서명된 인증서의 경우 루트 인증서는 자체 서명된 인증서 자체입니다.

  1. 공용 인증서 다운로드:

    az keyvault certificate download --name $CERT_NAME --vault-name $AKV_NAME --file $CERT_PATH
    
  2. 서명 확인을 위해 다운로드한 공용 인증서를 명명된 신뢰 저장소에 추가합니다.

    STORE_TYPE="ca"
    STORE_NAME="wabbit-networks.io"
    notation cert add --type $STORE_TYPE --store $STORE_NAME $CERT_PATH
    
  3. 확인할 인증서를 나열합니다.

    notation cert ls
    
  4. 확인 전에 신뢰 정책을 구성합니다.

    신뢰 정책을 사용하면 사용자가 미세 조정된 확인 정책을 지정할 수 있습니다. 다음 예제에서는 이름이 인 wabbit-networks-images트러스트 정책을 구성합니다. 이 정책은 모든 아티팩트에서 $REGISTRY/$REPO 적용되며 형식$STORE_NAME의 명명된 신뢰 저장소 $STORE_TYPE 를 사용합니다. 또한 사용자가 X.509 주체 $CERT_SUBJECT가 있는 특정 ID를 신뢰한다고 가정합니다. 자세한 내용은 트러스트 저장소 및 트러스트 정책 사양을 참조하세요.

    cat <<EOF > ./trustpolicy.json
    {
        "version": "1.0",
        "trustPolicies": [
            {
                "name": "wabbit-networks-images",
                "registryScopes": [ "$REGISTRY/$REPO" ],
                "signatureVerification": {
                    "level" : "strict" 
                },
                "trustStores": [ "$STORE_TYPE:$STORE_NAME" ],
                "trustedIdentities": [
                    "x509.subject: $CERT_SUBJECT"
                ]
            }
        ]
    }
    EOF
    
  5. 이전에 만든 JSON 파일에서 트러스트 정책 구성을 가져오는 데 사용합니다 notation policy .

    notation policy import ./trustpolicy.json
    notation policy show
    
  6. 빌드 시간 후에 컨테이너 이미지가 변경되지 않았는지 확인하는 데 사용합니다 notation verify .

    notation verify $IMAGE
    

    신뢰 정책을 통해 이미지를 성공적으로 확인하면 확인된 이미지의 SHA256 다이제스트가 성공적인 출력 메시지로 반환됩니다.

타임스탬핑 사용

Notation v1.2.0 릴리스 이후 Notation은 RFC 3161 규격 타임스탬핑을 지원합니다. 이 개선된 기능은 타임스탬프 발행 기관(TSA)을 신뢰함으로써 인증서의 유효 기간 동안 생성된 서명의 신뢰를 확장합니다. 이 트러스트를 사용하면 인증서가 만료된 후에도 성공적인 서명 확인을 수행할 수 있습니다.

이미지 서명자는 신뢰할 수 있는 TSA가 생성한 타임스탬프를 사용하여 컨테이너 이미지에 서명해야 합니다. 이미지 검사자로서 이미지 서명자 및 관련된 TSA를 모두 신뢰하며, 신뢰 저장소 및 신뢰 정책을 통해 신뢰를 설정해야 합니다.

타임스탬핑은 인증서 만료로 인해 이미지를 주기적으로 다시 서명할 필요가 없도록 하여 비용을 절감합니다. 이 기능은 수명이 짧은 인증서를 사용하는 경우에 특히 중요합니다. 타임스탬핑을 사용하여 이미지에 서명하고 확인하는 방법에 대한 자세한 지침은 공증 프로젝트 타임스탬핑 가이드를 참조하세요.

Notation은 Azure Pipelines 및 GitHub Actions에서 CI/CD 솔루션을 제공합니다.

신뢰할 수 있는 컨테이너 이미지만 AKS(Azure Kubernetes Service)에 배포되도록 하려면 다음을 수행합니다.