为客户端身份验证设置 Microsoft Entra ID

警告

目前,Microsoft Entra 客户端身份验证和托管标识令牌服务在 Linux 上互不兼容。

对于在 Azure 上运行的群集,建议使用 Microsoft Entra ID 保护对管理终结点的访问。 本文介绍了如何设置 Microsoft Entra ID 来对 Service Fabric 群集的客户端进行身份验证。

在 Linux 上,请在创建群集之前完成以下步骤。 在 Windows 上,也可选择为现有群集配置 Microsoft Entra 身份验证

在本文中,“应用程序”一词用来指 Microsoft Entra 应用程序,而不是 Service Fabric 应用程序;将在必要时进行区分。 通过 Microsoft Entra ID,组织(称为租户)可管理用户对应用程序的访问。

Service Fabric 群集提供其管理功能的各种入口点,包括基于 Web 的 Service Fabric ExplorerVisual Studio。 因此,需要创建两个 Microsoft Entra 应用程序来控制对群集的访问:一个 Web 应用程序和一个本机应用程序。 创建应用程序后,将用户分配到只读和管理员角色。

注意

目前,Service Fabric 不支持对存储使用 Microsoft Entra 身份验证。

注意

已知问题是在 Azure 门户中无法查看已启用 Linux Microsoft Entra ID 的群集上的应用程序和节点。

注意

Microsoft Entra ID 现在要求验证应用程序(应用注册)发布者域或使用默认方案。 有关更多信息,请参阅配置应用程序的发布者域单租户应用程序中的 AppId URI 需要使用默认方案或已验证的域

注意

从 Service Fabric 11.0 开始,Service Fabric Explorer 将需要单页应用程序重定向 URI 而非 Web 重定向 URI。

先决条件

本文假设已创建了一个租户。 如果还没有,请先阅读如何获取 Microsoft Entra 租户。 为了简化涉及到配置 Microsoft Entra ID 与 Service Fabric 群集的某些步骤,我们创建了一组 Windows PowerShell 脚本。 某些操作需要对 Microsoft Entra ID 拥有管理级访问权限。 如果脚本遇到 401 或 403“Authorization_RequestDenied”错误,管理员需要执行脚本。

  1. 使用 Azure 管理权限进行身份验证。
  2. 将存储库克隆到计算机。
  3. 对于已安装脚本,确保具备所有先决条件

创建 Microsoft Entra 应用程序并为用户分配角色

我们将使用这些脚本创建两个 Microsoft Entra 应用程序来控制对群集的访问:一个 Web 应用程序和一个本机应用程序。 创建表示群集的应用程序后,将为 Service Fabric 支持的角色创建用户:只读和管理员。

SetupApplications.ps1

运行 SetupApplications.ps1 并提供租户 ID、群集名称、Web 应用程序 URI 和 Web 应用程序回复 URL 作为参数。 使用 -remove 删除应用注册。 使用 -logFile <log file path> 会生成脚本日志。 有关更多信息,请参阅脚本帮助 (help .\setupApplications.ps1 -full)。 脚本会创建 Web 和本机应用程序来代表你的 Service Fabric 群集。 这两个新应用注册条目采用以下格式:

  • ClusterName_Cluster
  • ClusterName_Client

注意

对于国家/地区云(例如由世纪互联运营的 Microsoft Azure),还应指定 -Location 参数。

参数

  • tenantId:可以通过执行 PowerShell 命令 Get-AzureSubscription 找到你的 TenantId。 执行此命令,为每个订阅显示 TenantId。

  • clusterName:ClusterName 用于为脚本创建的 Microsoft Entra 应用程序添加前缀。 它不需要完全匹配实际的群集名称。 旨在更加轻松地将 Microsoft Entra 项目映射到其配合使用的 Service Fabric 群集。

  • SpaApplicationReplyUrl:SpaApplicationReplyUrl 是 Microsoft Entra ID 在用户完成登录后返回给用户的默认终结点。 将此终结点设置为群集的 Service Fabric Explorer 的终结点。 如果创建 Microsoft Entra 应用程序来表示现有群集,请确保此 URL 与现有群集的终结点匹配。 如果为新群集创建应用程序,请计划群集将要拥有的终结点,并确保不使用现有群集的终结点。 默认情况下,Service Fabric Explorer 终结点为:https://<cluster_domain>:19080/Explorer/index.html

  • webApplicationUri:WebApplicationUri 是“已验证域”的 URI,或使用 API 方案格式 API://{{租户 ID}}/{{群集名称}} 的 URI。 有关更多信息,请参阅单租户应用程序中的 AppId URI 需要使用默认方案或已验证的域

    示例 API 方案:API://0e3d2646-78b3-4711-b8be-74a381d9890c/mysftestcluster

SetupApplications.ps1 示例

# if using local Shell



# cd clouddrive 
# git clone https://github.com/Azure-Samples/service-fabric-aad-helpers
# cd service-fabric-aad-helpers
# code .

$tenantId = '0e3d2646-78b3-4711-b8be-74a381d9890c'
$clusterName = 'mysftestcluster'
$spaApplicationReplyUrl = 'https://mysftestcluster.chinaeast.cloudapp.chinacloudapi.cn:19080/Explorer/index.html' # <--- client browser redirect url
#$webApplicationUri = 'https://mysftestcluster.contoso.com' # <--- must be verified domain due to AAD changes
$webApplicationUri = "API://$tenantId/$clusterName" # <--- doesn't have to be verified domain

$configObj = .\SetupApplications.ps1 -TenantId $tenantId `
  -ClusterName $clusterName `
  -SpaApplicationReplyUrl $spaApplicationReplyUrl `
  -AddResourceAccess `
  -WebApplicationUri $webApplicationUri `
  -Verbose

该脚本输出后续命令 $configObj 变量,并输出 Azure 资源管理器模板所需的 JSON。 复制 JSON 输出,并在创建或修改现有群集时使用 创建启用了 Microsoft Entra ID 的群集

SetupApplications.ps1 示例输出

Name                           Value
---- -----
WebAppId                       f263fd84-ec9e-44c0-a419-673b1b9fd345
TenantId                       0e3d2646-78b3-4711-b8be-74a381d9890c
ServicePrincipalId             3d10f55b-1876-4a62-87db-189bfc54a9f2
NativeClientAppId              b22cc0e2-7c4e-480c-89f5-25f768ecb439

-----ARM template-----
"azureActiveDirectory": {
  "tenantId":"0e3d2646-78b3-4711-b8be-74a381d9890c",
  "clusterApplication":"f263fd84-ec9e-44c0-a419-673b1b9fd345",
  "clientApplication":"b22cc0e2-7c4e-480c-89f5-25f768ecb439"
},

azureActiveDirectory 参数对象 JSON

"azureActiveDirectory": {
  "tenantId":"<guid>",
  "clusterApplication":"<guid>",
  "clientApplication":"<guid>"
},

SetupUser.ps1

SetupUser.ps1 用于通过上面的 $configObj 输出变量将用户帐户添加到新建的应用程序注册。 为要配置应用注册的用户帐户指定用户名,并为管理权限指定“isAdmin”。 如果用户帐户是新的,请同时提供新用户的临时密码。 首次登录时需要更改密码。 如果使用“-remove”,将删除用户帐户,而不仅仅是应用注册。

SetupUser.ps1 用户(读取)示例

.\SetupUser.ps1 -ConfigObj $configobj `
  -UserName 'TestUser' `
  -Password 'P@ssword!123' `
  -Verbose

SetupUser.ps1 管理员(读/写)示例

.\SetupUser.ps1 -ConfigObj $configobj `
  -UserName 'TestAdmin' `
  -Password 'P@ssword!123' `
  -IsAdmin `
  -Verbose

SetupClusterResource.ps1

可以选择性地使用 SetupClusterResource.ps1 导出现有群集资源 ARM 模板、添加/修改“azureActiveDirectory”配置和重新部署模板。 使用“-Whatif”只会导出和修改模板,但不会重新部署配置更改。 此脚本确实需要 Azure“Az”模块和群集资源组的名称。

SetupClusterResource.ps1 -whatIf 示例

# requires azure module 'az'
# install-module az
$resourceGroupName = 'mysftestcluster'
.\SetupClusterResource.ps1 -configObj $configObj `
  -resourceGroupName $resourceGroupName `
  -WhatIf

验证并准备好处理模板后,重新运行不带“-WhatIf”的脚本或使用 PowerShell cmdlet“New-AzResourceGroupDeployment”来部署模板。

SetupClusterResource.ps1 示例

$resourceGroupName = 'mysftestcluster'
.\SetupClusterResource.ps1 -configObj $configObj `
  -resourceGroupName $resourceGroupName

注意

使用新的群集资源 Microsoft Entra 配置更改更新群集预配 ARM 模板或脚本。

对于正在配置的“API 权限”,可能需要“授予管理员同意”。 导航到“Azure 应用注册”边栏选项卡并将群集名称添加到筛选器。 对于这两个注册,请打开“API 权限”,并选择“授予管理员同意”(如果可用)。

Screenshot that shows Grant admin consent selected on the Azure App registrations blade.

Screenshot that shows the Grant admin consent confirmation with Yes highlighted.

验证 Microsoft Entra 配置

导航到 Service Fabric Explorer (SFX) URL。 它应与参数 spaApplicationReplyUrl 相同。 应显示 Azure 身份验证对话框。 使用配置了新的 Microsoft Entra 配置的帐户登录。 验证管理员帐户是否拥有读/写访问权限,以及用户是否拥有读取访问权限。 对群集进行的任何修改(例如执行操作)都属于管理操作。

有关设置 Microsoft Entra ID 的故障排除帮助

Microsoft Entra ID 的设置和使用可能有一定难度,可以参考下面的一些指导来调试问题。 可以在“SetupApplications.ps1”和“SetupUser.ps1”脚本中使用“-logFile”参数来启用 PowerShell 脚本日志记录,以查看输出。

注意

随着标识平台的迁移(ADAL 到 MSAL),Azure AZ 已取代 AzureRM,并且由于支持多个版本的 PowerShell,依赖项并不一定是正确或最新的,从而导致脚本执行错误。 从 Azure power Shell 运行 PowerShell 命令和脚本可以减少会话自动身份验证和托管标识出错的可能性。

Request_BadRequest

问题

不是有效的引用更新。 Http 状态代码:400。

VERBOSE: POST with 157-byte payload
VERBOSE: received -byte response of content type application/json
>> TerminatingError(Invoke-WebRequest): "{"error":{"code":"Request_BadRequest","message":"Not a valid reference update.","innerError":{"date":"2022-09-11T22:17:16","request-id":"61fadb2a-478b-4483-8f23-d17e13732104","client-request-id":"61fadb2a-478b-4483-8f23-d17e13732104"}}}"
confirm-graphApiRetry returning:True
VERBOSE: invoke-graphApiCall status: 400
exception:
Response status code doesn't indicate success: 400 (Bad Request).

Invoke-WebRequest: /home/<user>/clouddrive/service-fabric-aad-helpers/Common.ps1:239
Line |
 239 |  …   $result = Invoke-WebRequest $uri -Method $method -Headers $headers  …
     |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | {"error":{"code":"Request_BadRequest","message":"Not a valid reference update.","innerError":{"date":"2022-09-11T22:17:16","request-id":"61fadb2a-478b-4483-8f23-d17e13732104","client-request-id":"61fadb2a-478b-4483-8f23-d17e13732104"}}}

at invoke-graphApiCall, /home/<user>/clouddrive/service-fabric-aad-helpers/Common.ps1: line 239
at invoke-graphApi, /home/<user>/clouddrive/service-fabric-aad-helpers/Common.ps1: line 275
at add-roleAssignment, /home/<user>/clouddrive/service-fabric-aad-helpers/SetupUser.ps1: line 193
at add-user, /home/<user>/clouddrive/service-fabric-aad-helpers/SetupUser.ps1: line 244
at enable-AADUser, /home/<user>/clouddrive/service-fabric-aad-helpers/SetupUser.ps1: line 178
at main, /home/<user>/clouddrive/service-fabric-aad-helpers/SetupUser.ps1: line 136
at <ScriptBlock>, /home/<user>/clouddrive/service-fabric-aad-helpers/SetupUser.ps1: line 378
at <ScriptBlock>, /home/<user>/clouddrive/aad-test.ps1: line 43
at <ScriptBlock>, <No file>: line 1
WARNING: invoke-graphApiCall response status: 400
invoke-graphApi count:0 statuscode:400 -uri https://graph.chinacloudapi.cn/v1.0/0e3d2646-78b3-4711-b8be-74a381d9890c/servicePrincipals/3d10f55b-1876-4a62-87db-189bfc54a9f2/appRoleAssignedTo -headers System.Collections.Hashtable -body System.Collections.Hashtable -method post
confirm-graphApiRetry returning:True

原因

配置更改尚未传播。 脚本将重试具有 HTTP 状态代码 400 和 404 的某些请求。

解决方案

脚本将重试具有 HTTP 状态代码 400 和 404 的某些请求,直到达到提供的“-timeoutMin”(默认为 5 分钟)。 可以根据需要重新执行脚本。

Service Fabric Explorer 提示选择证书

问题

成功登录到 Service Fabric Explorer 中的 Microsoft Entra ID 后,浏览器返回到主页,但会出现提示用户选择证书的消息。

SFX certificate dialog

原因

未在 Microsoft Entra ID 群集应用程序中为用户分配角色。 因此,Service Fabric 群集的 Microsoft Entra 身份验证失败。 Service Fabric Explorer 会故障回复到证书身份验证。

解决方案

遵循有关设置 Microsoft Entra ID 的说明操作,并为用户分配角色。 此外,我们建议打开“访问应用需要的用户分配”,如 SetupApplications.ps1 所示。

使用 PowerShell 进行连接失败并出现错误:“指定的凭据无效”

问题

使用 PowerShell 以“AzureActiveDirectory”安全模式连接到群集时,成功登录到 Microsoft Entra ID 后,连接失败并显示错误:“指定的凭据无效”。

解决方案

解决方案同上。

登录时,Service Fabric Explorer 返回失败信息:“AADSTS50011”

问题

用户尝试登录到 Service Fabric Explorer 中的 Microsoft Entra ID 时,页面返回故障:“AADSTS50011: 回复地址 <url> 与针对应用程序 <guid> 配置的回复地址不匹配”。

SFX reply address doesn't match

原因

代表 Service Fabric Explorer 的群集 (web) 应用程序尝试根据 Microsoft Entra ID 进行身份验证,在执行请求的过程中提供了重定向返回 URL。 但是,该 URL 并未列在 Microsoft Entra 应用程序的“回复 URL”列表中。

解决方案

在群集的“Microsoft Entra 应用注册”页上,选择“身份验证”,然后在“重定向 URI”部分下,将 Service Fabric Explorer URL 添加到列表中。 保存所做更改。

Web application reply URL

登录时,通过 PowerShell 使用 Microsoft Entra 身份验证连接到群集会生成错误:"AADSTS50011"

问题

尝试通过 PowerShell 使用 Microsoft Entra ID 连接到 Service Fabric 群集时,登录页会返回故障:“AADSTS50011: 在请求中指定的回复 URL 与为应用程序 <guid> 配置的回复 URL 不匹配”。

原因

与前面的问题类似,PowerShell 尝试针对 Microsoft Entra ID 进行身份验证,而 Microsoft Entra ID 提供 Microsoft Entra 应用程序的“回复 URL”列表中未列出的重定向 URL。

解决方案

使用与上述问题相同的过程,但 URL 必须设置为 urn:ietf:wg:oauth:2.0:oob,这是命令行身份验证的特殊重定向。

执行脚本导致授权错误

问题

PowerShell 脚本可能无法执行完成 Microsoft Entra 配置所需的所有 REST 命令,并出现错误“Authorization_RequestDenied”、“特权不足,无法完成操作”。 示例错误:

Invoke-WebRequest: /home/<user>/clouddrive/service-fabric-aad-helpers/Common.ps1:239
Line |
 239 |  …   $result = Invoke-WebRequest $uri -Method $method -Headers $headers  …
     |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | {"error":{"code":"Authorization_RequestDenied","message":"Insufficient privileges to complete the
     | operation.","innerError":{"date":"2022-08-29T14:46:37","request-id":"c4fd3acc-1558-4950-8028-68bb058f7bf0","client-request-id":"c4fd3acc-1558-4950-8028-68bb058f7bf0"}}}
...
invoke-graphApi count:0 statuscode:403 -uri https://graph.chinacloudapi.cn/v1.0/72f988bf-86f1-41af-91ab-2d7cd011db47/oauth2PermissionGrants -headers System.Collections.Hashtable -body System.Collections.Hashtable -method post
Write-Error: /home/<user>/clouddrive/service-fabric-aad-helpers/SetupApplications.ps1:364
Line |
 364 |      assert-notNull $result "aad app service principal oauth permissio …
     |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | aad app service principal oauth permissions User.Read configuration failed

Write-Error: /home/<user>/clouddrive/service-fabric-aad-helpers/SetupApplications.ps1:656
Line |
 656 |  main
     |  ~~~~
     | exception:  exception: assertion failure: object: message:aad app service principal oauth permissions User.Read configuration failed  Exception:
     | /home/<user>/clouddrive/service-fabric-aad-helpers/Common.ps1:22 Line |   22 |          throw "assertion failure: object:$obj message:$msg"      |         
     | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~      | assertion failure: object: message:aad app service principal oauth permissions User.Read configuration failed  
...

原因

当执行脚本的用户帐户无权执行 REST 调用时,会返回此错误。 如果用户对正在创建或修改的对象没有管理员/管理/写入权限,则可能会发生这种情况。

解决方案

与 Azure 租户或 Microsoft Entra ID 的管理员协作完成所有剩余操作。 提供的脚本是幂等的,因此可以重新执行这些脚本以完成该过程。

通过 PowerShell 使用 Microsoft Entra 身份验证连接群集

若要连接 Service Fabric 群集,请使用以下 PowerShell 命令示例:

Connect-ServiceFabricCluster -ConnectionEndpoint <endpoint> -KeepAliveIntervalInSec 10 -AzureActiveDirectory -ServerCertThumbprint <thumbprint>

若要了解详细信息,请参阅 Connect-ServiceFabricCluster cmdlet

是否可以在多个群集中重复使用同一个 Microsoft Entra 租户?

是的。 请记得将 Service Fabric Explorer 的 URL 添加到群集 (Web) 应用程序。 否则 Service Fabric Explorer 无法正常工作。

启用 Microsoft Entra ID 时为何仍需要服务器证书?

FabricClient 和 FabricGateway 执行相互身份验证。 在 Microsoft Entra 身份验证期间,Microsoft Entra 集成向服务器提供客户端标识,客户端使用服务器证书来验证服务器的标识。 有关 Service Fabric 证书的详细信息,请参阅 X.509 证书和 Service Fabric

后续步骤

在设置 Microsoft Entra 应用程序并为用户设置角色后,配置并部署群集