存取 Azure Container Registry (ACR) 的多種認證授權方法 | The Will Will Web

The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

存取 Azure Container Registry (ACR) 的多種認證授權方法

Azure Container Registry (ACR) 是 Azure 雲端平台非常重要的基礎建設,不但可以用來儲存 Docker Images,也可以用來儲存 Helm Charts 在上面。除此之外,企業所需的身份認證授權功能也相當完整,但只要扯到認證授權,事情就會複雜許多。這篇文章我將深入探討 ACR 各種不同的認證授權方法,幫助企業導入 ACR 使用。

關於操作 ACR 的多種認證方法

我是從 Authenticate with an Azure container registry 這頁開始看起,其內容相當詳細,唯獨缺少 REST API 的相關說明。

如果你想透過 Docker CLI (docker login) 或 AKS 來存取 ACR 上面的資源,看這篇文章就可以解決所有問題。

這篇文章提到多種認證方法:

  1. Admin account

    因為一個 ACR 只能有一個預設的「管理者帳號」,對於獨立開發者(只有一位開發人員)來說非常方便,但是對一間公司有多位開發者要共用一個 ACR 的情境來說,就顯的比較不實用了。

    請注意:ACR 預設並沒有啟用 Admin user 帳號,如果要用的話,請記得要先啟用才行!

    ACR 預設並沒有啟用 Admin user 帳號

    你也可以用 Azure CLI 來啟用 Admin user 帳號:

    az acr update -n <acrName> --admin-enabled true
    

    啟用 Admin user 之後,你就會得到一個 Username兩個 Password (任選一個皆可):

    啟用 Admin user 之後,你就會得到一個 Username 與兩個 Password (任選一個皆可)

    然後就可以輕鬆的使用 docker login <Login server> 來進行登入!

  2. Individual login with Azure AD

    我們公司就是採用這種認證方式,因為大家都有 Microsoft 365 帳號(因為背後是使用 Azure AD 目錄),所以可以直接透過 Azure AD 進行授權。如果大家想要存取 ACR 的話,只要輸入以下命令就可以登入完成:

    az login
    az account set -s <subscriptionId>
    az acr login --name <acrName>
    

    當你執行 az acr login 命令的時候,預設就隱含包括 docker login 登入,所以如果你沒有事先安裝 Docker 的話,是無法執行的。當然,你在執行完 az acr login 登入之後,不用再執行一次 docker login <Login server> 登入!

    注意:使用 az acr login 登入 ACR 的話,有效期間只有 3 小時而已!當時間一過,就無法再進行 docker pushdocker pull 囉,你必須再次執行 az acr login 才能繼續使用。

    如果你目前執行 Azure CLI 的電腦並沒有安裝 Docker,例如在 Azure Cloud Shell 執行命令。那麼你可能會想先取得 docker login 的臨時帳號密碼,讓你在其他電腦可以執行 docker login 登入,此時你可以透過以下命令來取得帳號密碼:

    az acr login --name <acrName> --expose-token
    

    這個命令會取得以下 JSON 結果:

    {
      "accessToken": "eyJhbGciOiJSUzI1NiIs[...]24V7wA",
      "loginServer": "contosouniversity.azurecr.io"
    }
    

    然後你就可以用以下命令登入,請注意,登入帳號是固定的 00000000-0000-0000-0000-000000000000 喔,不能亂打!

    docker login contosouniversity.azurecr.io --username 00000000-0000-0000-0000-000000000000 --password eyJhbGciOiJSUzI1NiIs[...]24V7wA
    

    注意:不要忘記,這組帳號密碼的有效期間只有 3 小時而已!

  3. AD Service principal

    如果你想在 CI/CD 的 Pipelines 存取 ACR 的話,可以先在 Azure AD 建立 service principal 物件,然後透過 Azure RBAC 進行 IAM 授權,讓該 service principal 可以對 ACR 進行 Pull, Push 或其他管理動作!

    常用來授權的角色有:AcrPull (pull)、AcrPush (pull and push) 與 Owner (pull, push, and assign roles to other users)

    完整的授權角色清單可參考 Azure Container Registry roles and permissions

    完整的設定步驟,請參考 Azure Container Registry authentication with service principals 文件說明。

  4. Managed identity for Azure resources

    如果你想從現有的 Azure 服務或資源存取 ACR 的話,例如透過 VM 或其他 PaaS 服務,就可以用這種方式進行驗證,這種認證方法也是適用於 CI/CD pipeline 的情境,不過僅限於從現有 Azure 資源存取 ACR 的情況。

  5. Integrate with AKS

    現在 AKS 與 ACR 整合已經是非常簡單了,幾個命令執行完就可以整合完畢!

    az aks update -n myAKSCluster -g myResourceGroup --attach-acr <acr-name>
    

    如果要移除 AKS 與 ACR 的連結,也是一個命令搞定!

    az aks update -n myAKSCluster -g myResourceGroup --detach-acr <acr-name>
    

    除此之外,使用 az acr import 命令還能將 Docker Hub 上面的 image 直接複製一份到 ACR 之中,還挺方便的!

    az acr import  -n contosouniversity --source docker.io/library/nginx:latest --image nginx:v1
    

    上述命令會將 docker.io/library/nginx:latest 匯入成為 nginx:v1,你之後就可以用 docker pull contosouniversity.azurecr.io/nginx:v1 下載 image 回來!

  6. Repository-scoped access token

    如果你想限制特定使用者「只能」存取特定 repository (image) 的話,就可以使用這個只有 Premium 等級才有個授權方式。

    關於不同的 ACR 等級 (Tier) 可以參考 Azure Container Registry service tiers 文章說明。

如何透過 REST API 操作 ACR

昨天在思考著如何利用 Azure Container Registry (ACR) 的 REST API 來查詢目前我們公司的 Container Registry 中有哪些 image 可用,但是實作的過程卻是意外的困難。一來是 ACR 官方文件關於 REST API 的說明非常精簡,完全沒有提到授權與認證的部分,導致嘗試了好久才正確理出頭緒。以下我將透過 WSL 進行實作,實作過程你就可以看出要如何正確取得 Bearer Token 並成功取得各種 ACR 裡面的資訊。

由於 Azure Container Registry REST API reference 上面列出許多 REST API 可用,且這些 REST API 主要是用 OAuth 2.0 作為授權標準,如果你不瞭解 Microsoft identity platform and OAuth 2.0 authorization code flow 的話,很難可以呼叫成功,建議先看瞭解一下,然後才能參考以下步驟取得「正確」的 Bearer Token 才能成功發出 HTTP 要求!

以下我們以 Repository - Get List 為例,試圖取得 ACR 中所有的 Repository (images) 清單:

  1. 先透過 cURL 發出一次呼叫,取得未授權的結果

    export registry="contosouniversity.azurecr.io"
    curl -v https://$registry/acr/v1/_catalog
    

    這個過程你會取得一段 JSON 結果:

    {
      "errors": [
        {
          "code": "UNAUTHORIZED",
          "message": "authentication required, visit https://aka.ms/acr/authorization for more information.",
          "detail": [
            {
              "Type": "registry",
              "Name": "catalog",
              "Action": "*"
            }
          ]
        }
      ]
    }
    

    從回應的 HTTP Headers 中你也會看到以下 Www-Authenticate 標頭內容:

    Www-Authenticate: Bearer realm="https://contosouniversity.azurecr.io/oauth2/token",service="contosouniversity.azurecr.io",scope="registry:catalog:*"
    
  2. 接著透過 Basic Auth 認證方式取得 OAuth 2.0 提供的 Access Token

    這個步驟是最困難的,因為 Access Tokens - Get 文件通通沒有說明! 😠

    首先,你要透過 /oauth2/token 取得 Token,但必須額外傳入 servicescope 參數才行!這兩個參數,都來自於上個步驟的 Www-Authenticate 標頭值中,且不同的 REST API 呼叫,會有不同的 scope 值,而且也沒有文件可以查,反正就先呼叫失敗一次,就知道需要哪些 scope 了!

    其次就是 Basic Auth 認證的帳號、密碼的來源,文件也都沒有交代,我完全是瞎子摸象,有點痛苦!還好先有看過 Authenticate with an Azure container registry 這份文件,否則還真的怎樣都猜不到。

    export user='00000000-0000-0000-0000-000000000000'
    export pass=$(az acr login --expose-token --name contosouniversity -o json | jq '.accessToken' -r)
    export scope="registry:catalog:*"
    curl -s -u "$user:$pass" "https://$registry/oauth2/token?service=$registry&scope=$scope"
    

    這個命令可以取得 OAuth 2.0 標準的 access_tokenrefresh_token 來用:

    {
      "access_token": "eyJhbGciOiJSUzI1NiIsIn[...]BWoOTane5d6mg",
      "refresh_token": "eyJhbGciOiJSUzI1NiIsIn[...]CSFvfL6Whsueg"
    }
    
  3. 呼叫原本要呼叫的 API 並傳入 Bearer Token

    我可以透過 jq 快速篩選出我要的 access_token

    export accessToken=$(curl -s -u "$user:$pass" "https://$registry/oauth2/token?service=$registry&scope=$scope" | jq -C '.access_token' -r)
    

    接著加入 Authorization 標題,並放入上個步驟取得的 access_token,即可成功呼叫 REST API 囉!

    curl -s -H "Authorization: Bearer $accessToken" https://$registry/acr/v1/_catalog | jq -C
    

    取得的結果為:

    {
      "repositories": [
        "nginx"
      ]
    }
    

結語

其實 ACR 功能超多、超好用,可惜 Microsoft Docs 的文件跟不太上,但我後來發現,其實在 ACR 的 GitHub Repo 都有完整的文件,也都有在更新,大家想深入瞭解可以上去查閱!

相關連結