Azureコンテナインスタンスをテストするための証明書権限の作成



動機
シナリオの相互TLSをテストするにはApplication Gateway 私は簡単にクライアントの証明書と同様にCAチェーンを作成することができます使い捨ての環境が必要
  • 右側の証明書要求を企業CAとその不必要な反復で把握するために、正しい種類の(クライアント)証明書を要求しないときに示される一般的なエラーFAILED:unhandled critical extension
  • アプリケーションゲートウェイなしでFAILED:self signed certificate - それは、相互のTLSのための自己署名証明書を受け入れません

  • セットアップ
    アイデアは、オンデマンド一時的なコンテナを作成することですAzure Container Instances with openssl フードの下で、永続的な発行された証明書とAzureファイル・ストレージのキーは、これらが目標環境にダウンロードされることができるか、再び上記の容器を走らせるとき、もう一つの時間のために再利用されることができます.

    Azureコンテナレジストリにイメージをビルドするには、次の手順に従います.az acr build できるので、ローカルDockerのインストールが必要です.実際のコンテナ実行では、Azureファイルストレージにマウントされた新しいAzureコンテナインスタンスにイメージが取り込まれます.

    all files are available on repository https://github.com/KaiWalter/aci-certificate-authority



    Dockerfile
    それはDockerfile インストールするopenssl だけでなくsudo and bash 良い処置のために.選んだnginx なぜなら、同じコンテナで後でHTTPリクエストを処理する必要があるからです.私は所望のOpenSSLの設定とコンテナ上の反復タスクを支援するいくつかのシェルスクリプトを追加します.
    FROM nginx:alpine
    
    RUN apk update && \
      apk add --no-cache openssl sudo bash && \
      rm -rf "/var/cache/apk/*"
    
    COPY *.sh /root/
    RUN chmod u+x /root/*.sh
    
    COPY openssl.cnf /etc/ssl1.1/openssl.cnf
    

    OpenSSL理研
    私が使用する設定はthe default - とdir 後でCAを操作するフォルダに調整します.
    ...
    dir      = /root/ca       # Where everything is kept
    certs    = $dir/certs     # Where the issued certs are kept
    crl_dir  = $dir/crl       # Where the issued crl are kept
    database = $dir/index.txt # database index file.
    #unique_subject = no   # Set to 'no' to allow creation of
                           # several certs with same subject.
    new_certs_dir = $dir/newcerts  # default place for new certs.
    
    certificate = $dir/cacert.pem # The CA certificate
    serial      = $dir/serial     # The current serial number
    crlnumber   = $dir/crlnumber  # the current crl number
                                  # must be commented out to leave a V1 CRL
    crl  = $dir/crl.pem           # The current CRL
    private_key = $dir/private/cakey.pem# The private key
    ...
    

    for later signing settings like certificate = $dir/cacert.pem and private_key = $dir/private/cakey.pem are crucial, as openssl expects those file exactly at the configured location



    準備する.sh
    このスクリプトは/root/ca コンテナが起動され、このフォルダがアジュールファイルストレージにマウントされたときにフォルダー.
    #!/bin/sh
    
    cd /root/ca
    
    chmod 600 -R /root/ca
    
    mkdir -p /root/ca/certs
    mkdir -p /root/ca/crl
    mkdir -p /root/ca/newcerts
    mkdir -p /root/ca/private
    mkdir -p /root/ca/requests
    
    touch index.txt
    
    if [ ! -f "serial" ]
    then
        echo '01' > serial
    fi
    
    ls -lh
    

    クリーンアップ.sh
    既に作成した証明書ファイルを削除する/root/ca 再びやり直す
    #!/bin/sh
    
    find /root/ca -name '*.pem' -print0 | xargs -0 rm -f
    find /root/ca -name '*.pfx' -print0 | xargs -0 rm -f
    find /root/ca -name '*.srl' -print0 | xargs -0 rm -f
    

    createecash
    対応する秘密キーを使用して証明書認証を作成します

    for /C=XX/ST=YY/L=ZZ/O=Acme Corp/OU=CA/CN=dev.cloud.acmecorp.com a sensible subject specification needs to be provided


    #!/bin/sh
    
    cd /root/ca
    
    openssl req -new -x509 -days 9999 -keyout private/cakey.pem -out cacert.pem -subj "/C=XX/ST=YY/L=ZZ/O=Acme Corp/OU=CA/CN=dev.cloud.acmecorp.com"
    

    CreateClientsh
    プライベートキーを使用してサンプルクライアント証明書を作成し、この証明書を署名し、確認します
    #!/bin/sh
    
    cd /root/ca
    
    openssl genrsa -out private/client1-key.pem 4096
    openssl req -new -key private/client1-key.pem -out requests/client1-csr.pem -subj "/C=XX/ST=YY/L=ZZ/O=Acme Corp/OU=CA/CN=client1.dev.cloud.acmecorp.com"
    openssl x509 -req -days 9999 -in requests/client1-csr.pem -CA cacert.pem -CAkey private/cakey.pem -CAcreateserial -out certs/client1-crt.pem
    openssl verify -CAfile cacert.pem certs/client1-crt.pem
    openssl pkcs12 -inkey private/client1-key.pem -in certs/client1-crt.pem -export -out client1.pfx
    

    セットアップ.ストレージと共有を作成する
    コンテナレジストリとストレージアカウントを持つ環境が作成されますsetup.ps1 :
    $resourceGroupName = "myrg"
    $location = "westeurope"
    
    $registryName = "mycaserveracr"
    $storageAccountName = "mycastorage"
    $storageAccountShareName = "cashare"
    
    $resourceGroup = Get-AzResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue
    if (!$resourceGroup) {
        New-AzResourceGroup -Name $resourceGroupName -Location $location
    }
    
    $registry = Get-AzContainerRegistry -Name $registryName -ResourceGroupName $resourceGroupName -ErrorAction SilentlyContinue
    if (!$registry) {
        New-AzContainerRegistry -Name $registryName -ResourceGroupName $resourceGroupName -EnableAdminUser -Sku Standard
    }
    
    $storageAccount = Get-AzStorageAccount -Name $storageAccountName -ResourceGroupName $resourceGroupName -ErrorAction SilentlyContinue
    if (!$storageAccount) {
        New-AzStorageAccount -Name $storageAccountName -ResourceGroupName $resourceGroupName -Location $location -SkuName Standard_GRS
        $storageAccount = Get-AzStorageAccount -Name $storageAccountName -ResourceGroupName $resourceGroupName -ErrorAction Stop
    }
    
    $storageAccountKey = (Get-AzStorageAccountKey -Name $storageAccountName -ResourceGroupName $resourceGroupName)[0].Value
    $stoCtx = New-AzStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $storageAccountKey
    
    $stoShare = Get-AzStorageShare -Name $storageAccountShareName -Context $stoCtx -ErrorAction SilentlyContinue
    if (!$stoShare) {
        New-AzStorageShare -Name $storageAccountShareName -Context $stoCtx
        $stoShare = Get-AzStorageShare -Name $storageAccountShareName -Context $stoCtx -ErrorAction Stop
    }
    

    ビルド.PS 1 -ビルドとプッシュコンテナ
    このPowerShellスクリプトを使用すると、コンテナはAzureコンテナのレジストリ上で直接ビルドされます( Adminアカウントを有効にします).
    $resourceGroupName = "myrg"
    $registryName = "mycaserveracr"
    
    $registry = Get-AzContainerRegistry -Name $registryName -ResourceGroupName $resourceGroupName
    $tag = Get-Date -AsUTC -Format yyMMdd_HHmmss
    $imagePrefix = "ca-server"
    $image = "$($registry.LoginServer)/$($imagePrefix):$tag"
    
    az acr build -t $image -r $registryName $PSScriptRoot
    

    I use Azure CLI for the container build here as a similar command seems not available for Azure PowerShell



    ラン.ps 1 -コンテナを実行する
    すべてのリソースが存在する場合、1つのスクリプトを使用してコンテナを起動し、実際の証明書操作を行うには、ファイル共有およびシェルにコンテナにマウントできます.
    $resourceGroupName = "myrg"
    $registryName = "mycaserveracr"
    $registry = Get-AzContainerRegistry -Name $registryName -ResourceGroupName $resourceGroupName
    $credentials = Get-AzContainerRegistryCredential -Name $registryName -ResourceGroupName $resourceGroupName
    
    $imagePrefix = "ca-server"
    $containerGroupName = "ca-server"
    
    $storageAccountName = "mycastorage"
    $storageAccountShareName = "cashare"
    $storageAccountKey = (Get-AzStorageAccountKey -Name $storageAccountName -ResourceGroupName $resourceGroupName)[0].Value
    
    # identify ca server image in registry
    $latestTag = ((Get-AzContainerRegistryTag -RegistryName $registryName -RepositoryName $imagePrefix).Tags | Sort-Object -Descending Name | Select-Object -First 1).Name
    
    $image = "$($registry.LoginServer)/$($imagePrefix):$latestTag"
    
    # ------------------------------------------------------------------------------------------
    # spin up ca image in ACI
    
    $containerInstanceLocation = $registry.location
    if ($registry.location -eq "germanywestcentral") {
        $containerInstanceLocation = "westeurope"
    }
    
    az container create --name $containerGroupName -g $resourceGroupName -l $containerInstanceLocation `
        --image $image `
        --registry-login-server $registry.LoginServer --registry-username $credentials.Username --registry-password $credentials.Password `
        --ip-address public --ports 80 `
        --azure-file-volume-account-name $storageAccountName `
        --azure-file-volume-account-key $storageAccountKey `
        --azure-file-volume-share-name $storageAccountShareName `
        --azure-file-volume-mount-path "/root/ca"
    
    $containerGroup = az container show -n $containerGroupName -g $resourceGroupName -o json | ConvertFrom-Json
    
    az container exec -n $containerGroupName -g $containerGroup.resourceGroup --exec-command "/bin/bash"
    
    # ------------------------------------------------------------------------------------------
    # clean up
    
    az container stop -n $containerGroup.name -g $containerGroup.resourceGroup
    
    az container delete --ids $containerGroup.id --yes
    

    this script still uses the admin account to allow ACI to pull the image from ACR. Alternatively an user assigned identity could be used.

    replacing ACI location germanywestcentral with westeurope : issue is a failed exec command that only occurs when the deployment is on Atlas, it works in other regions on k8s; germanywestcentral is an Atlas-only region



    実行
    基本環境を利用できるようにするには、上記のスクリプトでリソース名を調整して実行します.
    ./setup.ps1
    ./build.ps1
    
    そして-必要に応じて-環境を起動します.
    ./run.ps1
    
    コンテナが起動され、シェルのアパーチャが起動されると、suに切り替え、ルートホームに変更し、フォルダを準備します.
    bash-5.1# su
    / # cd ~
    ~ # ./prepare.sh
    total 1K
    drwxrwxrwx    2 root     root           0 Feb 20 18:31 certs
    drwxrwxrwx    2 root     root           0 Feb 20 18:31 crl
    -rwxrwxrwx    1 root     root           0 Feb 20 18:31 index.txt
    drwxrwxrwx    2 root     root           0 Feb 20 18:31 newcerts
    drwxrwxrwx    2 root     root           0 Feb 20 18:31 private
    drwxrwxrwx    2 root     root           0 Feb 20 18:31 requests
    -rwxrwxrwx    1 root     root           3 Feb 20 18:31 serial
    
    CA証明書とキーを作成できます.
    ~ # ./createca.sh
    Generating a RSA private key
    .......................................................+++++
    ..............+++++
    writing new private key to 'private/cakey.pem'
    Enter PEM pass phrase:
    Verifying - Enter PEM pass phrase:
    -----
    
    クライアントの証明書を作成できます.
    ~ # ./createclient.sh
    Generating RSA private key, 4096 bit long modulus (2 primes)
    .....................................................................................................................++++
    .....................................................................................................................................................................................................++++
    e is 65537 (0x010001)
    Signature ok
    subject=C = XX, ST = YY, L = ZZ, O = Acme Corp, OU = CA, CN = client1.dev.cloud.acmecorp.com
    Getting CA Private Key
    Enter pass phrase for private/cakey.pem:
    certs/client1-crt.pem: OK
    Enter Export Password:
    Verifying - Enter Export Password:
    
    2 x終了し、PowerShellに戻り、環境をクリーンアップします.
    ~ # exit
    bash-5.1# exit
    exit
    

    ファイル作成
    ~ # find /root/ca -name '*.pem'
    /root/ca/cacert.pem
    /root/ca/certs/client1-crt.pem
    /root/ca/private/cakey.pem
    /root/ca/private/client1-key.pem
    /root/ca/requests/client1-csr.pem
    ~ # find /root/ca -name '*.pfx'
    /root/ca/client1.pfx
    ~ # find /root/ca -name '*.srl'
    /root/ca/cacert.srl
    

    最後の思考
    「ちょうど」Azure記憶装置の中に横たわっているCA証明書とキーを貸すのは賢明でないかもしれません.他方、ストレージは仮想ネットワークにリンクされることができ、コンテナインスタンスは仮想ネットワーク内で動作することができ、特定のネットワーク境界からのみ敏感な情報へのアクセスを保護することができる.
    とにかく、私はこのアプローチのシンプルさと柔軟性が好きです.