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

[identity] log warning for users trying to access cloud shell using user assigned identity #20226

Merged
merged 15 commits into from
Feb 11, 2022

Conversation

KarishmaGhiya
Copy link
Member

@KarishmaGhiya KarishmaGhiya commented Feb 5, 2022

Packages impacted by this PR

@Azure/identity

Issues associated with this PR

Fixes #20142

Describe the problem that is addressed by this PR

Since Azure Managed Identities aren't available in the Azure Cloud Shell, we log a warning for users that try to access cloud shell using user assigned identity.

I am moving the upgrading of version of identity to a separate PR - because of the issues it exposes with the identity package references in the identity plugin packages. - #20340

What are the possible designs available to address the problem? If there are more than one possible design, why was the one in this PR chosen?

Throwing an exception will tie the client side behaviour to Service side impl details, if they change impl on service side in future, our logic of throwing exceptions can break. Instead, we will do some logging here to warn users on known targeted platforms and add some details to docs too.

Checklists

  • Added impacted package name to the issue description
  • Added a changelog (if necessary)

@ghost ghost added the Azure.Identity label Feb 5, 2022
@KarishmaGhiya KarishmaGhiya requested review from sadasant and removed request for sadasant February 5, 2022 02:28
@check-enforcer
Copy link

check-enforcer bot commented Feb 8, 2022

This pull request is protected by Check Enforcer.

What is Check Enforcer?

Check Enforcer helps ensure all pull requests are covered by at least one check-run (typically an Azure Pipeline). When all check-runs associated with this pull request pass then Check Enforcer itself will pass.

Why am I getting this message?

You are getting this message because Check Enforcer did not detect any check-runs being associated with this pull request within five minutes. This may indicate that your pull request is not covered by any pipelines and so Check Enforcer is correctly blocking the pull request being merged.

What should I do now?

If the check-enforcer check-run is not passing and all other check-runs associated with this PR are passing (excluding license-cla) then you could try telling Check Enforcer to evaluate your pull request again. You can do this by adding a comment to this pull request as follows:
/check-enforcer evaluate
Typically evaulation only takes a few seconds. If you know that your pull request is not covered by a pipeline and this is expected you can override Check Enforcer using the following command:
/check-enforcer override
Note that using the override command triggers alerts so that follow-up investigations can occur (PRs still need to be approved as normal).

What if I am onboarding a new service?

Often, new services do not have validation pipelines associated with them, in order to bootstrap pipelines for a new service, you can issue the following command as a pull request comment:
/azp run prepare-pipelines
This will run a pipeline that analyzes the source tree and creates the pipelines necessary to build and validate your pull request. Once the pipeline has been created you can trigger the pipeline using the following comment:
/azp run js - [service] - ci

authDetails.error?.message,
"ManagedIdentityCredential: Authentication failed. Message No responses left."
);
assert.equal(authDetails.requests.length, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is identical to other tests that we have in this file, except for having enabled the logs through setLogLevel. Let’s try something fun: In the cloudShellMsi, export the logger, then here use Sinon to spy the logger and see if the logger.warning function has been invoked. How does that sound?

Comment on lines 65 to 70
if (clientId) {
logger.warning(
`${msiName}: Unavailable. Azure Managed Identities aren't available in the Azure Cloud Shell.`
);
return false;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused by this. I think my confusion comes from three intersecting concerns:

  1. The warning is logged in the isAvailable test. Doesn't that mean this warning will pretty much always trigger if the user specifies a managedIdentityClientId when the ManagedIdentityCredential tries to cache its available MSI providers? I guess what I'm saying is that it feels weird to have a warning-level log that will happen any time you provide a client ID.

  2. The warning says "managed identities aren't available" in the cloud shell, but really the problem is that you can't pick the assigned managed identity, as the issue title says, is that right? I think the warning message could mislead someone into thinking that no form of Managed Identity is supported in the cloud shell.

  3. Previously, we just ignored this option, correct? So, what if the user had passed in the client ID of the identity that their cloud shell instance is actually assigned (is that possible)? We'd log a warning and return false now, even though the option was semantically correct, but ignored and appeared to work previously. Feels a bit like a breaking change.

CC @sadasant WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't that mean this warning will pretty much always trigger if the user specifies a managedIdentityClientId

Yep. However, SDK logs are not automatically logged. They’re only logged when they’re enabled.

warning-level log that will happen any time you provide a client ID

We have a bunch of info level logs which are far more pervasive. When I think of whether this should be an info level log or a warning level log, I think this is most likely a warning level log, since if the user provided a custom client ID and they’re in the cloud shell environment, an info log may not be sufficient indication that there was something wrong with the authentication.

The key point is that we can disable this credential on cloud shell by setting this isAvailable to false. I can think of other less clean approaches, like throwing on getToken or throwing on some other place if this is the only MSI available and the user specified a client ID. The alternatives seem much less clean to me than just making this MSI unavailable if clientId is provided.

The warning says "managed identities aren't available" in the cloud shell

Yeah this doesn’t look good! thank you for pointing it out. I have suggested some alternatives in another thread.

appeared to work previously. Feels a bit like a breaking change

This is fundamentally a bug fix, because in the past providing a client ID in cloud shell would have ignored the client ID and instead picked an entirely different identity (the system identity). We don’t want to default to the system identity if the user provided a client ID.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I disagree that it's a bug fix. It's not making something broken work correctly; it's disabling a buggy thing by making it an error case. I think that's an important difference. In this case, someone could have functional code in which the client_id parameter just doesn't do anything. Or: they could be testing something in Cloud Shell, but the code provides client_id for a prod use case that is deployed to App Service. Both of those cases now fail because no MSI provider is considered to be "available." I don't think we have good options here, but this also doesn't feel good.

On logging, I really feel that an info-level log is more appropriate, and maybe a warning-level log in getToken for this MSI provider if it is actually selected and client_id is set (I understand that in the current implementation in this PR, that couldn't happen, but if it were possible then a warning-level log would make sense). Consider someone who is using App Service MSI and passing client_id. Maybe that person forwards logs to Azure Monitor, so they have AZURE_LOG_LEVEL=warning. They will get warnings even though they never actually used cloud shell MSI if it was even tested for availability. It feels a bit strange for the code to warn the developer about that, but an info-level log ("hey FYI this parameter doesn't work with this provider") would be perfectly normal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not making something broken work correctly

It is making something broken work correctly since if users passed the clientId on the cloud shell environment they would have authenticated with the wrong client.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

someone could have functional code in which the client_id parameter just doesn't do anything

The fact that it seemed to work doesn’t mean that it really worked. It didn’t work since the client ID wasn’t being used.

Or: they could be testing something in Cloud Shell, but the code provides client_id for a prod use case that is deployed to App Service

In this case their test was wrong, but the deployed service would continue to work.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider someone who is using App Service MSI and passing client_id. Maybe that person forwards logs to Azure Monitor, so they have AZURE_LOG_LEVEL=warning. They will get warnings even though they never actually used cloud shell MSI if it was even tested for availability. It feels a bit strange for the code to warn the developer about that, but an info-level log ("hey FYI this parameter doesn't work with this provider") would be perfectly normal.

Ok I like this reasoning! @KarishmaGhiya let’s make this an info log then.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KarishmaGhiya Wait, let’s bring this conversation with other languages. They’re using a warning, but perhaps not in the same place? Let’s make sure we pick info or warning for the right reason.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some good news that will go well with your feedback, @witemple-msft !

After reading a conversation we had with the Identity crew, and this post by @KarishmaGhiya here: #20142 (comment) it is clear to me that this PR should be about adding a warning on getToken and not about preventing getToken 🙂 which means no arguably breaking changes.

const resource = mapScopesToResource(scopes);
if (!resource) {
logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);
return false;
}
if (clientId) {
logger.warning(
`${msiName}: Unavailable. Azure Managed Identities aren't available in the Azure Cloud Shell.`
Copy link
Contributor

@sadasant sadasant Feb 8, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This log should be specifically that specifying a client ID won’t work when authenticating the ManagedIdentityCredential on a Cloud Shell environment. Client IDs are usually provided when users make user-assigned identities, so the phrase user-assigned might be useful. Have we checked at what other languages are doing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, perhaps ManagedIdentityCredential does not support user-assigned identities in the Cloud Shell environment? What do you think?

secureResponses: [createResponse(200, { access_token: "token" })],
});

console.dir(authDetails);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember to remove this.

Copy link
Contributor

@sadasant sadasant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Let’s try to get a review from someone implementing this in another language before we merge this 🙂

Copy link
Member

@christothes christothes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - just suggested a tweak to the message text.

@KarishmaGhiya
Copy link
Member Author

/azp run js-identity-ci

@azure-pipelines
Copy link

No pipelines are associated with this pull request.

@KarishmaGhiya
Copy link
Member Author

/check-enforcer evaluate

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

Successfully merging this pull request may close these issues.

Cloud Shell doesn't support user assigned identities
5 participants