Compare commits

..

1 Commits

Author SHA1 Message Date
MoChilia
2431008d0a test update node 16 to 20 2024-02-19 11:31:25 +08:00
15 changed files with 3911 additions and 10107 deletions

View File

@@ -219,7 +219,7 @@ jobs:
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
$checkResult = (Get-AzContext).Environment.Name -eq 'AzureCloud' $checkResult = (Get-AzContext -ListAvailable).Count -eq 2
if(-not $checkResult){ if(-not $checkResult){
throw "Not all checks passed!" throw "Not all checks passed!"
} }

View File

@@ -1,12 +1,13 @@
name: pr-check name: pr-check
on: on:
pull_request: pull_request_target:
branches: branches:
- master - master
- 'releases/*' - 'releases/*'
jobs: jobs:
az-login-test: az-login-test:
environment: Automation test
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- name: Checkout from PR branch - name: Checkout from PR branch
@@ -27,5 +28,44 @@ jobs:
- name: Build GitHub Action - name: Build GitHub Action
run: npm run build run: npm run build
- name: Run mock test - name: 'Az CLI login with subscription'
run: npm run test uses: ./
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- run: |
az account show --output none
az vm list --output none
- name: 'Az CLI login without subscription'
uses: ./
with:
creds: ${{ secrets.AZURE_CREDENTIALS_NO_SUB }}
allow-no-subscriptions: true
- run: |
az account show --output none
# az vm list --output none
- name: 'Azure PowerShell login with subscription'
uses: ./
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
enable-AzPSSession: true
- uses: azure/powershell@v1
with:
inlineScript: "(Get-AzContext).Environment.Name"
azPSVersion: "latest"
# - name: 'Azure PowerShell login without subscription'
# uses: ./
# with:
# creds: ${{secrets.AZURE_CREDENTIALS_NO_SUB}}
# enable-AzPSSession: true
# allow-no-subscriptions: true
# - uses: azure/powershell@v1
# with:
# inlineScript: "Get-AzContext"
# azPSVersion: "latest"

View File

@@ -29,7 +29,7 @@ jobs:
run: | run: |
npm install npm install
npm run build npm run build
- name: 'Run L0 tests' - name: 'Run L0 tests'
run: | run: |
npm run test npm run test

View File

@@ -6,11 +6,6 @@ on:
schedule: schedule:
- cron: '0 19 * * 0' - cron: '0 19 * * 0'
permissions:
actions: read
contents: read
security-events: write
jobs: jobs:
CodeQL-Build: CodeQL-Build:
@@ -23,14 +18,14 @@ jobs:
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v3 uses: github/codeql-action/init@v2
with: with:
languages: javascript languages: javascript
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v3 uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
@@ -44,4 +39,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3 uses: github/codeql-action/analyze@v2

View File

@@ -7,4 +7,3 @@ Resources:
- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
- Employees can reach out at [aka.ms/opensource/moderation-support](https://aka.ms/opensource/moderation-support)

117
README.md
View File

@@ -19,7 +19,7 @@
- [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)
- [Security hardening](#security-hardening) - [Az logout and security hardening](#az-logout-and-security-hardening)
- [Azure CLI dependency](#azure-cli-dependency) - [Azure CLI dependency](#azure-cli-dependency)
- [Reference](#reference) - [Reference](#reference)
- [GitHub Action](#github-action) - [GitHub Action](#github-action)
@@ -183,21 +183,21 @@ name: Run Azure Login with OIDC
on: [push] on: [push]
permissions: permissions:
id-token: write id-token: write
contents: read contents: read
jobs: jobs:
build-and-deploy: build-and-deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Azure login - name: Azure login
uses: azure/login@v2 uses: azure/login@v1
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 }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Azure CLI script - name: Azure CLI script
uses: azure/cli@v2 uses: azure/CLI@v1
with: with:
azcliversion: latest azcliversion: latest
inlineScript: | inlineScript: |
@@ -213,29 +213,29 @@ name: Run Azure Login with OIDC
on: [push] on: [push]
permissions: permissions:
id-token: write id-token: write
contents: read contents: read
jobs: jobs:
build-and-deploy: build-and-deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Azure login - name: Azure login
uses: azure/login@v2 uses: azure/login@v1
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 }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true enable-AzPSSession: true
- name: Azure CLI script - name: Azure CLI script
uses: azure/cli@v2 uses: azure/CLI@v1
with: with:
azcliversion: latest azcliversion: latest
inlineScript: | inlineScript: |
az account show az account show
- name: Azure PowerShell script - name: Azure PowerShell script
uses: azure/powershell@v2 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@@ -281,17 +281,18 @@ jobs:
build-and-deploy: build-and-deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: azure/login@v2 - uses: azure/login@v1
with: with:
creds: ${{ secrets.AZURE_CREDENTIALS }} creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Azure CLI script - name: Azure CLI script
uses: azure/cli@v2 uses: azure/CLI@v1
with: with:
azcliversion: latest azcliversion: latest
inlineScript: | inlineScript: |
az account show az account show
``` ```
- **The workflow sample to run both Azure CLI and Azure PowerShell** - **The workflow sample to run both Azure CLI and Azure PowerShell**
@@ -308,21 +309,21 @@ jobs:
build-and-deploy: build-and-deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: azure/login@v2 - uses: azure/login@v1
with: with:
creds: ${{ secrets.AZURE_CREDENTIALS }} creds: ${{ secrets.AZURE_CREDENTIALS }}
enable-AzPSSession: true enable-AzPSSession: true
- name: Azure CLI script - name: Azure CLI script
uses: azure/cli@v2 uses: azure/CLI@v1
with: with:
azcliversion: latest azcliversion: latest
inlineScript: | inlineScript: |
az account show az account show
- name: Azure PowerShell script - name: Azure PowerShell script
uses: azure/powershell@v2 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@@ -332,7 +333,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@v2 - uses: Azure/login@v1
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 }}"}'
``` ```
@@ -371,29 +372,29 @@ Now you can try the workflow to login with system-assigned managed identity.
name: Run Azure Login with System-assigned Managed Identity name: Run Azure Login with System-assigned Managed Identity
on: [push] on: [push]
jobs: jobs:
build-and-deploy: build-and-deploy:
runs-on: self-hosted runs-on: self-hosted
steps: steps:
- name: Azure login - name: Azure login
uses: azure/login@v2 uses: azure/login@v1
with: with:
auth-type: IDENTITY auth-type: IDENTITY
tenant-id: ${{ secrets.AZURE_TENANT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true enable-AzPSSession: true
# Azure CLI Action only supports linux self-hosted runners for now. # Azure CLI Action only supports linux self-hosted runners for now.
# If you want to execute the Azure CLI script on a windows self-hosted runner, you can execute it directly in `run`. # If you want to execute the Azure CLI script on a windows self-hosted runner, you can execute it directly in `run`.
- name: Azure CLI script - name: Azure CLI script
uses: azure/cli@v2 uses: azure/CLI@v1
with: with:
azcliversion: latest azcliversion: latest
inlineScript: | inlineScript: |
az account show az account show
- name: Azure PowerShell script - name: Azure PowerShell script
uses: azure/powershell@v2 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@@ -437,30 +438,30 @@ Now you can try the workflow to login with user-assigned managed identity.
name: Run Azure Login with User-assigned Managed Identity name: Run Azure Login with User-assigned Managed Identity
on: [push] on: [push]
jobs: jobs:
build-and-deploy: build-and-deploy:
runs-on: self-hosted runs-on: self-hosted
steps: steps:
- name: Azure login - name: Azure login
uses: azure/login@v2 uses: azure/login@v1
with: with:
auth-type: IDENTITY auth-type: IDENTITY
client-id: ${{ secrets.AZURE_CLIENT_ID }} client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true enable-AzPSSession: true
# Azure CLI Action only supports linux self-hosted runners for now. # Azure CLI Action only supports linux self-hosted runners for now.
# If you want to execute the Azure CLI script on a windows self-hosted runner, you can execute it directly in `run`. # If you want to execute the Azure CLI script on a windows self-hosted runner, you can execute it directly in `run`.
- name: Azure CLI script - name: Azure CLI script
uses: azure/cli@v2 uses: azure/CLI@v1
with: with:
azcliversion: latest azcliversion: latest
inlineScript: | inlineScript: |
az account show az account show
- name: Azure PowerShell script - name: Azure PowerShell script
uses: azure/powershell@v2 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
@@ -481,12 +482,13 @@ jobs:
build-and-deploy: build-and-deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: azure/login@v2 - uses: azure/login@v1
with: with:
creds: ${{ secrets.AZURE_CREDENTIALS }} creds: ${{ secrets.AZURE_CREDENTIALS }}
environment: 'AzureUSGovernment' environment: 'AzureUSGovernment'
enable-AzPSSession: true enable-AzPSSession: true
``` ```
### Login to Azure Stack Hub ### Login to Azure Stack Hub
@@ -503,12 +505,13 @@ jobs:
build-and-deploy: build-and-deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: azure/login@v2 - uses: azure/login@v1
with: with:
creds: ${{ secrets.AZURE_CREDENTIALS }} creds: ${{ secrets.AZURE_CREDENTIALS }}
environment: 'AzureStack' environment: 'AzureStack'
enable-AzPSSession: true enable-AzPSSession: true
``` ```
Refer to the [Azure Stack Hub Login Action Tutorial](https://learn.microsoft.com/azure-stack/user/ci-cd-github-action-login-cli) for more detailed instructions. Refer to the [Azure Stack Hub Login Action Tutorial](https://learn.microsoft.com/azure-stack/user/ci-cd-github-action-login-cli) for more detailed instructions.
@@ -531,7 +534,7 @@ jobs:
steps: steps:
- name: Azure Login - name: Azure Login
uses: azure/login@v2 uses: azure/login@v1
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 }}
@@ -539,24 +542,44 @@ jobs:
enable-AzPSSession: true enable-AzPSSession: true
- name: Azure CLI script - name: Azure CLI script
uses: azure/cli@v2 uses: azure/CLI@v1
with: with:
azcliversion: latest azcliversion: latest
inlineScript: | inlineScript: |
az account show az account show
- name: Run Azure PowerShell - name: Run Azure PowerShell
uses: azure/powershell@v2 uses: azure/powershell@v1
with: with:
azPSVersion: "latest" azPSVersion: "latest"
inlineScript: | inlineScript: |
Get-AzContext Get-AzContext
``` ```
## Security hardening ## Az logout and security hardening
This action doesn't implement ```az logout``` by default at the end of execution. However, there is no way to tamper with the credentials or account information because the GitHub-hosted runner is on a VM that will get re-imaged for every customer run, which deletes everything. But if the runner is self-hosted (not provided by GitHub), it is recommended to manually log out at the end of the workflow, as shown below. More details on security of the runners can be found [here](https://docs.github.com/actions/learn-github-actions/security-hardening-for-github-actions#hardening-for-self-hosted-runners).
> [!WARNING] > [!WARNING]
> When using self hosted runners it is possible to have multiple runners on a single VM. Currently if your runners share a single user on the VM each runner will share the same credentials. That means in detail that each runner is able to change the permissions of another run. As a workaround we propose to use one single VM user per runner. If you start the runner as a service, do not forget to add the [optional user argument](https://docs.github.com/actions/hosting-your-own-runners/managing-self-hosted-runners/configuring-the-self-hosted-runner-application-as-a-service#installing-the-service) > When using self hosted runners it is possible to have multiple runners on a single VM. Currently if your runners share a single user on the VM each runner will share the same credentials. That means in detail that each runner is able to change the permissions of another run. As a workaround we propose to use one single VM user per runner. If you start the runner as a service, do not forget to add the [optional user argument](https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/configuring-the-self-hosted-runner-application-as-a-service#installing-the-service)
```yaml
- name: Azure CLI script
uses: azure/CLI@v1
with:
inlineScript: |
az logout
az cache purge
az account clear
- name: Azure PowerShell script
uses: azure/powershell@v1
with:
azPSVersion: "latest"
inlineScript: |
Clear-AzContext -Scope Process
Clear-AzContext -Scope CurrentUser
```
## Azure CLI dependency ## Azure CLI dependency

View File

@@ -96,7 +96,7 @@ describe("LoginConfig Test", () => {
expect(loginConfig.servicePrincipalId).toBe("client-id"); expect(loginConfig.servicePrincipalId).toBe("client-id");
expect(loginConfig.servicePrincipalSecret).toBe("client-secret"); expect(loginConfig.servicePrincipalSecret).toBe("client-secret");
expect(loginConfig.tenantId).toBe("tenant-id"); expect(loginConfig.tenantId).toBe("tenant-id");
expect(loginConfig.subscriptionId).toBe(undefined); expect(loginConfig.subscriptionId).toBe("");
}); });
test('initialize with creds', async () => { test('initialize with creds', async () => {

View File

@@ -40,7 +40,7 @@ describe("Getting AzLogin PS script", () => {
let loginConfig = new LoginConfig(); let loginConfig = new LoginConfig();
loginConfig.initialize(); loginConfig.initialize();
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => { return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
expect(loginScript.includes("$psLoginSecrets = ConvertTo-SecureString 'client-secret' -AsPlainText -Force; $psLoginCredential = New-Object System.Management.Automation.PSCredential('client-id', $psLoginSecrets); Connect-AzAccount -ServicePrincipal -Environment 'azurecloud' -Tenant 'tenant-id' -Subscription 'subscription-id' -Credential $psLoginCredential -InformationAction Ignore | out-null;")).toBeTruthy(); expect(loginScript.includes("$psLoginSecrets = ConvertTo-SecureString 'client-secret' -AsPlainText -Force; $psLoginCredential = New-Object System.Management.Automation.PSCredential('client-id', $psLoginSecrets); Connect-AzAccount -ServicePrincipal -Environment 'azurecloud' -Tenant 'tenant-id' -Subscription 'subscription-id' -Credential $psLoginCredential | out-null;")).toBeTruthy();
expect(loginMethod).toBe('service principal with secret'); expect(loginMethod).toBe('service principal with secret');
}); });
}); });
@@ -61,7 +61,7 @@ describe("Getting AzLogin PS script", () => {
let loginConfig = new LoginConfig(); let loginConfig = new LoginConfig();
loginConfig.initialize(); loginConfig.initialize();
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => { return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
expect(loginScript.includes("$psLoginSecrets = ConvertTo-SecureString 'client-se''cret' -AsPlainText -Force; $psLoginCredential = New-Object System.Management.Automation.PSCredential('client-id', $psLoginSecrets); Connect-AzAccount -ServicePrincipal -Environment 'azurecloud' -Tenant 'tenant-id' -Subscription 'subscription-id' -Credential $psLoginCredential -InformationAction Ignore | out-null;")).toBeTruthy(); expect(loginScript.includes("$psLoginSecrets = ConvertTo-SecureString 'client-se''cret' -AsPlainText -Force; $psLoginCredential = New-Object System.Management.Automation.PSCredential('client-id', $psLoginSecrets); Connect-AzAccount -ServicePrincipal -Environment 'azurecloud' -Tenant 'tenant-id' -Subscription 'subscription-id' -Credential $psLoginCredential | out-null;")).toBeTruthy();
expect(loginMethod).toBe('service principal with secret'); expect(loginMethod).toBe('service principal with secret');
}); });
}); });
@@ -82,7 +82,7 @@ describe("Getting AzLogin PS script", () => {
let loginConfig = new LoginConfig(); let loginConfig = new LoginConfig();
loginConfig.initialize(); loginConfig.initialize();
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => { return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
expect(loginScript.includes("$psLoginSecrets = ConvertTo-SecureString 'client-secret' -AsPlainText -Force; $psLoginCredential = New-Object System.Management.Automation.PSCredential('client-id', $psLoginSecrets); Connect-AzAccount -ServicePrincipal -Environment 'azurecloud' -Tenant 'tenant-id' -Subscription 'subscription-id' -Credential $psLoginCredential -InformationAction Ignore | out-null;")).toBeTruthy(); expect(loginScript.includes("$psLoginSecrets = ConvertTo-SecureString 'client-secret' -AsPlainText -Force; $psLoginCredential = New-Object System.Management.Automation.PSCredential('client-id', $psLoginSecrets); Connect-AzAccount -ServicePrincipal -Environment 'azurecloud' -Tenant 'tenant-id' -Subscription 'subscription-id' -Credential $psLoginCredential | out-null;")).toBeTruthy();
expect(loginMethod).toBe('service principal with secret'); expect(loginMethod).toBe('service principal with secret');
}); });
}); });
@@ -100,7 +100,7 @@ describe("Getting AzLogin PS script", () => {
loginConfig.initialize(); loginConfig.initialize();
jest.spyOn(loginConfig, 'getFederatedToken').mockImplementation(async () => {loginConfig.federatedToken = "fake-token";}); jest.spyOn(loginConfig, 'getFederatedToken').mockImplementation(async () => {loginConfig.federatedToken = "fake-token";});
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => { return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
expect(loginScript.includes("Connect-AzAccount -ServicePrincipal -Environment 'azurecloud' -Tenant 'tenant-id' -Subscription 'subscription-id' -ApplicationId 'client-id' -FederatedToken 'fake-token' -InformationAction Ignore | out-null;")).toBeTruthy(); expect(loginScript.includes("Connect-AzAccount -ServicePrincipal -Environment 'azurecloud' -Tenant 'tenant-id' -Subscription 'subscription-id' -ApplicationId 'client-id' -FederatedToken 'fake-token' | out-null;")).toBeTruthy();
expect(loginMethod).toBe('OIDC'); expect(loginMethod).toBe('OIDC');
}); });
}); });
@@ -115,7 +115,7 @@ describe("Getting AzLogin PS script", () => {
let loginConfig = new LoginConfig(); let loginConfig = new LoginConfig();
loginConfig.initialize(); loginConfig.initialize();
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => { return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
expect(loginScript.includes("Connect-AzAccount -Identity -Environment 'azurecloud' -Subscription 'subscription-id' -InformationAction Ignore | out-null;")).toBeTruthy(); expect(loginScript.includes("Connect-AzAccount -Identity -Environment 'azurecloud' -Subscription 'subscription-id' | out-null;")).toBeTruthy();
expect(loginMethod).toBe('system-assigned managed identity'); expect(loginMethod).toBe('system-assigned managed identity');
}); });
}); });
@@ -130,7 +130,7 @@ describe("Getting AzLogin PS script", () => {
let loginConfig = new LoginConfig(); let loginConfig = new LoginConfig();
loginConfig.initialize(); loginConfig.initialize();
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => { return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
expect(loginScript.includes("Connect-AzAccount -Identity -Environment 'azurecloud' -InformationAction Ignore | out-null;")).toBeTruthy(); expect(loginScript.includes("Connect-AzAccount -Identity -Environment 'azurecloud' | out-null;")).toBeTruthy();
expect(loginMethod).toBe('system-assigned managed identity'); expect(loginMethod).toBe('system-assigned managed identity');
}); });
}); });
@@ -145,7 +145,7 @@ describe("Getting AzLogin PS script", () => {
let loginConfig = new LoginConfig(); let loginConfig = new LoginConfig();
loginConfig.initialize(); loginConfig.initialize();
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => { return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
expect(loginScript.includes("Connect-AzAccount -Identity -Environment 'azurecloud' -AccountId 'client-id' -InformationAction Ignore | out-null;")).toBeTruthy(); expect(loginScript.includes("Connect-AzAccount -Identity -Environment 'azurecloud' -AccountId 'client-id' | out-null;")).toBeTruthy();
expect(loginMethod).toBe('user-assigned managed identity'); expect(loginMethod).toBe('user-assigned managed identity');
}); });
}); });

View File

@@ -1,7 +1,7 @@
# Login to Azure subscription # Login to Azure subscription
name: 'Azure Login' name: 'Azure Login'
description: 'Authenticate to Azure and run your Azure CLI or Azure PowerShell based actions or scripts.' description: 'Authenticate to Azure and run your Azure CLI or Azure PowerShell based actions or scripts.'
inputs: inputs:
creds: creds:
description: 'Paste output of `az ad sp create-for-rbac` as value of secret variable: AZURE_CREDENTIALS' description: 'Paste output of `az ad sp create-for-rbac` as value of secret variable: AZURE_CREDENTIALS'
required: false required: false
@@ -14,7 +14,7 @@ inputs:
subscription-id: subscription-id:
description: 'Azure subscriptionId' description: 'Azure subscriptionId'
required: false required: false
enable-AzPSSession: enable-AzPSSession:
description: 'Set this value to true to enable Azure PowerShell Login in addition to Azure CLI login' description: 'Set this value to true to enable Azure PowerShell Login in addition to Azure CLI login'
required: false required: false
default: false default: false
@@ -27,11 +27,11 @@ inputs:
required: false required: false
default: false default: false
audience: audience:
description: 'Provide audience field for access-token. Default value is api://AzureADTokenExchange' description: 'Provide audience field for access-token. Default value is api://AzureADTokenExchange'
required: false required: false
default: 'api://AzureADTokenExchange' default: 'api://AzureADTokenExchange'
auth-type: auth-type:
description: 'The type of authentication. Supported values are SERVICE_PRINCIPAL, IDENTITY. Default value is SERVICE_PRINCIPAL' description: 'The type of authentication. Supported values are SERVICE_PRINCIPAL, IDENTITY. Default value is SERVICE_PRINCIPAL'
required: false required: false
default: 'SERVICE_PRINCIPAL' default: 'SERVICE_PRINCIPAL'
branding: branding:
@@ -39,6 +39,6 @@ branding:
color: 'blue' color: 'blue'
runs: runs:
using: 'node20' using: 'node20'
pre: 'lib/cleanup/index.js' pre: 'lib/cleanup.js'
main: 'lib/main/index.js' main: 'lib/main.js'
post: 'lib/cleanup/index.js' post: 'lib/cleanup.js'

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

4232
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,17 @@
{ {
"name": "login", "name": "login",
"version": "2.0.0", "version": "1.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.js",
"scripts": { "scripts": {
"build:main": "ncc build src/main.ts -o lib/main", "build": "tsc",
"build:cleanup": "ncc build src/cleanup.ts -o lib/cleanup",
"build": "npm run build:main && npm run build:cleanup",
"test": "jest" "test": "jest"
}, },
"author": "Microsoft", "author": "Sumiran Aggarwal",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@types/jest": "^29.2.4", "@types/jest": "^29.2.4",
"@types/node": "^20.11.1", "@types/node": "^12.7.11",
"@vercel/ncc": "^0.38.1",
"jest": "^29.3.1", "jest": "^29.3.1",
"jest-circus": "^29.3.1", "jest-circus": "^29.3.1",
"ts-jest": "^29.0.3", "ts-jest": "^29.0.3",
@@ -24,6 +21,7 @@
"@actions/core": "1.9.1", "@actions/core": "1.9.1",
"@actions/exec": "^1.0.1", "@actions/exec": "^1.0.1",
"@actions/io": "^1.0.1", "@actions/io": "^1.0.1",
"actions-secret-parser": "^1.0.4",
"package-lock": "^1.0.3" "package-lock": "^1.0.3"
} }
} }

View File

@@ -104,7 +104,7 @@ export default class AzPSScriptBuilder {
if(subscriptionId){ if(subscriptionId){
loginCmdlet += `-Subscription '${subscriptionId}' `; loginCmdlet += `-Subscription '${subscriptionId}' `;
} }
loginCmdlet += `${cmdletSuffix} -InformationAction Ignore | out-null;`; loginCmdlet += `${cmdletSuffix} | out-null;`;
return loginCmdlet; return loginCmdlet;
} }
} }

View File

@@ -1,4 +1,5 @@
import * as core from '@actions/core'; import * as core from '@actions/core';
import { FormatType, SecretParser } from 'actions-secret-parser';
export class LoginConfig { export class LoginConfig {
static readonly AUTH_TYPE_SERVICE_PRINCIPAL = "SERVICE_PRINCIPAL"; static readonly AUTH_TYPE_SERVICE_PRINCIPAL = "SERVICE_PRINCIPAL";
@@ -48,10 +49,10 @@ export class LoginConfig {
private readParametersFromCreds() { private readParametersFromCreds() {
let creds = core.getInput('creds', { required: false }); let creds = core.getInput('creds', { required: false });
if (!creds) { let secrets = creds ? new SecretParser(creds, FormatType.JSON) : null;
if (!secrets) {
return; return;
} }
let secrets = JSON.parse(creds);
if(this.authType != LoginConfig.AUTH_TYPE_SERVICE_PRINCIPAL){ if(this.authType != LoginConfig.AUTH_TYPE_SERVICE_PRINCIPAL){
return; return;
@@ -63,11 +64,11 @@ export class LoginConfig {
} }
core.debug('Reading creds in JSON...'); core.debug('Reading creds in JSON...');
this.servicePrincipalId = this.servicePrincipalId ? this.servicePrincipalId : secrets.clientId; this.servicePrincipalId = this.servicePrincipalId ? this.servicePrincipalId : secrets.getSecret("$.clientId", false);
this.servicePrincipalSecret = secrets.clientSecret; this.servicePrincipalSecret = secrets.getSecret("$.clientSecret", false);
this.tenantId = this.tenantId ? this.tenantId : secrets.tenantId; this.tenantId = this.tenantId ? this.tenantId : secrets.getSecret("$.tenantId", false);
this.subscriptionId = this.subscriptionId ? this.subscriptionId : secrets.subscriptionId; this.subscriptionId = this.subscriptionId ? this.subscriptionId : secrets.getSecret("$.subscriptionId", false);
this.resourceManagerEndpointUrl = secrets.resourceManagerEndpointUrl; this.resourceManagerEndpointUrl = secrets.getSecret("$.resourceManagerEndpointUrl", false);
if (!this.servicePrincipalId || !this.servicePrincipalSecret || !this.tenantId) { if (!this.servicePrincipalId || !this.servicePrincipalSecret || !this.tenantId) {
throw new Error("Not all parameters are provided in 'creds'. Double-check if all keys are defined in 'creds': 'clientId', 'clientSecret', 'tenantId'."); throw new Error("Not all parameters are provided in 'creds'. Double-check if all keys are defined in 'creds': 'clientId', 'clientSecret', 'tenantId'.");
} }
@@ -116,3 +117,4 @@ async function jwtParser(federatedToken: string) {
let decodedPayload = JSON.parse(bufferObj.toString("utf8")); let decodedPayload = JSON.parse(bufferObj.toString("utf8"));
return [decodedPayload['iss'], decodedPayload['sub']]; return [decodedPayload['iss'], decodedPayload['sub']];
} }