Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Swagger tofile doesn't work when the api needs authentication #3124

Open
jerryxu1234 opened this issue Nov 1, 2024 · 5 comments
Open
Labels

Comments

@jerryxu1234
Copy link

Describe the bug

in my azure pipeline, When running swagger tofile myapi.dll swagger.json, authentication exception was thrown out.
From the trace, problem happens as it can't access our azure keyvault.
however, I already passed spn into azure cli task and it and the identity defined in azureSubscription arlready have access to keyvault (as we use same identity for other purpose in the same pipeline and there it has no problem to access the keyvault)

  • task: AzureCLI@2
    inputs:
    targetType: 'inline'
    azureSubscription: 'Core Services PreProd Deployment'
    scriptType: ps
    scriptLocation: 'InlineScript'
    workingDirectory: '$(Build.sourcesDirectory)/Fmy.DataApi/bin/Release/net8.0/'
    inlineScript: |
    $env:AZURE_DEVOPS_EXT_PAT = '$(System.AccessToken)'
    dotnet tool install -g Swashbuckle.AspNetCore.Cli --configfile NuGetPublic.config --version 6.9.0.0
    swagger tofile --help
    swagger tofile --output . my.Api.dll swagger.json
    addSpnToEnvironment: true

Expected behavior

the identity should be passed to keyvault

Actual behavior

exception was thrown out

Steps to reproduce

No response

Exception(s) (if any)

Unhandled exception. Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProviderException: Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net,/ Authority: https://login.microsoftonline.com/xxxx. Exception Message: Tried the following 3 methods to get an access token, but none of them worked.
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net,/ Authority: https://login.microsoftonline.com/xxxx. Exception Message: Tried to get token using Managed Service Identity. Access token could not be acquired. MSI ResponseCode: BadRequest, Response: {"error":"invalid_request","error_description":"Identity not found"}
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net,/ Authority: https://login.microsoftonline.com/82f41f1b-d00f-4f7b-a740-e0fd8515f272. Exception Message: Tried to get token using Visual Studio. Access token could not be acquired. Visual Studio Token provider file not found at "C:\Users\VssAdministrator\AppData\Local.IdentityService\AzureServiceAuth\tokenprovider.json"
Parameters: Connection String: [No connection string specified], Resource: https://vault.azure.net,/ Authority: https://login.microsoftonline.com/82f41f1b-d00f-4f7b-a740-e0fd8515f272. Exception Message: Tried to get token using Azure CLI. Access token could not be acquired. 'az' is not recognized as an internal or external command,
operable program or batch file.

at Microsoft.Azure.Services.AppAuthentication.AzureServiceTokenProvider.GetAccessTokenAsyncImpl(String authority, String resource, String scope)
at Microsoft.Azure.KeyVault.KeyVaultCredential.PostAuthenticate(HttpResponseMessage response)
at Microsoft.Azure.KeyVault.KeyVaultCredential.ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at Microsoft.Azure.KeyVault.KeyVaultClient.GetSecretsWithHttpMessagesAsync(String vaultBaseUrl, Nullable1 maxresults, Dictionary2 customHeaders, CancellationToken cancellationToken)
at Microsoft.Azure.KeyVault.KeyVaultClientExtensions.GetSecretsAsync(IKeyVaultClient operations, String vaultBaseUrl, Nullable1 maxresults, CancellationToken cancellationToken) at Microsoft.Extensions.Configuration.AzureKeyVault.AzureKeyVaultConfigurationProvider.LoadAsync() at Microsoft.Extensions.Configuration.AzureKeyVault.AzureKeyVaultConfigurationProvider.Load() at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList1 providers)
at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()
at Microsoft.Extensions.Hosting.HostBuilder.InitializeAppConfiguration()
at Microsoft.Extensions.Hosting.HostBuilder.Build()
at FE.Thunder.Api.Program.Main(String[] args) in D:\a\1\s\FE.Thunder.DataApi\Program.cs:line 17
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
--- End of stack trace from previous location ---
at Microsoft.Extensions.Hosting.HostFactoryResolver.HostingListener.CreateHost() in //src/Swashbuckle.AspNetCore.Cli/HostFactoryResolver.cs:line 276
at Microsoft.Extensions.Hosting.HostFactoryResolver.<>c__DisplayClass8_0.b__0(String[] args) in /
/src/Swashbuckle.AspNetCore.Cli/HostFactoryResolver.cs:line 75

Swashbuckle.AspNetCore version

latest

.NET Version

net8.0

Anything else?

No response

@jerryxu1234 jerryxu1234 added the bug label Nov 1, 2024
@martincostello
Copy link
Collaborator

The context in which Swashbuckle runs your app to retrieve the OpenAPI document(s) isn't able to see the az CLI on the path:

'az' is not recognized as an internal or external command,
operable program or batch file

The tool should inherit any environment variables from the parent process that invokes it. The tool can't add any special handling for things like Azure, AWS, Google Cloud, etc. services for credentials or any other tools.

You'll need to debug why the environment information isn't getting through to your app, or if it is, why your app code when invoked by Swashbuckle isn't seeing the information.

There's not anything we can do for you here.

@jerryxu1234
Copy link
Author

Hi,
I don't think that is what the problem is.
the azure identity nuget package tries 3 different method to authenticate

  1. Manged identity
  2. Visual studio identity
  3. AZ identity
    When no identity can be found, it will throw exception. The exception we see here shows that no identity can be found after trying 3.

The biggest problem is your code uses reflection to run the web API's program.cs. I don't believe this would pass the identity to the refelected code

@martincostello
Copy link
Collaborator

I don't believe this would pass the identity to the refelected code

It doesn't no, but why would it need to? And if it did, how would it ever do that without special-casing exactly what your specific use case needs?

The stack trace also shows that it isn't failing to find any identity because:

  1. There's no managed identity;
  2. It can't find C:\Users\VssAdministrator\AppData\Local.IdentityService\AzureServiceAuth\tokenprovider.json;
  3. It can't find az to acquire a credential through other means.

You'll need to debug why the environment information isn't getting through to your app, or if it is, why your app code when invoked by Swashbuckle isn't seeing the information.

There's nothing actionable for us to do here - you need to dig into your code and pipeline and work out why the code can't see these things.

Alternatively, change your code to detect that it's being run in the context of the Swashbuckle CLI, and skip trying to interact with Key Vault (or anything else you can't access/use in that context) at all, then your app should start up enough to be able to generate the OpenAPI document.

@jerryxu1234
Copy link
Author

hi, it can't see these things because you used reflection to call the api? that is the reason.

@martincostello
Copy link
Collaborator

That's irrelevant - how would using reflection affect the ability for the code to see C:\Users\VssAdministrator\AppData\Local.IdentityService\AzureServiceAuth\tokenprovider.json or az?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants