Azure / azure-dev

A developer CLI that reduces the time it takes for you to get started on Azure. The Azure Developer CLI (azd) provides a set of developer-friendly commands that map to key stages in your workflow - code, build, deploy, monitor, repeat.
https://aka.ms/azd
MIT License
373 stars 168 forks source link

[Issue] Logon with new version and personal Azure account #1398

Closed lechnerc77 closed 1 year ago

lechnerc77 commented 1 year ago

Output from azd version

azd version 0.5.0-beta.3 (commit 1c23678aade587d5b9685a256a3c1d2d7f4b42e0)

Output from az version

{
  "azure-cli": "2.39.0",
  "azure-cli-core": "2.39.0",
  "azure-cli-telemetry": "1.0.6",
  "extensions": {}
}

Describe the bug

This is a follow up issue to #1366. Although the login is now possible (flow works personal account), the azd does not fetch the subscription:

Screenshot 2023-01-14 171900

I just have the option "other" to enter the data manually.

Switching back to the old behavior via azd config set auth.useAzCliAuth true, I get the list:

Screenshot 2023-01-14 172048

To Reproduce

Expected behavior

azd init after azd login should show the available subscriptions of the account as in previous versions of azd

Environment

Additional context

n.a.

ellismg commented 1 year ago

Something I rediscovered while looking at this is #1148, which causes init to fail if you have a default subscription set that is inaccessible (this can happen if you used you work account and then switch to a personal account as we that that id). You can remove the saved value with azd config unset defaults.subscription

vhvb1989 commented 1 year ago

@ellismg , should we just automatically unset any saved subscription if it becomes unavailable? Or, should we store default subscription per tenant id?

ellismg commented 1 year ago

@ellismg , should we just automatically unset any saved subscription if it becomes unavailable? Or, should we store default subscription per tenant id?

@vhvb1989 I'm not sure - I'm not even sure that per tenant is correct (imagine if you log in as yourself and then as a SP in the same tenant, you may want different defaults?) - really these things should be scoped to an "identity" or "login session" or something? The other option to consider is to not fail the overall operation when we can't fetch what we have as the default, we were using this only so we could highlight a default in our list.

ciwchris commented 1 year ago

@ellismg I'm still unable to use my personal subscription after unsetting it and then logging back in. Is there something else I need to do?

ERROR: loading environment: initializing environment: listing accounts: the subscription id 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' is either invalid or you no longer have access.

ellismg commented 1 year ago

@ciwchris That's surprising! I would have expected azd config unset defaults.subscription to remove this stored value. The value is kept in ~/.azd/config.json. You should be able to delete the "subscription" property of the "defaults" object and it should stop trying to load that subscription.

ellismg commented 1 year ago

Running with --debug, I see that we make a request to https://management.azure.com/subscriptions?api-version=2021-01-01, which succeeds, but appears to return no subscriptions.

2023/01/17 11:09:22 main.go:49: Request: ==> OUTGOING REQUEST (Try=1)
   GET https://management.azure.com/subscriptions?api-version=2021-01-01
   Accept: application/json
   Authorization: REDACTED
   User-Agent: azsdk-go-armsubscriptions/v1.0.0 (go1.19.5; Windows_NT),azdev/0.0.0-dev.0 (Go go1.19.5; windows/amd64)
   2023/01/17 11:09:22 main.go:49: Response: ==> REQUEST/RESPONSE (Try=1/153.1405ms, OpTime=154.9446ms) -- RESPONSE RECEIVED
   GET https://management.azure.com/subscriptions?api-version=2021-01-01
   Accept: application/json
   Authorization: REDACTED
   User-Agent: azsdk-go-armsubscriptions/v1.0.0 (go1.19.5; Windows_NT),azdev/0.0.0-dev.0 (Go go1.19.5; windows/amd64)
   --------------------------------------------------------------------------------
   RESPONSE Status: 200 OK
   Cache-Control: no-cache
   Content-Type: application/json; charset=utf-8
   Date: Tue, 17 Jan 2023 19:09:22 GMT
   Expires: -1
   Pragma: no-cache
   Strict-Transport-Security: REDACTED
   Vary: REDACTED
   X-Content-Type-Options: REDACTED
   X-Ms-Correlation-Request-Id: REDACTED
   X-Ms-Ratelimit-Remaining-Tenant-Reads: REDACTED
   X-Ms-Request-Id: f46967e4-e7a3-438d-b9c7-f4a8497461c6
   X-Ms-Routing-Request-Id: REDACTED

2023/01/17 11:09:22 main.go:49: Retry: response 200
2023/01/17 11:09:22 main.go:49: Retry: exit due to non-retriable status code

The body looks like this:

{"value":[],"count":{"type":"Total","value":0}}

When setting azd config set auth.useAzCliAuth true then the call does work as expected (same URL). So the problem is probably related to the auth token we are using as part of the request?

vhvb1989 commented 1 year ago

@ellismg , I am curious about a flow like:

  1. azd login
  2. azd init (create env and save subscription in azd env)
  3. azd logout
  4. azd login (use another account with no access to the subscription within the azd current env)
  5. azd <some command> ( Should we force azd init here? for a new env? or fail saying no access to current saved subscription? )
ellismg commented 1 year ago

@vhvb1989 - My guess in this case would be that operations that require access to the given subscription would just start to fail saying you couldn't access the subscription.

ellismg commented 1 year ago

Working off the assumption that there is something different about the tokens between when we authenticate natively vs delegate to the az CLI, I set a breakpoint in the BearerTokenPolicy (azcore@v1.2.0\arm\runtime\policy_bearer_token.go) and inspected the token that was fetched for both cases.

There are some differences between the token fetched by azd natively and the one fetched by azure CLI credential.

The one fetched by the az CLI has some additional claims, but also, I noticed that it appears the issuer claim (which is segmented by tenant id) differs between the two tokens. In addition, the tid claim differs between the two tokens.

The tenant ID from the az CLI token matches what az account list shows me. I don't yet understand where the ID that is getting used when we authenticate natively is coming from yet, but I assume the problem is related to this.

ellismg commented 1 year ago

I was able to reproduce this issue outside of the context of azd by using InteractiveBrowserCredential and AzureCliCredential directly from a stand-alone go program that just uses the Azure SDKs directly:

https://gist.github.com/ellismg/63b7d1ce4834dba750a11e993cae601b

I'm going to discuss this with the identity team to better understand what we should be doing here (but I think the problem effects more than just azd)

ciwchris commented 1 year ago

I agree, I've experienced issues with other tools as well. Thank you for digging into this @ellismg !

ellismg commented 1 year ago

For now, you can work around this issue by configuring azd to delegate auth to the az CLI by running:

azd config set auth.useAzCliAuth true

Make sure that once you've done this you run az login to log in with your personal account.

ellismg commented 1 year ago

Thinking about this a bit more, I would not be surprised if we end up needing to do something like this when listing subscriptions:

  1. Use the TenantsClient to list all the tenants a given account has access to.
  2. For each tenant, Use the armsubscriptions Client to list the subscriptions the user has access to in that tenant. To do this we may need to add some capabilities to the azd credential token type to change the tenant id that is used for the current credential.
  3. We probably need to record the tenant id as well the subscription that the user has picked and use that that tenant id when interacting with the subscription.

I suspect doing this will require that we get the fix from MSAL that deals with doing silent authentication from a different tenant using the cached refresh token.

vhvb1989 commented 1 year ago

add some capabilities to the azd credential token type to change the tenant id that is used for the current credential.

I would create one credential per tenant-id instead. Credentials should be read-only after creation, as we must support multi-thread

fsaleemm commented 1 year ago

I am seeing similar issue when deploying using the latest azd 0.5.0-beta.3. This deployment had worked with the previous version.

Steps:

  1. azd login
  2. Set default sub using azd config set defaults.subscription \<subscription id>
  3. azd up -t \<GitHub repository URL> -b \<branch> --debug

I get the "The access token is from the wrong issuer ..." error.

Screenshot below:

image

The tenandId contains the subscription Id that I redacted. I verified using az login.

vhvb1989 commented 1 year ago

fixed by https://github.com/Azure/azure-dev/pull/1478

rajeshkamal5050 commented 1 year ago

@lechnerc77 Fix should be part of the next release.

If you want to try with the daily/bleeding edge builds. Please refer here - https://github.com/Azure/azure-dev/tree/main/cli/installer#download-from-daily-builds Let us know if you run into issues.