Skip to content

Support Managed Identity - #348

Merged
Yan Xu (YanaXu) merged 6 commits into
masterfrom
yanxu/mi
Oct 20, 2023
Merged

Yan Xu (YanaXu) merged 6 commits into
masterfrom
yanxu/mi

Conversation

@YanaXu

@YanaXu Yan Xu (YanaXu) commented Sep 26, 2023 •

Copy link
Copy Markdown
Contributor

Description

This PR is going to support both system- and user- assigned managed identity login for self-hosted runners on Azure VM.

What's new

  • The Action provides a parameter auth-type with value list [SERVICE_PRINCIPAL, IDENTITY] to identify the type of authentication.
    1. If auth-type: SERVICE_PRINCIPAL with clientId, tenantId and clientSecret detected in your input, we will attempt to login by using service principal with the secret.
    #login with secret
    - uses: azure/login@v1
          with:
            auth-type: SERVICE_PRINCIPAL
            creds: ${{ secrets.AZURE_CREDENTIALS }}
    1. If auth-type: SERVICE_PRINCIPAL with clientId and tenantId detected in your input, we will attempt to login by using OIDC.
    #login with OIDC
    - uses: azure/login@v1
        with:
            auth-type: SERVICE_PRINCIPAL
            client-id: ${{ secrets.AZURE_CLIENT_ID }}
            tenant-id: ${{ secrets.AZURE_TENANT_ID }}
            subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
    1. If auth-type: IDENTITY with clientId detected in your input, we will attempt to login by using user-assigned managed identity.
    #login with user-assigned managed identity
    - uses: azure/login@v1
       with:
           auth-type: IDENTITY
           client-id: ${{ secrets.AZURE_CLIENT_ID }}
           subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
    1. If auth-type: IDENTITY without clientId detected in your input, we will attempt to login by using system-assigned managed identity.
    #login with system-assigned managed identity
    - uses: azure/login@v1
     with:
           auth-type: IDENTITY
           subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

The default value of auth-type to be SERVICE_PRINCIPAL to make it backward-compatible.

  • Always specify the subscription-id for safety. Without doing so will make Azure CLI use the current active subscription, which can be risky if your default subscription has changed.

  • The changes for README.md is in Update README.md for Managed identityΒ #344.

@YanaXu

Copy link
Copy Markdown
Contributor Author

Hi Jiashuo Li (@jiasli) , Yeming Liu (@isra-fel) , Xiaogang (@dolauli) , please help us review this PR.
This design spec is Design Spec for Supporting Managed Identity in Azure Login Action.docx.
Please refer to this workflow file for the configuration of this action to support difference login methods.

The readme.md of this action will be updated separately in a later PR.

Comment thread src/PowerShell/AzPSLogin.ts Resolved
Comment thread src/PowerShell/AzPSScriptBuilder.ts Resolved
Comment thread src/Cli/AzureCliLogin.ts Outdated
return;
}
if (!this.loginConfig.subscriptionId) {
core.warning('No subscription-id is given. Skip setting subscription... If there are mutiple subscriptions under the tenant, please input subscription-id to specify which subscription to use.');

@jiasli Jiashuo Li (jiasli) Oct 9, 2023 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No subscription-id is given. Skip setting subscription...

This statement is not accurate. Azure CLI chooses the first active subscription as the default/subscription, so an implicit setting subscription is performed.

Comment thread src/common/LoginConfig.ts
Comment on lines -79 to -80
if (!this.subscriptionId && !this.allowNoSubscriptionsLogin) {
throw new Error("Not all values are present in the credentials. Ensure subscriptionId is supplied.");

@jiasli Jiashuo Li (jiasli) Oct 9, 2023 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The original design makes more sense to me. Without requiring the subscriptionId, the user may unexpectedly perform operations in a wrong subscription. See Azure/azure-cli#14933 (comment).

If this feature is not related to managed identity, I suggest we split this change to another PR.

Comment thread src/Cli/AzureCliLogin.ts
await this.loginWithUserAssignedIdentity(args);
}
else {
await this.loginWithSystemAssignedIdentity(args);

@jiasli Jiashuo Li (jiasli) Oct 9, 2023 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can loginWithSystemAssignedIdentity function and its siblings be written inline as it only contains 1 line and is called only once?

Comment thread src/PowerShell/AzPSLogin.ts Outdated
}
return result[AzPSConstants.Result];
}
} No newline at end of file

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This file lacks the ending new line.

@jiasli

Jiashuo Li (jiasli) commented Oct 9, 2023 •

Copy link
Copy Markdown
Contributor

In the previous code, creds is not compatible with individual parameters. We use creds for login using service principal with secret and individual parameters for OIDC login:

I personally prefer the original design as it is explicit and definitive. The new design allows using OIDC with either individual parameters or creds.

The value of creds is generated by az ad sp create-for-rbac --json-auth and users should never compose creds by themselves, so using creds with auth types other than service principal may not be very reasonable.

@YanaXu

Yan Xu (YanaXu) commented Oct 13, 2023 •

Copy link
Copy Markdown
Contributor Author

Hi Shiying Chen (@MoChilia) , Jiashuo Li (@jiasli), Yeming Liu (@isra-fel), Jin Lei (@msJinLei) ,
This PR is updated based on the review comments. Could you please review it again?

These comments are applied:

  • 'creds' will only support login with SP+secrets.
  • 'creds' will only be valid when there are no individual parameters and 'auth-type' is 'SERVICE_PRINCIPAL'.
  • if 'allow-no-subscriptions' is not set or set to false while 'subscription-id' is not set, throw an error (it's same as before).
  • In Azure PS login, don't use "Set-AzContext", add tenant id and subscription id in "Connect-AzAccount" instead.
  • Import Az.Accounts instead of adding its path to PSModulePath and print used Az.Accounts version.

This comment is skipped in this PR:

  • Add a warning message if 'allow-no-subscriptions' is true.

I also add the unit tests for parameter validation and Azure PS script generation. You can take them for reference.

@MoChilia Shiying Chen (MoChilia) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Common and Azure CLI part LGTM.

Comment thread action.yml Resolved
Comment thread action.yml
required: false
default: 'api://AzureADTokenExchange'
auth-type:
description: 'The type of authentication. Supported values are SERVICE_PRINCIPAL, IDENTITY. Default value is SERVICE_PRINCIPAL'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This introduced a new naming pattern "UPPER_CASE". It is different from all the existing parameters. Any particular reason?

const runner: string = process.env.RUNNER_OS || os.type();
switch (runner.toLowerCase()) {
case "linux":
this.pushPSModulePath(AzPSConstants.DEFAULT_AZ_PATH_ON_LINUX);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this function work on a custom runner?

@YanaXu Yan Xu (YanaXu) Oct 17, 2023 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes. It'll also work on a self-hosted runner.
There are 2 options for this:

  • Only apply this for GitHub-Hosted runners.
    • I see there is an env property RUNNER_ENVIRONMENT which have 2 values "self-hosted" and "github-hosted". But I didn't find official docs for it. That's why I don't suggest to use it in our code since it's not reliable. I didn't find other ways to check if this action is running on a GitHub-Hosted runner.
  • The other way is to keep it as it is now.
    • If so, this line will be applied for "self-hosted" runner too. It could add an invalid path to PSModulePath. However, it does no harm. We have test cases for it. This is aligned with the original code.

I suggest we choose option 2.

Comment thread src/PowerShell/AzPSLogin.ts Resolved
Comment thread src/PowerShell/AzPSScriptBuilder.ts Resolved
Comment thread src/PowerShell/AzPSScriptBuilder.ts Outdated
commands += `Add-AzEnvironment -Name '${loginConfig.environment}' -ARMEndpoint '${loginConfig.resourceManagerEndpointUrl}' | out-null;`;
}
if (loginConfig.authType === LoginConfig.AUTH_TYPE_SERVICE_PRINCIPAL) {
if (loginConfig.servicePrincipalKey) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It seems the nested if-else can be refactored to something like switch (loginConfig.GetLoginFlow()) { ... } but I don't have a strong opinion here.

Comment thread src/common/LoginConfig.ts Resolved
@anton-delphai

Copy link
Copy Markdown

It seems like this change makes allow-no-subscriptions option useless as readParametersFromCreds() already throws an error without considering this option

@pawan-regoti

Pawan Kumar Regoti (pawan-regoti) commented Nov 20, 2023 •

Copy link
Copy Markdown

a funny workaround is giving not null value to subscriptionId in creds and set allow-no-subscriptions to true. It will bypass the subscriptionId and not throws error saying subscriptionId is missing.

      - uses: azure/login@v1
        with:
          allow-no-subscriptions: true
          ...
          creds: '{"subscriptionId":"something"}'

This branch was previously deployed

1 inactive deployment
Automation test β€” bd9b473a Deployed Oct 17, 2023 by YanaXu
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants