如何使用 API 管理中的用戶端憑證驗證保護 API

適用於:所有 API 管理 層

API 管理可讓您以用戶端憑證和相互 TLS 驗證保護對 API 的存取 (意即,用戶端對 API 管理)。 您可以使用原則運算式,驗證連線用戶端所提供的憑證,並針對所需的值檢查憑證屬性。

有關如何使用用戶端憑證,保護對 API 後端服務之存取 (即 APIM 到後端) 的資訊,請參閱如何使用用戶端憑證驗證來保護後端服務

如需 API 授權的概念概觀,請參閱 APIM 中的 API 驗證和授權

憑證選項

針對憑證驗證,API 管理可以檢查 APIM 執行個體中管理的憑證。 如果您選擇使用 API 管理來管理用戶端憑證,您有下列選項:

  • 請參考在 Azure Key Vault 中的受控憑證
  • 直接在 API 管理中新增憑證檔案

建議執行金鑰保存庫憑證,因為這有助於改善 API 管理的安全性:

  • 儲存在金鑰保存庫中的憑證,可以跨服務重複使用
  • 可以將細微存取原則套用至,儲存在金鑰保存庫中的憑證
  • 在金鑰保存庫中,已更新的憑證會自動在 API 管理中旋轉。 將金鑰保存庫更新之後,在 API 管理中的憑證會在 4 小時內進行更新。 您也可以使用 Azure 入口網站,或透過管理 REST API 來手動重新整理憑證。

必要條件

  • 如果您尚未建立 API 管理服務執行個體,請參閱 建立 API 管理服務執行個體

  • 您需要存取憑證和密碼,才能在 Azure 金鑰保存庫中,管理或上傳至 API 管理服務。 該憑證必須為 CER 或 PFX 格式。 可接受自我簽署憑證。

    如果您使用自我簽署憑證,請在 APIM 執行個體中安裝信任根和中繼 CA 憑證

    注意

    使用層不支援憑證驗證的 CA 憑證。

金鑰保存庫整合的必要條件

  1. 如果您還沒有金鑰保存庫,請建立一個。 如需建立金鑰保存庫的步驟,請參閱快速入門:使用 Azure 入口網站建立金鑰保存庫

    若要建立憑證或將憑證匯入金鑰保存庫,請參閱快速入門:使用 Azure 入口網站從 Azure Key Vault 設定及擷取憑證

  2. 在 API 管理執行個體中啟用系統指派或使用者指派的受控識別

設定金鑰保存庫存取權

  1. 在入口網站中,瀏覽至您的金鑰保存庫。

  2. 從左側功能表中選取 [存取設定],並記下已設定的 [權限模型]

  3. 根據權限模型,為 APIM 受控識別設定金鑰保存庫存取原則Azure RBAC 存取權

    若要新增金鑰保存庫存取原則:

    1. 在左側功能表中,選取 [存取原則]
    2. 在 [存取原則] 頁面上,選取 [+ 建立]
    3. 在 [權限] 索引標籤的 [祕密權限] 下,選取 [取得] 與 [列出],然後選取 [下一步]
    4. 在 [主體] 索引標籤的 [選取主體] 中,搜尋受控識別的資源名稱,然後選取 [下一步]。 如果您使用系統指派的身分識別,則主體是您 API 管理執行個體的名稱。
    5. 再次選取 [下一步]。 在 [檢閱 + 建立] 索引標籤中,選取 [建立]

    若要設定 Azure RBAC 存取權:

    1. 在左側功能表中,選取 [存取控制 (IAM)]
    2. 在 [存取控制 (IAM)] 頁面上,選取 [新增角色指派]
    3. 在 [角色] 索引標籤上,選取 [金鑰保存庫祕密使用者]
    4. 在 [成員] 索引標籤上,選取 [受控識別]>[+ 選取成員]
    5. 在 [選取受控識別] 頁面上,選取系統指派的受控識別或與 APIM 執行個體相關聯的使用者指派受控識別,然後選取 [選取]
    6. 選取檢閱+指派

金鑰保存庫防火牆的需求

如果您的金鑰保存庫已啟用金鑰保存庫防火牆,則下列為其他需求:

  • 您必須使用 API 管理執行個體的系統指派受控識別來存取金鑰保存庫。

  • 在金鑰保存庫防火牆中,啟用 [允許信任的 Microsoft 服務略過此防火牆] 選項。

  • 當您選取要新增至 Azure API 管理的憑證或祕密時,請確定您的本機用戶端 IP 位址可以暫時存取金鑰保存庫。 如需詳細資訊,請參閱設定 Azure Key Vault 網路設定

    完成設定之後,您可以在金鑰保存庫防火牆中封鎖用戶端位址。

虛擬網路需求

如果 API 管理執行個體已部署在虛擬網路中,也請設定下列網路設定:

  • 在 API 管理子網路上啟用 Azure Key Vault 的服務端點
  • 設定網路安全性群組 (NSG) 規則,以允許對 AzureKeyVault 和 AzureActiveDirectory 服務標籤的輸出流量。

如需詳細資料,請參閱在 VNet 中設定 Azure API 管理時的網路設定

新增金鑰保存庫憑證

請參閱金鑰保存庫整合的必要條件

重要

將金鑰保存庫憑證新增至 API 管理執行個體時,您必須具有從金鑰保存庫列出秘密的權限。

警告

在 API 管理中使用金鑰保存庫憑證時,請小心不要刪除用來存取金鑰保存庫的憑證、金鑰保存庫,或受控識別。

如果要將金鑰保存庫憑證新增至 API 管理:

  1. Azure 入口網站中,瀏覽至您的 API 管理執行個體。

  2. [安全性] 底下,選取 [憑證]

  3. 選取 [憑證]>[+新增]

  4. [識別碼] 中,輸入您選擇的名稱。

  5. [憑證] 中,選取 [金鑰保存庫]

  6. 輸入金鑰保存庫憑證的識別碼,或選擇 [選取] 從金鑰保存庫來選取憑證。

    重要

    如果您自行輸入金鑰保存庫憑證識別碼,請確定這個沒有版本資訊。 否則,憑證在金鑰保存庫中更新後,不會在 API 管理中自動旋轉。

  7. 在 [用戶端身分識別] 中,選取系統指派或現有的使用者指派受控識別。 了解如何在 API 管理服務中新增或修改受控識別

    注意

    身分識別需要從金鑰保存庫來取得和列出憑證。 如果您尚未設定金鑰保存庫的存取權,API 管理會提示您,以便可以使用必要的權限自動設定身分識別。

  8. 選取 [新增]。

    將金鑰保存庫憑證新增至入口網站中 API 管理 的螢幕快照。

  9. 選取 [儲存]。

上傳憑證

如果要將用戶端憑證上傳至 API 管理:

  1. Azure 入口網站中,瀏覽至您的 API 管理執行個體。

  2. [安全性] 底下,選取 [憑證]

  3. 選取 [憑證]>[+新增]

  4. [識別碼] 中,輸入您選擇的名稱。

  5. [憑證] 中,選取 [自訂]

  6. 瀏覽以選取憑證 .pfx 檔案,然後輸入其密碼。

  7. 選取 [新增]。

    將客戶端憑證上傳至入口網站中 API 管理 的螢幕快照。

  8. 選取 [儲存]

注意

如果只想使用憑證向 APIM 驗證用戶端,則可上傳 CER 檔案。

啟用 APIM 執行個體來接收和驗證用戶端憑證

開發人員、基本、標準或進階層級

若要在開發人員、基本、基本 v2、標準、標準 v2 或 進階版 層中透過 HTTP/2 接收和驗證用戶端憑證,您必須在 [自定義網域] 刀鋒視窗上啟用交涉用戶端憑證設定,如下所示。

交涉客戶端憑證

使用層

若要在使用層中接收並驗證用戶端憑證,您必須在 [自訂網域] 刀鋒視窗上啟用 [要求用戶端憑證] 設定,如下所示。

要求主體憑證

驗證用戶端憑證的原則

使用 validate-client-certificate 原則來驗證用戶端憑證的一個或多個屬性,藉以存取您的 API 管理執行個體中裝載的 API。

設定原則來驗證一個或多個屬性,包括憑證簽發者、主體、指紋、憑證是否經過線上撤銷清單驗證,以及其他屬性。

使用內容變數進行憑證驗證

您也可以使用context變數建立原則運算式,以檢查用戶端憑證。 下列各節中的範例顯示使用 context.Request.Certificate 屬性和其他 context 屬性的運算式。

注意

利用應用程式閘道公開 APIM 閘道端點時,相互憑證驗證可能無法正常執行。 這是因為應用程式閘道可做為第 7 層負載平衡器,會使用後端 APIM 服務建立不同的 SSL 連線。 因此,用戶端在初始 HTTP 要求中附加的憑證不會轉送至 APIM。 不過,您可以將伺服器變數選項做為因應措施,用來傳輸憑證。 如需詳細指示,請參閱相互驗證伺服器變數

重要

  • 從 2021 年 5 月開始,API 管理執行個體的 hostnameConfigurationnegotiateClientCertificate 設定為 True 時,context.Request.Certificate 屬性只會要求憑證。 negotiateClientCertificate 預設是設定為 false。
  • 如果您的用戶端中停用 TLS 重新交涉,您可能會在使用 context.Request.Certificate 屬性要求憑證 時看到 TLS 錯誤。 如果發生這種情況,請在用戶端中啟用 TLS 重新交涉設定。
  • API 管理 v2 層不支持認證重新談判。

檢查簽發者和主旨

您可以設定下面的原則來檢查用戶端憑證的簽發者和主旨:

<choose>
    <when condition="@(context.Request.Certificate == null || !context.Request.Certificate.Verify() || context.Request.Certificate.Issuer != "trusted-issuer" || context.Request.Certificate.SubjectName.Name != "expected-subject-name")" >
        <return-response>
            <set-status code="403" reason="Invalid client certificate" />
        </return-response>
    </when>
</choose>

注意

若要停用檢查憑證撤銷清單,請使用 context.Request.Certificate.VerifyNoRevocation() 而非 context.Request.Certificate.Verify()。 如果用戶端憑證是自我簽署的,則必須將根 (或中繼) CA 憑證上傳到 API 管理,context.Request.Certificate.Verify()context.Request.Certificate.VerifyNoRevocation() 才能運作。

檢查指紋

您可以設定下面的原則來檢查用戶端憑證的指紋:

<choose>
    <when condition="@(context.Request.Certificate == null || !context.Request.Certificate.Verify() || context.Request.Certificate.Thumbprint != "DESIRED-THUMBPRINT-IN-UPPER-CASE")" >
        <return-response>
            <set-status code="403" reason="Invalid client certificate" />
        </return-response>
    </when>
</choose>

注意

若要停用檢查憑證撤銷清單,請使用 context.Request.Certificate.VerifyNoRevocation() 而非 context.Request.Certificate.Verify()。 如果用戶端憑證是自我簽署的,則必須將根 (或中繼) CA 憑證上傳到 API 管理,context.Request.Certificate.Verify()context.Request.Certificate.VerifyNoRevocation() 才能運作。

檢查指紋是否符合已上傳到 API 管理的憑證

下列範例說明如何檢查用戶端憑證的指紋是否符合已上傳到 API 管理的憑證:

<choose>
    <when condition="@(context.Request.Certificate == null || !context.Request.Certificate.Verify()  || !context.Deployment.Certificates.Any(c => c.Value.Thumbprint == context.Request.Certificate.Thumbprint))" >
        <return-response>
            <set-status code="403" reason="Invalid client certificate" />
        </return-response>
    </when>
</choose>

注意

若要停用檢查憑證撤銷清單,請使用 context.Request.Certificate.VerifyNoRevocation() 而非 context.Request.Certificate.Verify()。 如果用戶端憑證是自我簽署的,則必須將根 (或中繼) CA 憑證上傳到 API 管理,context.Request.Certificate.Verify()context.Request.Certificate.VerifyNoRevocation() 才能運作。

提示

文章所述的用戶端憑證死結問題可以透過數種方式自行顯示,例如要求凍結、要求在逾時後導致 403 Forbidden 狀態碼、context.Request.Certificatenull。 此問題通常會影響內容長度大約為 60 KB 或更大的 POSTPUT 要求。 若要防止此問題發生,請在 [自訂網域] 刀鋒視窗上開啟所需主機名稱的 [交涉用戶端憑證] 設定,如本文件的第一個影像所示。 使用階層不提供此功能。

下一步