Compare commits

..

3 commits

Author SHA1 Message Date
Shiying Chen
deb78bee2b add await to setazurestack 2024-06-19 16:27:55 +08:00
MoChilia
0df14e308f remove unregister cloud first 2024-06-18 17:05:25 +08:00
Shiying Chen
ca0c27b734 fix 459 2024-06-11 16:42:01 +08:00
20 changed files with 9933 additions and 385 deletions

2
.github/CODEOWNERS vendored
View file

@ -1 +1 @@
@YanaXu @kaverma @kanika1894 @BALAGA-GAYATRI @pulkitaggarwl

View file

@ -30,7 +30,7 @@ jobs:
az --version az --version
- name: Check out repository - name: Check out repository
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: 'Az CLI login with subscription' - name: 'Az CLI login with subscription'
uses: azure/login@v1 uses: azure/login@v1
@ -89,3 +89,4 @@ jobs:
- name: Post to slack - name: Post to slack
shell: bash shell: bash
run: curl -X POST -H 'Content-type:application/json' --data '{"blocks":[{"type":"section","text":{"type":"mrkdwn","text":"${{steps.slack_report.outputs.report}}"}}]}' https://hooks.slack.com/services/${{SECRETS.SLACK_CHANNEL_SECRET}} run: curl -X POST -H 'Content-type:application/json' --data '{"blocks":[{"type":"section","text":{"type":"mrkdwn","text":"${{steps.slack_report.outputs.report}}"}}]}' https://hooks.slack.com/services/${{SECRETS.SLACK_CHANNEL_SECRET}}

View file

@ -37,7 +37,7 @@ jobs:
creds: ${{ secrets.AZURE_CREDENTIALS }} creds: ${{ secrets.AZURE_CREDENTIALS }}
enable-AzPSSession: true enable-AzPSSession: true
- uses: azure/powershell@v3 - uses: azure/powershell@v1
with: with:
inlineScript: "(Get-AzContext).Environment.Name" inlineScript: "(Get-AzContext).Environment.Name"
azPSVersion: "latest" azPSVersion: "latest"
@ -49,7 +49,7 @@ jobs:
enable-AzPSSession: true enable-AzPSSession: true
allow-no-subscriptions: true allow-no-subscriptions: true
- uses: azure/powershell@v3 - uses: azure/powershell@v1
with: with:
inlineScript: "(Get-AzContext).Environment.Name" inlineScript: "(Get-AzContext).Environment.Name"
azPSVersion: "latest" azPSVersion: "latest"
@ -87,7 +87,7 @@ jobs:
subscription-id: ${{ secrets.AZURE_SUBSCRIPTIONID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTIONID }}
enable-AzPSSession: true enable-AzPSSession: true
- uses: azure/powershell@v3 - uses: azure/powershell@v1
with: with:
inlineScript: "(Get-AzContext).Environment.Name" inlineScript: "(Get-AzContext).Environment.Name"
azPSVersion: "latest" azPSVersion: "latest"
@ -100,7 +100,7 @@ jobs:
enable-AzPSSession: true enable-AzPSSession: true
allow-no-subscriptions: true allow-no-subscriptions: true
- uses: azure/powershell@v3 - uses: azure/powershell@v1
with: with:
inlineScript: "(Get-AzContext).Environment.Name" inlineScript: "(Get-AzContext).Environment.Name"
azPSVersion: "latest" azPSVersion: "latest"
@ -126,4 +126,4 @@ jobs:
- name: Post to slack - name: Post to slack
shell: bash shell: bash
run: curl -X POST -H 'Content-type:application/json' --data '{"blocks":[{"type":"section","text":{"type":"mrkdwn","text":"${{steps.slack_report.outputs.report}}"}}]}' https://hooks.slack.com/services/${{SECRETS.SLACK_CHANNEL_SECRET}} run: curl -X POST -H 'Content-type:application/json' --data '{"blocks":[{"type":"section","text":{"type":"mrkdwn","text":"${{steps.slack_report.outputs.report}}"}}]}' https://hooks.slack.com/services/${{SECRETS.SLACK_CHANNEL_SECRET}}

View file

@ -19,12 +19,12 @@ jobs:
steps: steps:
- name: 'Checking out repo code' - name: 'Checking out repo code'
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Set Node.js 24.x for GitHub Action - name: Set Node.js 20.x for GitHub Action
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
node-version: 24.x node-version: 20.x
- name: 'Validate build' - name: 'Validate build'
run: | run: |
@ -58,7 +58,7 @@ jobs:
- name: Run Azure PowerShell - name: Run Azure PowerShell
id: ps_3 id: ps_3
continue-on-error: true continue-on-error: true
uses: azure/powershell@v3 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@ -82,12 +82,12 @@ jobs:
steps: steps:
- name: 'Checking out repo code' - name: 'Checking out repo code'
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Set Node.js 24.x for GitHub Action - name: Set Node.js 20.x for GitHub Action
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
node-version: 24.x node-version: 20.x
- name: 'Validate build' - name: 'Validate build'
run: | run: |
@ -186,7 +186,7 @@ jobs:
- name: Run Azure PowerShell - name: Run Azure PowerShell
id: ps_8 id: ps_8
continue-on-error: true continue-on-error: true
uses: azure/powershell@v3 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@ -216,7 +216,7 @@ jobs:
- name: Run Azure PowerShell - name: Run Azure PowerShell
id: ps_9 id: ps_9
continue-on-error: true continue-on-error: true
uses: azure/powershell@v3 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@ -332,4 +332,37 @@ jobs:
uses: actions/github-script@v7 uses: actions/github-script@v7
with: with:
script: | script: |
core.setFailed('Last action should fail but not. Please check it.') core.setFailed('Last action should fail but not. Please check it.')
VMTest:
strategy:
matrix:
os: [self_linux, self_windows]
runs-on: ${{ matrix.os }}
environment: Automation test
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v4
- name: Set Node.js 20.x for GitHub Action
uses: actions/setup-node@v4
with:
node-version: 20.x
- name: 'Validate build'
run: |
npm install
npm run build
- name: Login with system-assigned managed identity without auth-type
id: login_14
continue-on-error: true
uses: ./
- name: Check Last step failed
if: steps.login_14.outcome == 'success'
uses: actions/github-script@v7
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')

View file

@ -12,18 +12,18 @@ jobs:
BasicTest: BasicTest:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest, self_linux, self_windows]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
environment: Automation test environment: Automation test
steps: steps:
- name: 'Checking out repo code' - name: 'Checking out repo code'
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Set Node.js 24.x for GitHub Action - name: Set Node.js 20.x for GitHub Action
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
node-version: 24.x node-version: 20.x
- name: 'Validate build' - name: 'Validate build'
run: | run: |
@ -47,11 +47,13 @@ jobs:
az vm list --output none az vm list --output none
- name: Run Azure PowerShell - name: Run Azure PowerShell
uses: azure/powershell@v3 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud' $checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
$checkResult = $checkResult -and ((Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG')
$checkResult = $checkResult -and ((Get-AzVM).Count -gt 0)
if(-not $checkResult){ if(-not $checkResult){
throw "Not all checks passed!" throw "Not all checks passed!"
} }
@ -69,7 +71,7 @@ jobs:
az account show --output none az account show --output none
- name: Run Azure PowerShell again - name: Run Azure PowerShell again
uses: azure/powershell@v3 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@ -92,11 +94,13 @@ jobs:
az vm list --output none az vm list --output none
- name: Run Azure PowerShell - name: Run Azure PowerShell
uses: azure/powershell@v3 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud' $checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
$checkResult = $checkResult -and ((Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG')
$checkResult = $checkResult -and ((Get-AzVM).Count -gt 0)
if(-not $checkResult){ if(-not $checkResult){
throw "Not all checks passed!" throw "Not all checks passed!"
} }
@ -110,12 +114,12 @@ jobs:
steps: steps:
- name: 'Checking out repo code' - name: 'Checking out repo code'
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Set Node.js 24.x for GitHub Action - name: Set Node.js 20.x for GitHub Action
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
node-version: 24.x node-version: 20.x
- name: 'Validate build' - name: 'Validate build'
run: | run: |
@ -160,11 +164,13 @@ jobs:
az vm list --output none az vm list --output none
- name: Run Azure PowerShell - name: Run Azure PowerShell
uses: azure/powershell@v3 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud' $checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
$checkResult = $checkResult -and ((Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG')
$checkResult = $checkResult -and ((Get-AzVM).Count -gt 0)
if(-not $checkResult){ if(-not $checkResult){
throw "Not all checks passed!" throw "Not all checks passed!"
} }
@ -183,7 +189,7 @@ jobs:
az account show --output none az account show --output none
- name: Run Azure PowerShell again - name: Run Azure PowerShell again
uses: azure/powershell@v3 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@ -209,7 +215,7 @@ jobs:
} }
- name: Run Azure PowerShell - name: Run Azure PowerShell
uses: azure/powershell@v3 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@ -230,7 +236,7 @@ jobs:
az account show --output none az account show --output none
- name: Run Azure PowerShell - name: Run Azure PowerShell
uses: azure/powershell@v3 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@ -239,78 +245,118 @@ jobs:
throw "Not all checks passed!" throw "Not all checks passed!"
} }
InDockerTest: VMTest:
runs-on: ubuntu-latest strategy:
container: ubuntu:24.04 matrix:
os: [self_linux, self_windows]
runs-on: ${{ matrix.os }}
environment: Automation test environment: Automation test
steps: steps:
- name: 'Checking out repo code' - name: 'Checking out repo code'
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Set Node.js 24.x for GitHub Action - name: Set Node.js 20.x for GitHub Action
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
node-version: 24.x node-version: 20.x
- name: Install Azure CLI
run: |
apt-get update
apt-get install -y curl
curl -sL https://aka.ms/InstallAzureCLIDeb | bash
- name: Check Azure CLI Version
run: |
az --version
- name: Install Powershell
run: |
apt-get update
apt-get install -y wget apt-transport-https software-properties-common
wget -q "https://packages.microsoft.com/config/ubuntu/24.04/packages-microsoft-prod.deb"
dpkg -i packages-microsoft-prod.deb
rm packages-microsoft-prod.deb
apt-get update
apt-get install -y powershell
- name: Check Powershell Version
shell: pwsh
run: |
$PSVersionTable
- name: Install Azure Powershell
shell: pwsh
run: |
Install-Module -Name Az -Repository PSGallery -Force
- name: Check Azure Powershell Version
shell: pwsh
run: |
Get-Module -ListAvailable Az
- name: 'Validate build' - name: 'Validate build'
run: | run: |
npm install npm install
npm run build npm run build
- name: 'Run L0 tests'
run: |
npm run test
- name: Login with individual parameters - name: Login with system-assigned managed identity, no subscription-id
uses: ./ uses: ./
with: with:
client-id: ${{ secrets.SP1_CLIENT_ID }} auth-type: IDENTITY
tenant-id: ${{ secrets.SP1_TENANT_ID }} allow-no-subscriptions: true
subscription-id: ${{ secrets.SP1_SUBSCRIPTION_ID }}
enable-AzPSSession: true enable-AzPSSession: true
- name: Run Azure Cli again - name: Run Azure Cli
run: | run: |
az group list --output none az account show --output none
- name: Run Azure PowerShell again - name: Run Azure PowerShell
uses: azure/powershell@v3 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
$checkResult = Get-AzResourceGroup $checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
if(-not $checkResult){
throw "Not all checks passed!"
}
- name: Login with system-assigned managed identity, with subscription id
uses: ./
with:
auth-type: IDENTITY
subscription-id: ${{ secrets.AZURE_SUBSCRIPTIONID }}
enable-AzPSSession: true
- name: Run Azure Cli
run: |
az account show --output none
az group show --name GitHubAction_CI_RG --output none
az vm list --output none
- name: Run Azure PowerShell
uses: azure/powershell@v1
with:
azPSVersion: "latest"
inlineScript: |
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
$checkResult = $checkResult -and ((Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG')
$checkResult = $checkResult -and ((Get-AzVM).Count -gt 0)
if(-not $checkResult){
throw "Not all checks passed!"
}
- name: Login with tenant-level user-assigned managed identity with allow-no-subscriptions
uses: ./
with:
client-id: ${{ secrets.UMI2_CLIENT_ID }}
allow-no-subscriptions: true
auth-type: IDENTITY
enable-AzPSSession: true
- name: Run Azure Cli
run: |
az account show --output none
- name: Run Azure PowerShell
uses: azure/powershell@v1
with:
azPSVersion: "latest"
inlineScript: |
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
if(-not $checkResult){
throw "Not all checks passed!"
}
- name: Login with user-assigned managed identity, subscription-id
uses: ./
with:
client-id: ${{ secrets.UMI1_CLIENT_ID }}
subscription-id: ${{ secrets.UMI1_SUBSCRIPTION_ID }}
auth-type: IDENTITY
enable-AzPSSession: true
- name: Run Azure Cli
run: |
az account show --output none
az group show --name GitHubAction_CI_RG --output none
az vm list --output none
- name: Run Azure PowerShell
uses: azure/powershell@v1
with:
azPSVersion: "latest"
inlineScript: |
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud'
$checkResult = $checkResult -and ((Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG')
$checkResult = $checkResult -and ((Get-AzVM).Count -gt 0)
if(-not $checkResult){
throw "Not all checks passed!"
}

View file

@ -10,16 +10,16 @@ jobs:
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- name: Checkout from PR branch - name: Checkout from PR branch
uses: actions/checkout@v6 uses: actions/checkout@v4
with: with:
repository: ${{ github.event.pull_request.head.repo.full_name }} repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.ref }} ref: ${{ github.event.pull_request.head.ref }}
# Using 24.x version as an example # Using 20.x version as an example
- name: Set Node.js 24.x for GitHub Action - name: Set Node.js 20.x for GitHub Action
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
node-version: 24.x node-version: 20.x
- name: installing node_modules - name: installing node_modules
run: npm install run: npm install

View file

@ -18,12 +18,12 @@ jobs:
steps: steps:
- name: 'Checking out repo code' - name: 'Checking out repo code'
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Set Node.js 24.x for GitHub Action - name: Set Node.js 20.x for GitHub Action
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
node-version: 24.x node-version: 20.x
- name: 'Validate build' - name: 'Validate build'
run: | run: |

View file

@ -19,7 +19,7 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v6 uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL

View file

@ -7,11 +7,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v4
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
node-version: 24.x node-version: 20.x
- name: Run Markdownlint - name: Run Markdownlint
run: | run: |
npm i -g markdownlint-cli2 npm i -g markdownlint-cli2

147
README.md
View file

@ -19,7 +19,6 @@
- [Login to Azure US Government cloud](#login-to-azure-us-government-cloud) - [Login to Azure US Government cloud](#login-to-azure-us-government-cloud)
- [Login to Azure Stack Hub](#login-to-azure-stack-hub) - [Login to Azure Stack Hub](#login-to-azure-stack-hub)
- [Login without subscription](#login-without-subscription) - [Login without subscription](#login-without-subscription)
- [Enable/Disable the cleanup steps](#enabledisable-the-cleanup-steps)
- [Security hardening](#security-hardening) - [Security hardening](#security-hardening)
- [Azure CLI dependency](#azure-cli-dependency) - [Azure CLI dependency](#azure-cli-dependency)
- [Reference](#reference) - [Reference](#reference)
@ -156,7 +155,7 @@ Refer to [Login With System-assigned Managed Identity](#login-with-system-assign
> - Ensure the CLI version is 2.30 or above to support login with OIDC. > - Ensure the CLI version is 2.30 or above to support login with OIDC.
> - By default, Azure access tokens issued during OIDC based login could have limited validity. Azure access token issued by Service Principal is expected to have an expiration of 1 hour by default. And with Managed Identities, it would be 24 hours. This expiration time is further configurable in Azure. Refer to [access-token lifetime](https://learn.microsoft.com/azure/active-directory/develop/access-tokens#access-token-lifetime) for more details. > - By default, Azure access tokens issued during OIDC based login could have limited validity. Azure access token issued by Service Principal is expected to have an expiration of 1 hour by default. And with Managed Identities, it would be 24 hours. This expiration time is further configurable in Azure. Refer to [access-token lifetime](https://learn.microsoft.com/azure/active-directory/develop/access-tokens#access-token-lifetime) for more details.
Before you use Azure Login Action with OIDC, you need to configure a federated identity credential on a service principal or a managed identity. Before you use Azure Login Action with OIDC, you need to configure a federated identity credential on an service principal or a managed identity.
- Prepare a service principal for Login with OIDC - Prepare a service principal for Login with OIDC
- [Create a service principal and assign a role to it](https://learn.microsoft.com/entra/identity-platform/howto-create-service-principal-portal) - [Create a service principal and assign a role to it](https://learn.microsoft.com/entra/identity-platform/howto-create-service-principal-portal)
@ -193,7 +192,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Azure login - name: Azure login
uses: azure/login@v3 uses: azure/login@v2
with: with:
client-id: ${{ secrets.AZURE_CLIENT_ID }} client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }}
@ -223,7 +222,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Azure login - name: Azure login
uses: azure/login@v3 uses: azure/login@v2
with: with:
client-id: ${{ secrets.AZURE_CLIENT_ID }} client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }}
@ -238,7 +237,7 @@ jobs:
az account show az account show
- name: Azure PowerShell script - name: Azure PowerShell script
uses: azure/powershell@v3 uses: azure/powershell@v2
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@ -285,7 +284,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: azure/login@v3 - uses: azure/login@v2
with: with:
creds: ${{ secrets.AZURE_CREDENTIALS }} creds: ${{ secrets.AZURE_CREDENTIALS }}
@ -312,7 +311,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: azure/login@v3 - uses: azure/login@v2
with: with:
creds: ${{ secrets.AZURE_CREDENTIALS }} creds: ${{ secrets.AZURE_CREDENTIALS }}
enable-AzPSSession: true enable-AzPSSession: true
@ -325,7 +324,7 @@ jobs:
az account show az account show
- name: Azure PowerShell script - name: Azure PowerShell script
uses: azure/powershell@v3 uses: azure/powershell@v2
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@ -335,7 +334,7 @@ jobs:
If you want to pass subscription ID, tenant ID, client ID, and client secret as individual parameters instead of bundling them in a single JSON object to address the [security concerns](https://docs.github.com/actions/security-guides/encrypted-secrets), below snippet can help with the same. If you want to pass subscription ID, tenant ID, client ID, and client secret as individual parameters instead of bundling them in a single JSON object to address the [security concerns](https://docs.github.com/actions/security-guides/encrypted-secrets), below snippet can help with the same.
```yaml ```yaml
- uses: azure/login@v3 - uses: azure/login@v2
with: with:
creds: '{"clientId":"${{ secrets.AZURE_CLIENT_ID }}","clientSecret":"${{ secrets.AZURE_CLIENT_SECRET }}","subscriptionId":"${{ secrets.AZURE_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZURE_TENANT_ID }}"}' creds: '{"clientId":"${{ secrets.AZURE_CLIENT_ID }}","clientSecret":"${{ secrets.AZURE_CLIENT_SECRET }}","subscriptionId":"${{ secrets.AZURE_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZURE_TENANT_ID }}"}'
``` ```
@ -379,7 +378,7 @@ jobs:
runs-on: self-hosted runs-on: self-hosted
steps: steps:
- name: Azure login - name: Azure login
uses: azure/login@v3 uses: azure/login@v2
with: with:
auth-type: IDENTITY auth-type: IDENTITY
tenant-id: ${{ secrets.AZURE_TENANT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }}
@ -396,7 +395,7 @@ jobs:
az account show az account show
- name: Azure PowerShell script - name: Azure PowerShell script
uses: azure/powershell@v3 uses: azure/powershell@v2
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@ -445,7 +444,7 @@ jobs:
runs-on: self-hosted runs-on: self-hosted
steps: steps:
- name: Azure login - name: Azure login
uses: azure/login@v3 uses: azure/login@v2
with: with:
auth-type: IDENTITY auth-type: IDENTITY
client-id: ${{ secrets.AZURE_CLIENT_ID }} client-id: ${{ secrets.AZURE_CLIENT_ID }}
@ -463,7 +462,7 @@ jobs:
az account show az account show
- name: Azure PowerShell script - name: Azure PowerShell script
uses: azure/powershell@v3 uses: azure/powershell@v2
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@ -485,7 +484,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: azure/login@v3 - uses: azure/login@v2
with: with:
creds: ${{ secrets.AZURE_CREDENTIALS }} creds: ${{ secrets.AZURE_CREDENTIALS }}
environment: 'AzureUSGovernment' environment: 'AzureUSGovernment'
@ -507,7 +506,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: azure/login@v3 - uses: azure/login@v2
with: with:
creds: ${{ secrets.AZURE_CREDENTIALS }} creds: ${{ secrets.AZURE_CREDENTIALS }}
environment: 'AzureStack' environment: 'AzureStack'
@ -534,7 +533,7 @@ jobs:
steps: steps:
- name: Azure Login - name: Azure Login
uses: azure/login@v3 uses: azure/login@v2
with: with:
client-id: ${{ secrets.AZURE_CLIENT_ID }} client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }}
@ -549,123 +548,13 @@ jobs:
az account show az account show
- name: Run Azure PowerShell - name: Run Azure PowerShell
uses: azure/powershell@v3 uses: azure/powershell@v2
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
Get-AzContext Get-AzContext
``` ```
### Enable/Disable the cleanup steps
In Azure Login Action, "cleanup" means cleaning up the login context. For security reasons, we recommend users run cleanup every time. But in some scenarios, users need flexible control over cleanup.
Referring to [`runs` for JavaScript actions](https://docs.github.com/actions/sharing-automations/creating-actions/metadata-syntax-for-github-actions#runs-for-javascript-actions), there are 3 steps in an action: `pre:`, `main:` and `post:`. Azure Login Action only implement 2 steps: `main:` and `post:`.
There are 2 "cleanup" steps in Azure Login Action:
- cleanup in `main:`
- It's **disabled** by default.
- Users can enable it by setting an env variable `AZURE_LOGIN_PRE_CLEANUP` to `true`.
- cleanup in `post:`
- It's **enabled** by default.
- Users can disable it by setting an env variable `AZURE_LOGIN_POST_CLEANUP` to `false`.
Azure Login Action use env variables to enable or disable cleanup steps. In GitHub Actions, there are three valid scopes for env variables.
- [env](https://docs.github.com/actions/writing-workflows/workflow-syntax-for-github-actions#env)
- valid for all jobs in this workflow.
- [jobs.<job_id>.env](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idenv)
- valid for all the steps in the job.
- [jobs.<job_id>.steps[*].env](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsenv)
- only valid for the step in a job.
We set `jobs.<job_id>.steps[*].env` for example. Users can set `env` or `jobs.<job_id>.env` for a wider scope.
```yaml
# File: .github/workflows/workflow.yml
on: [push]
name: Cleanup examples for Multiple Azure Login
jobs:
deploy:
runs-on: ubuntu-latest
steps:
# enable cleanup for the 1st Azure Login
- name: Azure Login
uses: azure/login@v3
env:
AZURE_LOGIN_PRE_CLEANUP: true
AZURE_LOGIN_POST_CLEANUP: true
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true
# run some actions
# disable cleanup for all other Azure Login
- name: Azure Login 2
uses: azure/login@v3
env:
AZURE_LOGIN_PRE_CLEANUP: false
AZURE_LOGIN_POST_CLEANUP: false
with:
client-id: ${{ secrets.AZURE_CLIENT_ID_2 }}
tenant-id: ${{ secrets.AZURE_TENANT_ID_2 }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID_2 }}
enable-AzPSSession: true
# run other actions
# disable cleanup for all other Azure Login
- name: Azure Login 3
uses: azure/login@v3
env:
AZURE_LOGIN_PRE_CLEANUP: false
AZURE_LOGIN_POST_CLEANUP: false
with:
client-id: ${{ secrets.AZURE_CLIENT_ID_3 }}
tenant-id: ${{ secrets.AZURE_TENANT_ID_3 }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID_3 }}
enable-AzPSSession: true
# run other actions
```
```yaml
# File: .github/workflows/workflow.yml
on: [push]
name: Disable cleanup for GitHub Hosted Runners
jobs:
deploy:
runs-on: [ubuntu-latest, self-hosted]
steps:
- name: Azure Login
uses: azure/login@v3
env:
AZURE_LOGIN_PRE_CLEANUP: ${{ startsWith(runner.name, 'GitHub Actions') }}
AZURE_LOGIN_POST_CLEANUP: ${{ startsWith(runner.name, 'GitHub Actions') }}
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true
# run some actions
```
## Security hardening ## Security hardening
> [!WARNING] > [!WARNING]
@ -679,7 +568,7 @@ Internally in this action, we use azure CLI and execute `az login` with the cred
### GitHub Action ### GitHub Action
[GitHub Actions](https://docs.github.com/actions) gives you the flexibility to build an automated software development lifecycle workflow. [GitHub Actions](https://help.github.com/articles/about-github-actions) gives you the flexibility to build an automated software development lifecycle workflow.
### GitHub Actions for deploying to Azure ### GitHub Actions for deploying to Azure
@ -705,4 +594,4 @@ provided by the bot. You will only need to do this once across all repos using o
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

View file

@ -245,7 +245,7 @@ describe("LoginConfig Test", () => {
let loginConfig = new LoginConfig(); let loginConfig = new LoginConfig();
await loginConfig.initialize(); await loginConfig.initialize();
testValidateWithErrorMessage(loginConfig, "Ensure 'subscription-id' is supplied or 'allow-no-subscriptions' is 'true'."); testValidateWithErrorMessage(loginConfig, "Ensure subscriptionId is supplied.");
}); });
test('validate without subscriptionId and allowNoSubscriptionsLogin=true', async () => { test('validate without subscriptionId and allowNoSubscriptionsLogin=true', async () => {

View file

@ -38,7 +38,7 @@ branding:
icon: 'login.svg' icon: 'login.svg'
color: 'blue' color: 'blue'
runs: runs:
using: 'node24' using: 'node20'
pre: 'lib/cleanup/index.js'
main: 'lib/main/index.js' main: 'lib/main/index.js'
post-if: (!env.AZURE_LOGIN_POST_CLEANUP || env.AZURE_LOGIN_POST_CLEANUP != 'false')
post: 'lib/cleanup/index.js' post: 'lib/cleanup/index.js'

4632
lib/cleanup/index.js Normal file

File diff suppressed because it is too large Load diff

4911
lib/main/index.js Normal file

File diff suppressed because it is too large Load diff

268
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "login", "name": "login",
"version": "3.0.0", "version": "2.0.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "login", "name": "login",
"version": "3.0.0", "version": "2.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "1.9.1", "@actions/core": "1.9.1",
@ -16,7 +16,7 @@
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.2.4", "@types/jest": "^29.2.4",
"@types/node": "^24.0.0", "@types/node": "^20.11.1",
"@vercel/ncc": "^0.38.1", "@vercel/ncc": "^0.38.1",
"jest": "^29.3.1", "jest": "^29.3.1",
"jest-circus": "^29.3.1", "jest-circus": "^29.3.1",
@ -77,20 +77,73 @@
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
"version": "7.29.0", "version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
"integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-validator-identifier": "^7.28.5", "@babel/highlight": "^7.23.4",
"js-tokens": "^4.0.0", "chalk": "^2.4.2"
"picocolors": "^1.1.1"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/code-frame/node_modules/ansi-styles": {
"version": "3.2.1",
"dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^1.9.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/@babel/code-frame/node_modules/chalk": {
"version": "2.4.2",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/@babel/code-frame/node_modules/color-convert": {
"version": "1.9.3",
"dev": true,
"license": "MIT",
"dependencies": {
"color-name": "1.1.3"
}
},
"node_modules/@babel/code-frame/node_modules/color-name": {
"version": "1.1.3",
"dev": true,
"license": "MIT"
},
"node_modules/@babel/code-frame/node_modules/escape-string-regexp": {
"version": "1.0.5",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/@babel/code-frame/node_modules/supports-color": {
"version": "5.5.0",
"dev": true,
"license": "MIT",
"dependencies": {
"has-flag": "^3.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/@babel/compat-data": { "node_modules/@babel/compat-data": {
"version": "7.20.5", "version": "7.20.5",
"dev": true, "dev": true,
@ -268,9 +321,7 @@
} }
}, },
"node_modules/@babel/helper-string-parser": { "node_modules/@babel/helper-string-parser": {
"version": "7.27.1", "version": "7.23.4",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -278,9 +329,7 @@
} }
}, },
"node_modules/@babel/helper-validator-identifier": { "node_modules/@babel/helper-validator-identifier": {
"version": "7.28.5", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
"integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -296,28 +345,91 @@
} }
}, },
"node_modules/@babel/helpers": { "node_modules/@babel/helpers": {
"version": "7.29.2", "version": "7.20.6",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz",
"integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/template": "^7.28.6", "@babel/template": "^7.18.10",
"@babel/types": "^7.29.0" "@babel/traverse": "^7.20.5",
"@babel/types": "^7.20.5"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/highlight": {
"version": "7.29.2", "version": "7.23.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz",
"integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/types": "^7.29.0" "@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.4.2",
"js-tokens": "^4.0.0"
}, },
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/highlight/node_modules/ansi-styles": {
"version": "3.2.1",
"dev": true,
"license": "MIT",
"dependencies": {
"color-convert": "^1.9.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/@babel/highlight/node_modules/chalk": {
"version": "2.4.2",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/@babel/highlight/node_modules/color-convert": {
"version": "1.9.3",
"dev": true,
"license": "MIT",
"dependencies": {
"color-name": "1.1.3"
}
},
"node_modules/@babel/highlight/node_modules/color-name": {
"version": "1.1.3",
"dev": true,
"license": "MIT"
},
"node_modules/@babel/highlight/node_modules/escape-string-regexp": {
"version": "1.0.5",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/@babel/highlight/node_modules/supports-color": {
"version": "5.5.0",
"dev": true,
"license": "MIT",
"dependencies": {
"has-flag": "^3.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/@babel/parser": {
"version": "7.23.9",
"dev": true,
"license": "MIT",
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
}, },
@ -489,15 +601,13 @@
} }
}, },
"node_modules/@babel/template": { "node_modules/@babel/template": {
"version": "7.28.6", "version": "7.23.9",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
"integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.28.6", "@babel/code-frame": "^7.23.5",
"@babel/parser": "^7.28.6", "@babel/parser": "^7.23.9",
"@babel/types": "^7.28.6" "@babel/types": "^7.23.9"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@ -524,14 +634,13 @@
} }
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.29.0", "version": "7.23.9",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
"integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.27.1", "@babel/helper-string-parser": "^7.23.4",
"@babel/helper-validator-identifier": "^7.28.5" "@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@ -968,13 +1077,11 @@
} }
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "24.12.0", "version": "20.11.19",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz",
"integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"undici-types": "~7.16.0" "undici-types": "~5.26.4"
} }
}, },
"node_modules/@types/prettier": { "node_modules/@types/prettier": {
@ -1163,9 +1270,7 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "1.1.12", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
@ -1173,13 +1278,11 @@
} }
}, },
"node_modules/braces": { "node_modules/braces": {
"version": "3.0.3", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"fill-range": "^7.1.1" "fill-range": "^7.0.1"
}, },
"engines": { "engines": {
"node": ">=8" "node": ">=8"
@ -1363,9 +1466,7 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.6", "version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -1537,9 +1638,7 @@
} }
}, },
"node_modules/fill-range": { "node_modules/fill-range": {
"version": "7.1.1", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -1565,21 +1664,6 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC" "license": "ISC"
}, },
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": { "node_modules/function-bind": {
"version": "1.1.1", "version": "1.1.1",
"dev": true, "dev": true,
@ -1662,6 +1746,14 @@
"node": ">= 0.4.0" "node": ">= 0.4.0"
} }
}, },
"node_modules/has-flag": {
"version": "3.0.0",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/html-escaper": { "node_modules/html-escaper": {
"version": "2.0.2", "version": "2.0.2",
"dev": true, "dev": true,
@ -1747,8 +1839,6 @@
}, },
"node_modules/is-number": { "node_modules/is-number": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -2386,15 +2476,11 @@
}, },
"node_modules/js-tokens": { "node_modules/js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/js-yaml": { "node_modules/js-yaml": {
"version": "3.14.2", "version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -2465,9 +2551,7 @@
} }
}, },
"node_modules/lodash": { "node_modules/lodash": {
"version": "4.17.23", "version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/lodash.memoize": { "node_modules/lodash.memoize": {
@ -2519,13 +2603,11 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/micromatch": { "node_modules/micromatch": {
"version": "4.0.8", "version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"braces": "^3.0.3", "braces": "^3.0.2",
"picomatch": "^2.3.1" "picomatch": "^2.3.1"
}, },
"engines": { "engines": {
@ -2541,9 +2623,7 @@
} }
}, },
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "3.1.5", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
@ -2719,9 +2799,7 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/picocolors": { "node_modules/picocolors": {
"version": "1.1.1", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
@ -3037,10 +3115,16 @@
"dev": true, "dev": true,
"license": "BSD-3-Clause" "license": "BSD-3-Clause"
}, },
"node_modules/to-fast-properties": {
"version": "2.0.0",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/to-regex-range": { "node_modules/to-regex-range": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@ -3145,9 +3229,7 @@
} }
}, },
"node_modules/undici-types": { "node_modules/undici-types": {
"version": "7.16.0", "version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },

View file

@ -1,6 +1,6 @@
{ {
"name": "login", "name": "login",
"version": "3.0.0", "version": "2.0.0",
"description": "Login Azure wraps the az login, allowing for Azure actions to log into Azure", "description": "Login Azure wraps the az login, allowing for Azure actions to log into Azure",
"main": "lib/main/index.js", "main": "lib/main/index.js",
"scripts": { "scripts": {
@ -13,7 +13,7 @@
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@types/jest": "^29.2.4", "@types/jest": "^29.2.4",
"@types/node": "^24.0.0", "@types/node": "^20.11.1",
"@vercel/ncc": "^0.38.1", "@vercel/ncc": "^0.38.1",
"jest": "^29.3.1", "jest": "^29.3.1",
"jest-circus": "^29.3.1", "jest-circus": "^29.3.1",

View file

@ -8,7 +8,6 @@ export class AzureCliLogin {
loginConfig: LoginConfig; loginConfig: LoginConfig;
azPath: string; azPath: string;
loginOptions: ExecOptions; loginOptions: ExecOptions;
azVersion: string;
constructor(loginConfig: LoginConfig) { constructor(loginConfig: LoginConfig) {
this.loginConfig = loginConfig; this.loginConfig = loginConfig;
@ -31,12 +30,7 @@ export class AzureCliLogin {
await this.executeAzCliCommand(["version"], true, execOptions); await this.executeAzCliCommand(["version"], true, execOptions);
core.debug(`Azure CLI version used:\n${output}`); core.debug(`Azure CLI version used:\n${output}`);
try {
this.azVersion = JSON.parse(output)["azure-cli"];
}
catch (error) {
core.warning("Failed to parse Azure CLI version.");
}
await this.registerAzurestackEnvIfNecessary(); await this.registerAzurestackEnvIfNecessary();
await this.executeAzCliCommand(["cloud", "set", "-n", this.loginConfig.environment], false); await this.executeAzCliCommand(["cloud", "set", "-n", this.loginConfig.environment], false);
@ -114,20 +108,7 @@ export class AzureCliLogin {
} }
async loginWithUserAssignedIdentity(args: string[]) { async loginWithUserAssignedIdentity(args: string[]) {
let azcliMinorVersion = 0; args.push("--username", this.loginConfig.servicePrincipalId);
try {
azcliMinorVersion = parseInt(this.azVersion.split('.')[1], 10);
}
catch (error) {
core.warning("Failed to parse the minor version of Azure CLI. Assuming the version is less than 2.69.0");
}
//From Azure-cli v2.69.0, `--username` is replaced with `--client-id`, `--object-id` or `--resource-id`: https://github.com/Azure/azure-cli/pull/30525
if (azcliMinorVersion < 69) {
args.push("--username", this.loginConfig.servicePrincipalId);
}
else {
args.push("--client-id", this.loginConfig.servicePrincipalId);
}
await this.callCliLogin(args, 'user-assigned managed identity'); await this.callCliLogin(args, 'user-assigned managed identity');
} }

View file

@ -79,16 +79,11 @@ export class LoginConfig {
this.mask(this.federatedToken); this.mask(this.federatedToken);
} }
catch (error) { catch (error) {
core.error("Failed to fetch federated token from GitHub. Please make sure to give write permissions to id-token in the workflow."); core.error(`Please make sure to give write permissions to id-token in the workflow.`);
throw error; throw error;
} }
try { let [issuer, subjectClaim] = await jwtParser(this.federatedToken);
let [issuer, subjectClaim, audience, jobWorkflowRef] = await jwtParser(this.federatedToken); core.info("Federated token details:\n issuer - " + issuer + "\n subject claim - " + subjectClaim);
core.info("Federated token details:\n issuer - " + issuer + "\n subject claim - " + subjectClaim + "\n audience - " + audience + "\n job_workflow_ref - " + jobWorkflowRef);
}
catch (error) {
core.warning(`Failed to parse the federated token. Error: ${error}`);
}
} }
validate() { validate() {
@ -104,7 +99,7 @@ export class LoginConfig {
} }
} }
if (!this.subscriptionId && !this.allowNoSubscriptionsLogin) { if (!this.subscriptionId && !this.allowNoSubscriptionsLogin) {
throw new Error("Ensure 'subscription-id' is supplied or 'allow-no-subscriptions' is 'true'."); throw new Error("Ensure subscriptionId is supplied.");
} }
} }
@ -119,20 +114,5 @@ async function jwtParser(federatedToken: string) {
let tokenPayload = federatedToken.split('.')[1]; let tokenPayload = federatedToken.split('.')[1];
let bufferObj = Buffer.from(tokenPayload, "base64"); let bufferObj = Buffer.from(tokenPayload, "base64");
let decodedPayload = JSON.parse(bufferObj.toString("utf8")); let decodedPayload = JSON.parse(bufferObj.toString("utf8"));
const JWT_CLAIM_ISSUER = 'iss'; return [decodedPayload['iss'], decodedPayload['sub']];
const JWT_CLAIM_SUBJECT = 'sub'; }
const JWT_CLAIM_AUDIENCE = 'aud';
const JWT_CLAIM_JOB_WORKFLOW_REF = 'job_workflow_ref';
const requiredClaims = [
JWT_CLAIM_ISSUER,
JWT_CLAIM_SUBJECT,
JWT_CLAIM_AUDIENCE,
JWT_CLAIM_JOB_WORKFLOW_REF
];
for (const claim of requiredClaims) {
if (!decodedPayload[claim]) {
throw new Error(`The claim '${claim}' is missing from the token payload`);
}
}
return [decodedPayload[JWT_CLAIM_ISSUER], decodedPayload[JWT_CLAIM_SUBJECT], decodedPayload[JWT_CLAIM_AUDIENCE], decodedPayload[JWT_CLAIM_JOB_WORKFLOW_REF]];
}

View file

@ -7,8 +7,8 @@ import { AzPSConstants, AzPSUtils } from '../PowerShell/AzPSUtils';
export function setUserAgent(): void { export function setUserAgent(): void {
let usrAgentRepo = crypto.createHash('sha256').update(`${process.env.GITHUB_REPOSITORY}`).digest('hex'); let usrAgentRepo = crypto.createHash('sha256').update(`${process.env.GITHUB_REPOSITORY}`).digest('hex');
let actionName = 'AzureLogin'; let actionName = 'AzureLogin';
process.env.AZURE_HTTP_USER_AGENT = (!!process.env.AZURE_HTTP_USER_AGENT ? `${process.env.AZURE_HTTP_USER_AGENT} ` : '') + `GITHUBACTIONS/${actionName}@v2_${usrAgentRepo}_${process.env.RUNNER_ENVIRONMENT}_${process.env.GITHUB_RUN_ID}`; process.env.AZURE_HTTP_USER_AGENT = (!!process.env.AZURE_HTTP_USER_AGENT ? `${process.env.AZURE_HTTP_USER_AGENT} ` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`;
process.env.AZUREPS_HOST_ENVIRONMENT = (!!process.env.AZUREPS_HOST_ENVIRONMENT ? `${process.env.AZUREPS_HOST_ENVIRONMENT} ` : '') + `GITHUBACTIONS/${actionName}@v2_${usrAgentRepo}_${process.env.RUNNER_ENVIRONMENT}_${process.env.GITHUB_RUN_ID}`; process.env.AZUREPS_HOST_ENVIRONMENT = (!!process.env.AZUREPS_HOST_ENVIRONMENT ? `${process.env.AZUREPS_HOST_ENVIRONMENT} ` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`;
} }
export async function cleanupAzCLIAccounts(): Promise<void> { export async function cleanupAzCLIAccounts(): Promise<void> {

View file

@ -1,5 +1,5 @@
import * as core from '@actions/core'; import * as core from '@actions/core';
import { cleanupAzCLIAccounts, cleanupAzPSAccounts, setUserAgent } from './common/Utils'; import { setUserAgent } from './common/Utils';
import { AzPSLogin } from './PowerShell/AzPSLogin'; import { AzPSLogin } from './PowerShell/AzPSLogin';
import { LoginConfig } from './common/LoginConfig'; import { LoginConfig } from './common/LoginConfig';
import { AzureCliLogin } from './Cli/AzureCliLogin'; import { AzureCliLogin } from './Cli/AzureCliLogin';
@ -7,13 +7,6 @@ import { AzureCliLogin } from './Cli/AzureCliLogin';
async function main() { async function main() {
try { try {
setUserAgent(); setUserAgent();
const preCleanup: string = process.env.AZURE_LOGIN_PRE_CLEANUP;
if ('true' == preCleanup) {
await cleanupAzCLIAccounts();
if (core.getInput('enable-AzPSSession').toLowerCase() === "true") {
await cleanupAzPSAccounts();
}
}
// prepare the login configuration // prepare the login configuration
var loginConfig = new LoginConfig(); var loginConfig = new LoginConfig();