Compare commits

..

1 Commits

Author SHA1 Message Date
YanaXu
4c88f01b0e prepare release 1.5.0 2023-11-20 14:12:35 +08:00
227 changed files with 26266 additions and 26457 deletions

View File

@@ -30,7 +30,7 @@ jobs:
az --version
- name: Check out repository
uses: actions/checkout@v4
uses: actions/checkout@v3
- name: 'Az CLI login with subscription'
uses: azure/login@v1

View File

@@ -9,6 +9,86 @@ permissions:
jobs:
OSTest:
runs-on: macos-latest
environment: Automation test
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v3.5.2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v1
with:
node-version: 16.x
- name: 'Validate build'
run: |
npm install
npm run build
npm run test
- name: Login with creds
continue-on-error: true
uses: ./
with:
creds: ${{secrets.SP1}}
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
id: ps_1
continue-on-error: true
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
(Get-AzContext).Environment.Name -eq 'AzureCloud'
(Get-AzResourceGroup -Name GitHubAction_CI_RG).ResourceGroupName -eq 'GitHubAction_CI_RG'
(Get-AzVM).Count -gt 0
- name: Check Last step failed
if: steps.ps_1.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Login with individual parameters
id: login_2
uses: ./
with:
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
# subscription-id: ${{ secrets.OIDC_SP2_SUBSCRIPTION_ID }}
allow-no-subscriptions: true
enable-AzPSSession: true
- name: Run Azure Cli again
run: |
az account show --output none
- name: Run Azure PowerShell again
id: ps_2
continue-on-error: true
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
(Get-AzContext).Environment.Name -eq 'AzureCloud'
- name: Check Last step failed
if: steps.ps_2.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
PermissionTest:
strategy:
matrix:
@@ -19,10 +99,10 @@ jobs:
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v4
uses: actions/checkout@v3.5.2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v4
uses: actions/setup-node@v1
with:
node-version: 16.x
@@ -50,7 +130,7 @@ jobs:
- name: Check Last step failed
if: steps.cli_3.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
@@ -58,7 +138,7 @@ jobs:
- name: Run Azure PowerShell
id: ps_3
continue-on-error: true
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -68,7 +148,7 @@ jobs:
- name: Check Last step failed
if: steps.ps_3.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
@@ -82,10 +162,10 @@ jobs:
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v4
uses: actions/checkout@v3.5.2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v4
uses: actions/setup-node@v1
with:
node-version: 16.x
@@ -104,7 +184,7 @@ jobs:
- name: Check Last step failed
if: steps.login_4.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
@@ -119,7 +199,7 @@ jobs:
- name: Check Last step failed
if: steps.login_5.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
@@ -133,7 +213,7 @@ jobs:
- name: Check Last step failed
if: steps.login_6.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
@@ -149,7 +229,7 @@ jobs:
- name: Check Last step failed
if: steps.login_7.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
@@ -166,7 +246,7 @@ jobs:
- name: Check Last step failed
if: steps.login_8.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
@@ -186,7 +266,7 @@ jobs:
- name: Run Azure PowerShell
id: ps_8
continue-on-error: true
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -196,7 +276,7 @@ jobs:
- name: Check Last step failed
if: steps.ps_8.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
@@ -216,7 +296,7 @@ jobs:
- name: Run Azure PowerShell
id: ps_9
continue-on-error: true
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -226,7 +306,7 @@ jobs:
- name: Check Last step failed
if: steps.ps_9.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
@@ -245,7 +325,7 @@ jobs:
- name: Check Last step failed
if: steps.login_10.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
@@ -262,12 +342,12 @@ jobs:
- name: Check Last step failed
if: steps.login_11.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
# SP1 is ignored and SP2 will be used for login, but it will fail since SP2 has no access to the given subscription
# Secret of SP1 in creds will be used to sign in SP2
- name: Login with both creds and individual parameters
id: login_12
continue-on-error: true
@@ -282,7 +362,7 @@ jobs:
- name: Check Last step failed
if: steps.login_12.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
@@ -298,38 +378,7 @@ jobs:
- name: Check Last step failed
if: steps.login_13.outcome == 'success'
uses: actions/github-script@v7
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Login with individual parameters, no subscription-id, no allow-no-subscriptions
id: login_14
continue-on-error: true
uses: ./
with:
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
enable-AzPSSession: true
- 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.')
- name: Login with creds, no subscription-id, no allow-no-subscriptions
id: login_15
continue-on-error: true
uses: ./
with:
creds: '{"clientId":"${{ secrets.OIDC_SP2_CLIENT_ID }}","clientSecret":"${{ secrets.SP2_CLIENT_SECRET }}","tenantId":"${{ secrets.OIDC_SP2_TENANT_ID }}"}'
enable-AzPSSession: true
- name: Check Last step failed
if: steps.login_15.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
@@ -343,10 +392,10 @@ jobs:
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v4
uses: actions/checkout@v3.5.2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v4
uses: actions/setup-node@v1
with:
node-version: 16.x
@@ -362,7 +411,7 @@ jobs:
- name: Check Last step failed
if: steps.login_14.outcome == 'success'
uses: actions/github-script@v7
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')

View File

@@ -12,16 +12,16 @@ jobs:
BasicTest:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest, self_linux, self_windows]
os: [ubuntu-latest, windows-latest, self_linux, self_windows]
runs-on: ${{ matrix.os }}
environment: Automation test
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v4
uses: actions/checkout@v3.5.2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v4
uses: actions/setup-node@v1
with:
node-version: 16.x
@@ -47,7 +47,7 @@ jobs:
az vm list --output none
- name: Run Azure PowerShell
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -61,9 +61,10 @@ jobs:
- name: Login with individual parameters
uses: ./
with:
client-id: ${{ secrets.SP1_CLIENT_ID }}
tenant-id: ${{ secrets.SP1_TENANT_ID }}
subscription-id: ${{ secrets.SP1_SUBSCRIPTION_ID }}
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
# subscription-id: ${{ secrets.OIDC_SP2_SUBSCRIPTION_ID }}
allow-no-subscriptions: true
enable-AzPSSession: true
- name: Run Azure Cli again
@@ -71,7 +72,7 @@ jobs:
az account show --output none
- name: Run Azure PowerShell again
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -94,7 +95,7 @@ jobs:
az vm list --output none
- name: Run Azure PowerShell
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -108,16 +109,16 @@ jobs:
ParameterTest:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
environment: Automation test
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v4
uses: actions/checkout@v3.5.2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v4
uses: actions/setup-node@v1
with:
node-version: 16.x
@@ -164,7 +165,7 @@ jobs:
az vm list --output none
- name: Run Azure PowerShell
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -175,29 +176,6 @@ jobs:
throw "Not all checks passed!"
}
- name: Login with individual parameters, allow no subscription
uses: ./
with:
client-id: ${{ secrets.SP1_CLIENT_ID }}
tenant-id: ${{ secrets.SP1_TENANT_ID}}
subscription-id: ${{ secrets.SP1_SUBSCRIPTION_ID }}
allow-no-subscriptions: true
enable-AzPSSession: true
- name: Run Azure Cli again
run: |
az account show --output none
- name: Run Azure PowerShell again
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 individual parameters, no subscription, allow no subscription
uses: ./
with:
@@ -206,37 +184,12 @@ jobs:
allow-no-subscriptions: true
enable-AzPSSession: true
- name: Run Azure Cli
shell: pwsh
run: |
$checkResult = (az account list --output json | ConvertFrom-Json).Count -eq 2
if(-not $checkResult){
throw "Not all checks passed!"
}
- name: Run Azure PowerShell
uses: azure/powershell@v1
with:
azPSVersion: "latest"
inlineScript: |
$checkResult = (Get-AzContext -ListAvailable).Count -eq 2
if(-not $checkResult){
throw "Not all checks passed!"
}
- name: Login with creds, no subscription, allow no subscription
uses: ./
with:
creds: '{"clientId":"${{ secrets.OIDC_SP2_CLIENT_ID }}","clientSecret":"${{ secrets.SP2_CLIENT_SECRET }}","tenantId":"${{ secrets.OIDC_SP2_TENANT_ID }}"}'
allow-no-subscriptions: true
enable-AzPSSession: true
- name: Run Azure Cli
run: |
az account show --output none
- name: Run Azure PowerShell
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -254,10 +207,10 @@ jobs:
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v4
uses: actions/checkout@v3.5.2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v4
uses: actions/setup-node@v1
with:
node-version: 16.x
@@ -278,7 +231,7 @@ jobs:
az account show --output none
- name: Run Azure PowerShell
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -301,7 +254,7 @@ jobs:
az vm list --output none
- name: Run Azure PowerShell
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -325,7 +278,7 @@ jobs:
az account show --output none
- name: Run Azure PowerShell
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -349,7 +302,7 @@ jobs:
az vm list --output none
- name: Run Azure PowerShell
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |

View File

@@ -11,14 +11,14 @@ jobs:
runs-on: windows-latest
steps:
- name: Checkout from PR branch
uses: actions/checkout@v4
uses: actions/checkout@v2
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.ref }}
# Using 16.x version as an example
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v4
uses: actions/setup-node@v1
with:
node-version: 16.x

View File

@@ -1,5 +1,3 @@
name: Build and Test
on:
pull_request:
branches:
@@ -18,10 +16,10 @@ jobs:
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v4
uses: actions/setup-node@v1
with:
node-version: 16.x

View File

@@ -14,13 +14,23 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: javascript
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, 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)

View File

@@ -14,7 +14,7 @@ jobs:
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/stale@v8
- uses: actions/stale@v3
name: Setting issue as idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
@@ -25,7 +25,7 @@ jobs:
operations-per-run: 100
exempt-issue-labels: 'backlog'
- uses: actions/stale@v8
- uses: actions/stale@v3
name: Setting PR as idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -7,9 +7,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@v3
with:
node-version: 16.x
- name: Run Markdownlint

View File

@@ -235,7 +235,7 @@ jobs:
az account show
- name: Azure PowerShell script
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -323,7 +323,7 @@ jobs:
az account show
- name: Azure PowerShell script
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -394,7 +394,7 @@ jobs:
az account show
- name: Azure PowerShell script
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -461,7 +461,7 @@ jobs:
az account show
- name: Azure PowerShell script
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -549,7 +549,7 @@ jobs:
az account show
- name: Run Azure PowerShell
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
@@ -560,9 +560,6 @@ jobs:
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]
> 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
@@ -573,7 +570,7 @@ This action doesn't implement ```az logout``` by default at the end of execution
az account clear
- name: Azure PowerShell script
uses: azure/powershell@v1
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |

View File

@@ -75,28 +75,15 @@ describe("LoginConfig Test", () => {
});
test('initialize with creds, lack of subscriptionId, but allowNoSubscriptionsLogin=true', async () => {
test('initialize with creds, lack of subscriptionId', async () => {
let creds1 = {
'clientId': 'client-id',
'clientSecret': 'client-secret',
'tenantId': 'tenant-id',
// 'subscriptionId': 'subscription-id'
}
setEnv('environment', 'azurecloud');
setEnv('enable-AzPSSession', 'true');
setEnv('allow-no-subscriptions', 'true');
setEnv('auth-type', 'SERVICE_PRINCIPAL');
setEnv('creds', JSON.stringify(creds1));
let loginConfig = new LoginConfig();
await loginConfig.initialize();
expect(loginConfig.environment).toBe("azurecloud");
expect(loginConfig.enableAzPSSession).toBeTruthy();
expect(loginConfig.allowNoSubscriptionsLogin).toBeTruthy();
expect(loginConfig.authType).toBe("SERVICE_PRINCIPAL");
expect(loginConfig.servicePrincipalId).toBe("client-id");
expect(loginConfig.servicePrincipalSecret).toBe("client-secret");
expect(loginConfig.tenantId).toBe("tenant-id");
expect(loginConfig.subscriptionId).toBe("");
await testCreds(creds1);
});
test('initialize with creds', async () => {

View File

@@ -2,7 +2,7 @@ import * as os from 'os';
import { AzPSLogin } from '../../src/PowerShell/AzPSLogin';
import { LoginConfig } from '../../src/common/LoginConfig';
import { AzPSConstants, AzPSUtils } from '../../src/PowerShell/AzPSUtils';
import AzPSConstants from '../../src/PowerShell/AzPSConstants';
let azpsLogin: AzPSLogin;
jest.setTimeout(30000);
@@ -36,7 +36,7 @@ describe('Testing login', () => {
describe('Testing set module path', () => {
test('setDefaultPSModulePath should work', () => {
AzPSUtils.setPSModulePathForGitHubRunner();
azpsLogin.setPSModulePathForGitHubRunner();
const runner: string = process.env.RUNNER_OS || os.type();
if(runner.toLowerCase() === "linux"){
expect(process.env.PSModulePath).toContain(AzPSConstants.DEFAULT_AZ_PATH_ON_LINUX);
@@ -63,7 +63,7 @@ describe('Testing runPSScript', () => {
}
return ConvertTo-Json $output`;
let psVersion: string = await AzPSUtils.runPSScript(script);
let psVersion: string = await AzPSLogin.runPSScript(script);
expect(psVersion === null).toBeFalsy();
});
@@ -82,7 +82,7 @@ describe('Testing runPSScript', () => {
return ConvertTo-Json $output`;
try{
await AzPSUtils.runPSScript(script);
await AzPSLogin.runPSScript(script);
throw new Error("The last step should fail.");
}catch(error){
expect(error.message.includes("Azure PowerShell login failed with error: You cannot call a method on a null-valued expression.")).toBeTruthy();

View File

@@ -40,7 +40,7 @@ describe("Getting AzLogin PS script", () => {
let loginConfig = new LoginConfig();
loginConfig.initialize();
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 | out-null;")).toBeTruthy();
expect(loginScript.includes("Clear-AzContext -Scope Process; Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue; $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');
});
});
@@ -61,7 +61,7 @@ describe("Getting AzLogin PS script", () => {
let loginConfig = new LoginConfig();
loginConfig.initialize();
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 | out-null;")).toBeTruthy();
expect(loginScript.includes("Clear-AzContext -Scope Process; Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue; $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');
});
});
@@ -82,7 +82,7 @@ describe("Getting AzLogin PS script", () => {
let loginConfig = new LoginConfig();
loginConfig.initialize();
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 | out-null;")).toBeTruthy();
expect(loginScript.includes("Clear-AzContext -Scope Process; Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue; $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');
});
});
@@ -100,7 +100,7 @@ describe("Getting AzLogin PS script", () => {
loginConfig.initialize();
jest.spyOn(loginConfig, 'getFederatedToken').mockImplementation(async () => {loginConfig.federatedToken = "fake-token";});
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' | out-null;")).toBeTruthy();
expect(loginScript.includes("Clear-AzContext -Scope Process; Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue; Connect-AzAccount -ServicePrincipal -Environment 'azurecloud' -Tenant 'tenant-id' -Subscription 'subscription-id' -ApplicationId 'client-id' -FederatedToken 'fake-token' | out-null;")).toBeTruthy();
expect(loginMethod).toBe('OIDC');
});
});
@@ -115,7 +115,7 @@ describe("Getting AzLogin PS script", () => {
let loginConfig = new LoginConfig();
loginConfig.initialize();
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
expect(loginScript.includes("Connect-AzAccount -Identity -Environment 'azurecloud' -Subscription 'subscription-id' | out-null;")).toBeTruthy();
expect(loginScript.includes("Clear-AzContext -Scope Process; Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue; Connect-AzAccount -Identity -Environment 'azurecloud' -Subscription 'subscription-id' | out-null;")).toBeTruthy();
expect(loginMethod).toBe('system-assigned managed identity');
});
});
@@ -130,7 +130,7 @@ describe("Getting AzLogin PS script", () => {
let loginConfig = new LoginConfig();
loginConfig.initialize();
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
expect(loginScript.includes("Connect-AzAccount -Identity -Environment 'azurecloud' | out-null;")).toBeTruthy();
expect(loginScript.includes("Clear-AzContext -Scope Process; Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue; Connect-AzAccount -Identity -Environment 'azurecloud' | out-null;")).toBeTruthy();
expect(loginMethod).toBe('system-assigned managed identity');
});
});
@@ -145,7 +145,7 @@ describe("Getting AzLogin PS script", () => {
let loginConfig = new LoginConfig();
loginConfig.initialize();
return AzPSSCriptBuilder.getAzPSLoginScript(loginConfig).then(([loginMethod, loginScript]) => {
expect(loginScript.includes("Connect-AzAccount -Identity -Environment 'azurecloud' -AccountId 'client-id' | out-null;")).toBeTruthy();
expect(loginScript.includes("Clear-AzContext -Scope Process; Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue; Connect-AzAccount -Identity -Environment 'azurecloud' -AccountId 'client-id' | out-null;")).toBeTruthy();
expect(loginMethod).toBe('user-assigned managed identity');
});
});

View File

@@ -39,6 +39,4 @@ branding:
color: 'blue'
runs:
using: 'node16'
pre: 'lib/cleanup.js'
main: 'lib/main.js'
post: 'lib/cleanup.js'

View File

@@ -46,6 +46,9 @@ class AzureCliLogin {
return __awaiter(this, void 0, void 0, function* () {
core.info(`Running Azure CLI Login.`);
this.azPath = yield io.which("az", true);
if (!this.azPath) {
throw new Error("Azure CLI is not found in the runner.");
}
core.debug(`Azure CLI path: ${this.azPath}`);
let output = "";
const execOptions = {
@@ -150,14 +153,15 @@ class AzureCliLogin {
args.push("--allow-no-subscriptions");
}
yield this.executeAzCliCommand(args, true, this.loginOptions);
if (this.loginConfig.subscriptionId) {
yield this.setSubscription();
}
yield this.setSubscription();
core.info(`Azure CLI login succeeds by using ${methodName}.`);
});
}
setSubscription() {
return __awaiter(this, void 0, void 0, function* () {
if (this.loginConfig.allowNoSubscriptionsLogin) {
return;
}
let args = ["account", "set", "--subscription", this.loginConfig.subscriptionId];
yield this.executeAzCliCommand(args, true, this.loginOptions);
core.info("Subscription is set successfully.");
@@ -183,7 +187,7 @@ function defaultExecOptions() {
if (error && error.trim().length !== 0 && !startsWithWarning) {
if (startsWithError) {
//removing the keyword 'ERROR' to avoid duplicates while throwing error
error = error.slice(7);
error = error.slice(5);
}
core.error(error);
}

View File

@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class AzPSConstants {
}
exports.default = AzPSConstants;
AzPSConstants.DEFAULT_AZ_PATH_ON_LINUX = '/usr/share';
AzPSConstants.DEFAULT_AZ_PATH_ON_WINDOWS = 'C:\\Modules';
AzPSConstants.AzAccounts = "Az.Accounts";
AzPSConstants.PowerShell_CmdName = "pwsh";

View File

@@ -37,8 +37,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true });
exports.AzPSLogin = void 0;
const core = __importStar(require("@actions/core"));
const exec = __importStar(require("@actions/exec"));
const io = __importStar(require("@actions/io"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const AzPSScriptBuilder_1 = __importDefault(require("./AzPSScriptBuilder"));
const AzPSUtils_1 = require("./AzPSUtils");
const AzPSConstants_1 = __importDefault(require("./AzPSConstants"));
class AzPSLogin {
constructor(loginConfig) {
this.loginConfig = loginConfig;
@@ -46,14 +50,77 @@ class AzPSLogin {
login() {
return __awaiter(this, void 0, void 0, function* () {
core.info(`Running Azure PowerShell Login.`);
AzPSUtils_1.AzPSUtils.setPSModulePathForGitHubRunner();
yield AzPSUtils_1.AzPSUtils.importLatestAzAccounts();
this.setPSModulePathForGitHubRunner();
yield this.importLatestAzAccounts();
const [loginMethod, loginScript] = yield AzPSScriptBuilder_1.default.getAzPSLoginScript(this.loginConfig);
core.info(`Attempting Azure PowerShell login by using ${loginMethod}...`);
core.debug(`Azure PowerShell Login Script: ${loginScript}`);
yield AzPSUtils_1.AzPSUtils.runPSScript(loginScript);
yield AzPSLogin.runPSScript(loginScript);
console.log(`Running Azure PowerShell Login successfully.`);
});
}
setPSModulePathForGitHubRunner() {
const runner = process.env.RUNNER_OS || os.type();
switch (runner.toLowerCase()) {
case "linux":
this.pushPSModulePath(AzPSConstants_1.default.DEFAULT_AZ_PATH_ON_LINUX);
break;
case "windows":
case "windows_nt":
this.pushPSModulePath(AzPSConstants_1.default.DEFAULT_AZ_PATH_ON_WINDOWS);
break;
case "macos":
case "darwin":
core.warning(`Skip setting the default PowerShell module path for OS ${runner.toLowerCase()}.`);
break;
default:
core.warning(`Skip setting the default PowerShell module path for unknown OS ${runner.toLowerCase()}.`);
break;
}
}
pushPSModulePath(psModulePath) {
process.env.PSModulePath = `${psModulePath}${path.delimiter}${process.env.PSModulePath}`;
core.debug(`Set PSModulePath as ${process.env.PSModulePath}`);
}
importLatestAzAccounts() {
return __awaiter(this, void 0, void 0, function* () {
let importLatestAccountsScript = AzPSScriptBuilder_1.default.getImportLatestModuleScript(AzPSConstants_1.default.AzAccounts);
core.debug(`The script to import the latest Az.Accounts: ${importLatestAccountsScript}`);
let azAccountsPath = yield AzPSLogin.runPSScript(importLatestAccountsScript);
core.debug(`The latest Az.Accounts used: ${azAccountsPath}`);
});
}
static runPSScript(psScript) {
return __awaiter(this, void 0, void 0, function* () {
let outputString = "";
let commandStdErr = false;
const options = {
silent: true,
listeners: {
stdout: (data) => {
outputString += data.toString();
},
stderr: (data) => {
let error = data.toString();
if (error && error.trim().length !== 0) {
commandStdErr = true;
core.error(error);
}
}
}
};
let psPath = yield io.which(AzPSConstants_1.default.PowerShell_CmdName, true);
yield exec.exec(`"${psPath}"`, ["-Command", psScript], options);
if (commandStdErr) {
throw new Error('Azure PowerShell login failed with errors.');
}
const result = JSON.parse(outputString.trim());
console.log(result);
if (!(result.Success)) {
throw new Error(`Azure PowerShell login failed with error: ${result.Error}`);
}
return result.Result;
});
}
}
exports.AzPSLogin = AzPSLogin;

View File

@@ -31,7 +31,8 @@ class AzPSScriptBuilder {
static getAzPSLoginScript(loginConfig) {
return __awaiter(this, void 0, void 0, function* () {
let loginMethodName = "";
let commands = "";
let commands = 'Clear-AzContext -Scope Process; ';
commands += 'Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue; ';
if (loginConfig.environment.toLowerCase() == "azurestack") {
commands += `Add-AzEnvironment -Name '${loginConfig.environment}' -ARMEndpoint '${loginConfig.resourceManagerEndpointUrl}' | out-null;`;
}

View File

@@ -1,119 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AzPSUtils = exports.AzPSConstants = void 0;
const core = __importStar(require("@actions/core"));
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const exec = __importStar(require("@actions/exec"));
const io = __importStar(require("@actions/io"));
const AzPSScriptBuilder_1 = __importDefault(require("./AzPSScriptBuilder"));
class AzPSConstants {
}
exports.AzPSConstants = AzPSConstants;
AzPSConstants.DEFAULT_AZ_PATH_ON_LINUX = '/usr/share';
AzPSConstants.DEFAULT_AZ_PATH_ON_WINDOWS = 'C:\\Modules';
AzPSConstants.AzAccounts = "Az.Accounts";
AzPSConstants.PowerShell_CmdName = "pwsh";
class AzPSUtils {
static setPSModulePathForGitHubRunner() {
return __awaiter(this, void 0, void 0, function* () {
const runner = process.env.RUNNER_OS || os.type();
switch (runner.toLowerCase()) {
case "linux":
AzPSUtils.pushPSModulePath(AzPSConstants.DEFAULT_AZ_PATH_ON_LINUX);
break;
case "windows":
case "windows_nt":
AzPSUtils.pushPSModulePath(AzPSConstants.DEFAULT_AZ_PATH_ON_WINDOWS);
break;
case "macos":
case "darwin":
core.warning(`Skip setting the default PowerShell module path for OS ${runner.toLowerCase()}.`);
break;
default:
core.warning(`Skip setting the default PowerShell module path for unknown OS ${runner.toLowerCase()}.`);
break;
}
});
}
static pushPSModulePath(psModulePath) {
process.env.PSModulePath = `${psModulePath}${path.delimiter}${process.env.PSModulePath}`;
core.debug(`Set PSModulePath as ${process.env.PSModulePath}`);
}
static importLatestAzAccounts() {
return __awaiter(this, void 0, void 0, function* () {
let importLatestAccountsScript = AzPSScriptBuilder_1.default.getImportLatestModuleScript(AzPSConstants.AzAccounts);
core.debug(`The script to import the latest Az.Accounts: ${importLatestAccountsScript}`);
let azAccountsPath = yield AzPSUtils.runPSScript(importLatestAccountsScript);
core.debug(`The latest Az.Accounts used: ${azAccountsPath}`);
});
}
static runPSScript(psScript) {
return __awaiter(this, void 0, void 0, function* () {
let outputString = "";
let commandStdErr = false;
const options = {
silent: true,
listeners: {
stdout: (data) => {
outputString += data.toString();
},
stderr: (data) => {
let error = data.toString();
if (error && error.trim().length !== 0) {
commandStdErr = true;
core.error(error);
}
}
}
};
let psPath = yield io.which(AzPSConstants.PowerShell_CmdName, true);
yield exec.exec(`"${psPath}"`, ["-Command", psScript], options);
if (commandStdErr) {
throw new Error('Azure PowerShell login failed with errors.');
}
const result = JSON.parse(outputString.trim());
console.log(result);
if (!(result.Success)) {
throw new Error(`Azure PowerShell login failed with error: ${result.Error}`);
}
return result.Result;
});
}
}
exports.AzPSUtils = AzPSUtils;

View File

@@ -1,52 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(require("@actions/core"));
const Utils_1 = require("./common/Utils");
function cleanup() {
return __awaiter(this, void 0, void 0, function* () {
try {
(0, Utils_1.setUserAgent)();
yield (0, Utils_1.cleanupAzCLIAccounts)();
if (core.getInput('enable-AzPSSession').toLowerCase() === "true") {
yield (0, Utils_1.cleanupAzPSAccounts)();
}
}
catch (error) {
core.warning(`Login cleanup failed with ${error}. Cleanup will be skipped.`);
core.debug(error.stack);
}
});
}
cleanup();

View File

@@ -72,8 +72,8 @@ class LoginConfig {
this.tenantId = this.tenantId ? this.tenantId : secrets.getSecret("$.tenantId", false);
this.subscriptionId = this.subscriptionId ? this.subscriptionId : secrets.getSecret("$.subscriptionId", false);
this.resourceManagerEndpointUrl = secrets.getSecret("$.resourceManagerEndpointUrl", false);
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'.");
if (!this.servicePrincipalId || !this.servicePrincipalSecret || !this.tenantId || !this.subscriptionId) {
throw new Error("Not all parameters are provided in 'creds'. Double-check if all keys are defined in 'creds': 'clientId', 'clientSecret', 'subscriptionId', 'tenantId'.");
}
}
getFederatedToken() {

View File

@@ -1,69 +0,0 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.cleanupAzPSAccounts = exports.cleanupAzCLIAccounts = exports.setUserAgent = void 0;
const core = __importStar(require("@actions/core"));
const exec = __importStar(require("@actions/exec"));
const io = __importStar(require("@actions/io"));
const crypto = __importStar(require("crypto"));
const AzPSUtils_1 = require("../PowerShell/AzPSUtils");
function setUserAgent() {
let usrAgentRepo = crypto.createHash('sha256').update(`${process.env.GITHUB_REPOSITORY}`).digest('hex');
let actionName = 'AzureLogin';
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}@v1_${usrAgentRepo}`;
}
exports.setUserAgent = setUserAgent;
function cleanupAzCLIAccounts() {
return __awaiter(this, void 0, void 0, function* () {
let azPath = yield io.which("az", true);
core.debug(`Azure CLI path: ${azPath}`);
core.info("Clearing azure cli accounts from the local cache.");
yield exec.exec(`"${azPath}"`, ["account", "clear"]);
});
}
exports.cleanupAzCLIAccounts = cleanupAzCLIAccounts;
function cleanupAzPSAccounts() {
return __awaiter(this, void 0, void 0, function* () {
let psPath = yield io.which(AzPSUtils_1.AzPSConstants.PowerShell_CmdName, true);
core.debug(`PowerShell path: ${psPath}`);
core.debug("Importing Azure PowerShell module.");
AzPSUtils_1.AzPSUtils.setPSModulePathForGitHubRunner();
yield AzPSUtils_1.AzPSUtils.importLatestAzAccounts();
core.info("Clearing azure powershell accounts from the local cache.");
yield exec.exec(`"${psPath}"`, ["-Command", "Clear-AzContext", "-Scope", "Process"]);
yield exec.exec(`"${psPath}"`, ["-Command", "Clear-AzContext", "-Scope", "CurrentUser", "-Force", "-ErrorAction", "SilentlyContinue"]);
});
}
exports.cleanupAzPSAccounts = cleanupAzPSAccounts;

View File

@@ -33,14 +33,20 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(require("@actions/core"));
const Utils_1 = require("./common/Utils");
const AzPSLogin_1 = require("./PowerShell/AzPSLogin");
const LoginConfig_1 = require("./common/LoginConfig");
const AzureCliLogin_1 = require("./Cli/AzureCliLogin");
var prefix = !!process.env.AZURE_HTTP_USER_AGENT ? `${process.env.AZURE_HTTP_USER_AGENT}` : "";
var azPSHostEnv = !!process.env.AZUREPS_HOST_ENVIRONMENT ? `${process.env.AZUREPS_HOST_ENVIRONMENT}` : "";
function main() {
return __awaiter(this, void 0, void 0, function* () {
try {
(0, Utils_1.setUserAgent)();
let usrAgentRepo = `${process.env.GITHUB_REPOSITORY}`;
let actionName = 'AzureLogin';
let userAgentString = (!!prefix ? `${prefix}+` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`;
let azurePSHostEnv = (!!azPSHostEnv ? `${azPSHostEnv}+` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`;
core.exportVariable('AZURE_HTTP_USER_AGENT', userAgentString);
core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azurePSHostEnv);
// prepare the login configuration
var loginConfig = new LoginConfig_1.LoginConfig();
yield loginConfig.initialize();
@@ -55,9 +61,14 @@ function main() {
}
}
catch (error) {
core.setFailed(`Login failed with ${error}. Double check if the 'auth-type' is correct. Refer to https://github.com/Azure/login#readme for more information.`);
core.setFailed(`Login failed with ${error}. Make sure 'az' is installed on the runner. If 'enable-AzPSSession' is true, make sure 'pwsh' is installed on the runner together with Azure PowerShell module. Double check if the 'auth-type' is correct. Refer to https://github.com/Azure/login#readme for more information.`);
core.debug(error.stack);
}
finally {
// Reset AZURE_HTTP_USER_AGENT
core.exportVariable('AZURE_HTTP_USER_AGENT', prefix);
core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azPSHostEnv);
}
});
}
main();

8
node_modules/.package-lock.json generated vendored
View File

@@ -1117,11 +1117,11 @@
"dev": true
},
"node_modules/actions-secret-parser": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/actions-secret-parser/-/actions-secret-parser-1.0.4.tgz",
"integrity": "sha512-gDAB8GK2Vj9CN5r97DZlmpxqrMcpAGKGWiIY3hpFhJMieLpl3K3ocVR49/Q4ANaA5a/2wNRE3Qng+x0K8mkmkQ==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/actions-secret-parser/-/actions-secret-parser-1.0.3.tgz",
"integrity": "sha512-+iGlMSsE/cbxDaEZlqR0NUjn35DckMYsdYFwVeZ7JRbtyO/AiBKnaScKkzkHSoiZ4nEPTdIHtMpRGVgoeVYX+A==",
"dependencies": {
"@actions/core": "^1.1.10",
"@actions/core": "^1.1.3",
"jsonpath": "^1.0.2",
"xmldom": "^0.1.27",
"xpath": "0.0.27"

View File

@@ -1,6 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SecretParser = exports.FormatType = void 0;
var core = require('@actions/core');
var jp = require('jsonpath');
var xpath = require('xpath');

View File

@@ -1,8 +1,8 @@
{
"name": "actions-secret-parser",
"version": "1.0.4",
"version": "1.0.3",
"description": "Parse and set repository secrets",
"main": "index.js",
"main": "lib/index.js",
"scripts": {
"build": "tsc",
"copypackage": "copy package.json lib",
@@ -23,11 +23,10 @@
"homepage": "https://github.com/Microsoft/pipelines-appservice-lib/tree/master/packages/utility",
"license": "MIT",
"devDependencies": {
"@types/node": "^18.11.17",
"typescript": "^3.6.3"
},
"dependencies": {
"@actions/core": "^1.1.10",
"@actions/core": "^1.1.3",
"jsonpath": "^1.0.2",
"xmldom": "^0.1.27",
"xpath": "0.0.27"

18
package-lock.json generated
View File

@@ -12,7 +12,7 @@
"@actions/core": "1.9.1",
"@actions/exec": "^1.0.1",
"@actions/io": "^1.0.1",
"actions-secret-parser": "^1.0.4",
"actions-secret-parser": "^1.0.2",
"package-lock": "^1.0.3"
},
"devDependencies": {
@@ -1137,11 +1137,11 @@
"dev": true
},
"node_modules/actions-secret-parser": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/actions-secret-parser/-/actions-secret-parser-1.0.4.tgz",
"integrity": "sha512-gDAB8GK2Vj9CN5r97DZlmpxqrMcpAGKGWiIY3hpFhJMieLpl3K3ocVR49/Q4ANaA5a/2wNRE3Qng+x0K8mkmkQ==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/actions-secret-parser/-/actions-secret-parser-1.0.3.tgz",
"integrity": "sha512-+iGlMSsE/cbxDaEZlqR0NUjn35DckMYsdYFwVeZ7JRbtyO/AiBKnaScKkzkHSoiZ4nEPTdIHtMpRGVgoeVYX+A==",
"dependencies": {
"@actions/core": "^1.1.10",
"@actions/core": "^1.1.3",
"jsonpath": "^1.0.2",
"xmldom": "^0.1.27",
"xpath": "0.0.27"
@@ -4741,11 +4741,11 @@
"dev": true
},
"actions-secret-parser": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/actions-secret-parser/-/actions-secret-parser-1.0.4.tgz",
"integrity": "sha512-gDAB8GK2Vj9CN5r97DZlmpxqrMcpAGKGWiIY3hpFhJMieLpl3K3ocVR49/Q4ANaA5a/2wNRE3Qng+x0K8mkmkQ==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/actions-secret-parser/-/actions-secret-parser-1.0.3.tgz",
"integrity": "sha512-+iGlMSsE/cbxDaEZlqR0NUjn35DckMYsdYFwVeZ7JRbtyO/AiBKnaScKkzkHSoiZ4nEPTdIHtMpRGVgoeVYX+A==",
"requires": {
"@actions/core": "^1.1.10",
"@actions/core": "^1.1.3",
"jsonpath": "^1.0.2",
"xmldom": "^0.1.27",
"xpath": "0.0.27"

View File

@@ -21,7 +21,7 @@
"@actions/core": "1.9.1",
"@actions/exec": "^1.0.1",
"@actions/io": "^1.0.1",
"actions-secret-parser": "^1.0.4",
"actions-secret-parser": "^1.0.2",
"package-lock": "^1.0.3"
}
}

View File

@@ -17,6 +17,9 @@ export class AzureCliLogin {
async login() {
core.info(`Running Azure CLI Login.`);
this.azPath = await io.which("az", true);
if (!this.azPath) {
throw new Error("Azure CLI is not found in the runner.");
}
core.debug(`Azure CLI path: ${this.azPath}`);
let output: string = "";
@@ -123,13 +126,14 @@ export class AzureCliLogin {
args.push("--allow-no-subscriptions");
}
await this.executeAzCliCommand(args, true, this.loginOptions);
if (this.loginConfig.subscriptionId) {
await this.setSubscription();
}
await this.setSubscription();
core.info(`Azure CLI login succeeds by using ${methodName}.`);
}
async setSubscription() {
if (this.loginConfig.allowNoSubscriptionsLogin) {
return;
}
let args = ["account", "set", "--subscription", this.loginConfig.subscriptionId];
await this.executeAzCliCommand(args, true, this.loginOptions);
core.info("Subscription is set successfully.");
@@ -156,7 +160,7 @@ function defaultExecOptions(): exec.ExecOptions {
if (error && error.trim().length !== 0 && !startsWithWarning) {
if (startsWithError) {
//removing the keyword 'ERROR' to avoid duplicates while throwing error
error = error.slice(7);
error = error.slice(5);
}
core.error(error);
}

View File

@@ -0,0 +1,7 @@
export default class AzPSConstants {
static readonly DEFAULT_AZ_PATH_ON_LINUX: string = '/usr/share';
static readonly DEFAULT_AZ_PATH_ON_WINDOWS: string = 'C:\\Modules';
static readonly AzAccounts: string = "Az.Accounts";
static readonly PowerShell_CmdName = "pwsh";
}

View File

@@ -1,9 +1,19 @@
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as io from '@actions/io';
import * as os from 'os';
import * as path from 'path';
import AzPSScriptBuilder from './AzPSScriptBuilder';
import { AzPSUtils } from './AzPSUtils';
import AzPSConstants from './AzPSConstants';
import { LoginConfig } from '../common/LoginConfig';
interface PSResultType {
Result: string;
Success: boolean;
Error: string;
}
export class AzPSLogin {
loginConfig: LoginConfig;
@@ -13,12 +23,78 @@ export class AzPSLogin {
async login() {
core.info(`Running Azure PowerShell Login.`);
AzPSUtils.setPSModulePathForGitHubRunner();
await AzPSUtils.importLatestAzAccounts();
this.setPSModulePathForGitHubRunner();
await this.importLatestAzAccounts();
const [loginMethod, loginScript] = await AzPSScriptBuilder.getAzPSLoginScript(this.loginConfig);
core.info(`Attempting Azure PowerShell login by using ${loginMethod}...`);
core.debug(`Azure PowerShell Login Script: ${loginScript}`);
await AzPSUtils.runPSScript(loginScript);
await AzPSLogin.runPSScript(loginScript);
console.log(`Running Azure PowerShell Login successfully.`);
}
setPSModulePathForGitHubRunner() {
const runner: string = process.env.RUNNER_OS || os.type();
switch (runner.toLowerCase()) {
case "linux":
this.pushPSModulePath(AzPSConstants.DEFAULT_AZ_PATH_ON_LINUX);
break;
case "windows":
case "windows_nt":
this.pushPSModulePath(AzPSConstants.DEFAULT_AZ_PATH_ON_WINDOWS);
break;
case "macos":
case "darwin":
core.warning(`Skip setting the default PowerShell module path for OS ${runner.toLowerCase()}.`);
break;
default:
core.warning(`Skip setting the default PowerShell module path for unknown OS ${runner.toLowerCase()}.`);
break;
}
}
private pushPSModulePath(psModulePath: string) {
process.env.PSModulePath = `${psModulePath}${path.delimiter}${process.env.PSModulePath}`;
core.debug(`Set PSModulePath as ${process.env.PSModulePath}`);
}
private async importLatestAzAccounts() {
let importLatestAccountsScript: string = AzPSScriptBuilder.getImportLatestModuleScript(AzPSConstants.AzAccounts);
core.debug(`The script to import the latest Az.Accounts: ${importLatestAccountsScript}`);
let azAccountsPath: string = await AzPSLogin.runPSScript(importLatestAccountsScript);
core.debug(`The latest Az.Accounts used: ${azAccountsPath}`);
}
static async runPSScript(psScript: string): Promise<string> {
let outputString: string = "";
let commandStdErr = false;
const options: any = {
silent: true,
listeners: {
stdout: (data: Buffer) => {
outputString += data.toString();
},
stderr: (data: Buffer) => {
let error = data.toString();
if (error && error.trim().length !== 0) {
commandStdErr = true;
core.error(error);
}
}
}
};
let psPath: string = await io.which(AzPSConstants.PowerShell_CmdName, true);
await exec.exec(`"${psPath}"`, ["-Command", psScript], options)
if (commandStdErr) {
throw new Error('Azure PowerShell login failed with errors.');
}
const result: PSResultType = JSON.parse(outputString.trim());
console.log(result);
if (!(result.Success)) {
throw new Error(`Azure PowerShell login failed with error: ${result.Error}`);
}
return result.Result;
}
}

View File

@@ -1,3 +1,4 @@
import AzPSConstants from "./AzPSConstants";
import { LoginConfig } from '../common/LoginConfig';
export default class AzPSScriptBuilder {
@@ -23,7 +24,8 @@ export default class AzPSScriptBuilder {
static async getAzPSLoginScript(loginConfig: LoginConfig) {
let loginMethodName = "";
let commands = "";
let commands = 'Clear-AzContext -Scope Process; ';
commands += 'Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue; ';
if (loginConfig.environment.toLowerCase() == "azurestack") {
commands += `Add-AzEnvironment -Name '${loginConfig.environment}' -ARMEndpoint '${loginConfig.resourceManagerEndpointUrl}' | out-null;`;

View File

@@ -1,85 +0,0 @@
import * as core from '@actions/core';
import * as os from 'os';
import * as path from 'path';
import * as exec from '@actions/exec';
import * as io from '@actions/io';
import AzPSScriptBuilder from './AzPSScriptBuilder';
interface PSResultType {
Result: string;
Success: boolean;
Error: string;
}
export class AzPSConstants {
static readonly DEFAULT_AZ_PATH_ON_LINUX: string = '/usr/share';
static readonly DEFAULT_AZ_PATH_ON_WINDOWS: string = 'C:\\Modules';
static readonly AzAccounts: string = "Az.Accounts";
static readonly PowerShell_CmdName = "pwsh";
}
export class AzPSUtils {
static async setPSModulePathForGitHubRunner() {
const runner: string = process.env.RUNNER_OS || os.type();
switch (runner.toLowerCase()) {
case "linux":
AzPSUtils.pushPSModulePath(AzPSConstants.DEFAULT_AZ_PATH_ON_LINUX);
break;
case "windows":
case "windows_nt":
AzPSUtils.pushPSModulePath(AzPSConstants.DEFAULT_AZ_PATH_ON_WINDOWS);
break;
case "macos":
case "darwin":
core.warning(`Skip setting the default PowerShell module path for OS ${runner.toLowerCase()}.`);
break;
default:
core.warning(`Skip setting the default PowerShell module path for unknown OS ${runner.toLowerCase()}.`);
break;
}
}
private static pushPSModulePath(psModulePath: string) {
process.env.PSModulePath = `${psModulePath}${path.delimiter}${process.env.PSModulePath}`;
core.debug(`Set PSModulePath as ${process.env.PSModulePath}`);
}
static async importLatestAzAccounts() {
let importLatestAccountsScript: string = AzPSScriptBuilder.getImportLatestModuleScript(AzPSConstants.AzAccounts);
core.debug(`The script to import the latest Az.Accounts: ${importLatestAccountsScript}`);
let azAccountsPath: string = await AzPSUtils.runPSScript(importLatestAccountsScript);
core.debug(`The latest Az.Accounts used: ${azAccountsPath}`);
}
static async runPSScript(psScript: string): Promise<string> {
let outputString: string = "";
let commandStdErr = false;
const options: any = {
silent: true,
listeners: {
stdout: (data: Buffer) => {
outputString += data.toString();
},
stderr: (data: Buffer) => {
let error = data.toString();
if (error && error.trim().length !== 0) {
commandStdErr = true;
core.error(error);
}
}
}
};
let psPath: string = await io.which(AzPSConstants.PowerShell_CmdName, true);
await exec.exec(`"${psPath}"`, ["-Command", psScript], options)
if (commandStdErr) {
throw new Error('Azure PowerShell login failed with errors.');
}
const result: PSResultType = JSON.parse(outputString.trim());
console.log(result);
if (!(result.Success)) {
throw new Error(`Azure PowerShell login failed with error: ${result.Error}`);
}
return result.Result;
}
}

View File

@@ -1,19 +0,0 @@
import * as core from '@actions/core';
import { setUserAgent, cleanupAzCLIAccounts, cleanupAzPSAccounts } from './common/Utils';
async function cleanup() {
try {
setUserAgent();
await cleanupAzCLIAccounts();
if(core.getInput('enable-AzPSSession').toLowerCase() === "true"){
await cleanupAzPSAccounts();
}
}
catch (error) {
core.warning(`Login cleanup failed with ${error}. Cleanup will be skipped.`);
core.debug(error.stack);
}
}
cleanup();

View File

@@ -69,8 +69,8 @@ export class LoginConfig {
this.tenantId = this.tenantId ? this.tenantId : secrets.getSecret("$.tenantId", false);
this.subscriptionId = this.subscriptionId ? this.subscriptionId : secrets.getSecret("$.subscriptionId", false);
this.resourceManagerEndpointUrl = secrets.getSecret("$.resourceManagerEndpointUrl", false);
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'.");
if (!this.servicePrincipalId || !this.servicePrincipalSecret || !this.tenantId || !this.subscriptionId) {
throw new Error("Not all parameters are provided in 'creds'. Double-check if all keys are defined in 'creds': 'clientId', 'clientSecret', 'subscriptionId', 'tenantId'.");
}
}

View File

@@ -1,30 +0,0 @@
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as io from '@actions/io';
import * as crypto from 'crypto';
import { AzPSConstants, AzPSUtils } from '../PowerShell/AzPSUtils';
export function setUserAgent(): void {
let usrAgentRepo = crypto.createHash('sha256').update(`${process.env.GITHUB_REPOSITORY}`).digest('hex');
let actionName = 'AzureLogin';
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}@v1_${usrAgentRepo}`;
}
export async function cleanupAzCLIAccounts(): Promise<void> {
let azPath = await io.which("az", true);
core.debug(`Azure CLI path: ${azPath}`);
core.info("Clearing azure cli accounts from the local cache.");
await exec.exec(`"${azPath}"`, ["account", "clear"]);
}
export async function cleanupAzPSAccounts(): Promise<void> {
let psPath: string = await io.which(AzPSConstants.PowerShell_CmdName, true);
core.debug(`PowerShell path: ${psPath}`);
core.debug("Importing Azure PowerShell module.");
AzPSUtils.setPSModulePathForGitHubRunner();
await AzPSUtils.importLatestAzAccounts();
core.info("Clearing azure powershell accounts from the local cache.");
await exec.exec(`"${psPath}"`, ["-Command", "Clear-AzContext", "-Scope", "Process"]);
await exec.exec(`"${psPath}"`, ["-Command", "Clear-AzContext", "-Scope", "CurrentUser", "-Force", "-ErrorAction", "SilentlyContinue"]);
}

View File

@@ -1,12 +1,19 @@
import * as core from '@actions/core';
import { setUserAgent } from './common/Utils';
import { AzPSLogin } from './PowerShell/AzPSLogin';
import { LoginConfig } from './common/LoginConfig';
import { AzureCliLogin } from './Cli/AzureCliLogin';
var prefix = !!process.env.AZURE_HTTP_USER_AGENT ? `${process.env.AZURE_HTTP_USER_AGENT}` : "";
var azPSHostEnv = !!process.env.AZUREPS_HOST_ENVIRONMENT ? `${process.env.AZUREPS_HOST_ENVIRONMENT}` : "";
async function main() {
try {
setUserAgent();
let usrAgentRepo = `${process.env.GITHUB_REPOSITORY}`;
let actionName = 'AzureLogin';
let userAgentString = (!!prefix ? `${prefix}+` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`;
let azurePSHostEnv = (!!azPSHostEnv ? `${azPSHostEnv}+` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`;
core.exportVariable('AZURE_HTTP_USER_AGENT', userAgentString);
core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azurePSHostEnv);
// prepare the login configuration
var loginConfig = new LoginConfig();
@@ -24,9 +31,14 @@ async function main() {
}
}
catch (error) {
core.setFailed(`Login failed with ${error}. Double check if the 'auth-type' is correct. Refer to https://github.com/Azure/login#readme for more information.`);
core.setFailed(`Login failed with ${error}. Make sure 'az' is installed on the runner. If 'enable-AzPSSession' is true, make sure 'pwsh' is installed on the runner together with Azure PowerShell module. Double check if the 'auth-type' is correct. Refer to https://github.com/Azure/login#readme for more information.`);
core.debug(error.stack);
}
finally {
// Reset AZURE_HTTP_USER_AGENT
core.exportVariable('AZURE_HTTP_USER_AGENT', prefix);
core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azPSHostEnv);
}
}
main();