microsoft / service-fabric-client-dotnet

.NET client library for Service Fabric
MIT License
66 stars 36 forks source link

Missing details in documentation on how to connect from PowerShell #104

Open bjorn-einar-bjartnes-4ss opened 2 years ago

bjorn-einar-bjartnes-4ss commented 2 years ago

Describe the bug

Maybe an alternative title could be - how to connect given that I have the Az-Context with permissions to manage the cluster?

I am trying to connect from an Azure Automation account in a similar fashion to Az.ServiceFabric, but have not been successful following the documentation. The Az.ServiceFabric command will only update services made with ARM templates, so I am trying my luck using this library.

Using Az.ServiceFabric we can connect to Service fabric from Azure Automation accounts by setting the Az context and then running commands.

Connect-AzAccount `
    -ServicePrincipal `
    -Tenant $ServicePrincipalConnection.TenantId `
    -ApplicationId $ServicePrincipalConnection.ApplicationId `
    -CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint

Get-AzSubscription -SubscriptionName $SubscriptionName -TenantId $ServicePrincipalConnection.TenantId | Set-AzContext

I am trying to use this package from Azure Automation and connection following Connect-SFCluster, but struggling to figure out how to make it work in a similar fashion.

I have tried to connect using

Connect-SFCluster -ConnectionEndpoint $ServiceFabricConnectionEndpoint `
                  -AzureActiveDirectory `
                  -ServerCertThumbprint $ServicePrincipalConnection.CertificateThumbprint `
                  -ClientTimeout 90 

but it fails with

System.EntryPointNotFoundException: Unable to find an entry point named 'GetPerAdapterInfo' in DLL 'iphlpapi.dll'.
   at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Platform.WebUI.<AcquireAuthorizationAsync>d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---

I have also tried supplying "the AAD Token" as mentioned in the documentation, but I am not sure which excact token this is, scope etc, so all my attempts have failed. Since I was already connected with az I was hoping to use Get-AzAccessToken and supply it directly as mentioned here.

For example, I have tried with

$securityToken = Get-AzAccessToken -TenantId  $ServicePrincipalConnection.TenantId
Connect-SFCluster -ConnectionEndpoint $ServiceFabricConnectionEndpoint `
                  -AzureActiveDirectory `
                  -ServerCertThumbprint $ServicePrincipalConnection.CertificateThumbprint `
                  -ClientTimeout 90 `
                  -SecurityToken $securityToken.Token

. The token I get back looks OK, but it gives

Microsoft.ServiceFabric.Client.Exceptions.InvalidCredentialsException: Authorization error, invalid client credentials.
   at Microsoft.ServiceFabric.Client.Http.ServiceFabricHttpClient.<SendAsyncHandleSecurityExceptions>d__32.MoveNext() in D:\a\1\s\src\Microsoft.ServiceFabric.Client.Http\ServiceFabricHttpClient.cs:line 477
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.ServiceFabric.Client.Http.ServiceFabricHttpClient.<SendAsyncHandleUnsuccessfulResponse>d__31.MoveNext() in D:\a\1\s\src\Microsoft.ServiceFabric.Client.Http\ServiceFabricHttpClient.cs:line 402
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.ServiceFabric.Client.Http.ServiceFabricHttpClient.<SendAsyncGetResponse>d__27`1.MoveNext() in D:\a\1\s\src\Microsoft.ServiceFabric.Client.Http\ServiceFabricHttpClient.cs:line 233
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.ServiceFabric.Powershell.Http.ConnectClusterCmdlet.ProcessRecordInternal() in D:\a\1\s\src\Microsoft.ServiceFabric.Powershell.Http\ConnectClusterCmdlet.cs:line 324
   at Microsoft.ServiceFabric.Powershell.Http.CommonCmdletBase.ProcessRecord() in D:\a\1\s\src\Microsoft.ServiceFabric.Powershell.Http\CommonCmdletBase.cs:line 97
Authorization error, invalid client credentials.

To Reproduce Create an Azure Automation account with a Runbook and a Service Fabric cluster. Try to connect with the Connect-SFCluster command.

Expected behavior Expecting to connect to the cluster.

bjartwolf commented 2 years ago

We figured out how to get the AAD token and get it to connect 🥳 . I do not know if this is the preferred way or something that does not or does belong in this repo, maybe we can get the correct token through Get-AzAccessToken as well, I have not yet investigated.

I think something on this topic would be nice to have in the documentation, I can add a suggestion, I leave it here at least for reference. I have not described the inputs in details, but at least it gives a hint on how to get the correct ServiceFabric Token. I do find the flow in Az somewhat more streamlined, perhaps it is possible to do something similar with a command that wraps the below Invoke-RestMethod to make it more clear how to connect?


$request = @{"grant_type" = "client_credentials"; "resource" = $ClusterServerId; "client_id" = $ClusterClientId; "client_secret" = $ClusterClientSecret }
$response = Invoke-RestMethod -Uri https://login.microsoftonline.com/$ClusterTenantId/oauth2/token -Method Post -Body $request
$securitytoken = $response.access_token ```
bjartwolf commented 2 years ago

Figured out how to get the same token through the Az commands too (when we had the Az context set), one issue is that we have to use the GUID where it wants the URL, which is a bit confusing, but the audience in the token has to be a GUID representing the app registration.

#Get token for the SF-cluster. Resource needs to be the GUID of the app registration, using the App ID URI grants a token that gives 403 on usage
Get-AzAccessToken -ResourceUrl $ServiceFabricClusterEnvAppId 
websolut commented 1 year ago

Hi @bjartwolf. We have tried both approaches and they do not work for us. Does anybody else have any suggestions? Thanks.