Azure PowerShell Login changes (#25)
* Initial commit
* updating package version
* adding secret info link in logs
* adding user-agent
* Update README.md
* Added changes for azure powershell login
Changes in loginAzurePowerShell.ts
using latest version
Added getlatestazmodule version
changes in runner info
code refactor
changes in loginAzurePowerShell
code refactor
Code refactor
Code refactor
added review comments
changes in scriptbuilder
changes in setmodulepath
added paths in tsconfig.json
Revert "added paths in tsconfig.json"
This reverts commit cb2f4176bf.
changes in action.yml
changes in main
added review comments
Added changes for review comments
Modified description in action.yml
Added telemetry info
Code refactor
added review comments
added review comments
removed tslint from package.json
added log in ServicePrincipalLogin
added boolean for error log
Added Unit tests (#15)
* Added unit tests for Azure PowerShell
* Added unit tests
* changes in utils
* removed babel
* changed variable name of enable-PSSession
* refactor
* added ci.yml
* changes in utils test
making login calls silent (#19)
Co-authored-by: Deepak Sattiraju <desattir@microsoft.com>
update utils test (#16)
* update utils test
* update utils test
* update serviceprincipallogin test
Co-authored-by: Microsoft GitHub User <msftgits@microsoft.com>
Co-authored-by: Sumiran Aggarwal <suaggar@microsoft.com>
Co-authored-by: UshaN <ushan@microsoft.com>
This commit is contained in:
parent
d1bf5b744b
commit
ab6d759ee8
22 changed files with 766 additions and 15 deletions
28
.github/workflows/ci.yml
vendored
Normal file
28
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build_test_job:
|
||||
name: 'Build and test job'
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||
steps:
|
||||
|
||||
- name: 'Checking out repo code'
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: 'Validate build'
|
||||
run: |
|
||||
npm install
|
||||
npm run build
|
||||
|
||||
- name: 'Run L0 tests'
|
||||
run: |
|
||||
npm run test
|
||||
38
__tests__/PowerShell/ServicePrinicipalLogin.test.ts
Normal file
38
__tests__/PowerShell/ServicePrinicipalLogin.test.ts
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import { ServicePrincipalLogin } from '../../src/PowerShell/ServicePrincipalLogin';
|
||||
|
||||
jest.mock('../../src/PowerShell/Utilities/Utils');
|
||||
jest.mock('../../src/PowerShell/Utilities/PowerShellToolRunner');
|
||||
let spnlogin: ServicePrincipalLogin;
|
||||
|
||||
beforeAll(() => {
|
||||
spnlogin = new ServicePrincipalLogin("servicePrincipalID", "servicePrinicipalkey", "tenantId", "subscriptionId");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('Testing initialize', () => {
|
||||
let initializeSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
initializeSpy = jest.spyOn(spnlogin, 'initialize');
|
||||
});
|
||||
test('ServicePrincipalLogin initialize should pass', async () => {
|
||||
await spnlogin.initialize();
|
||||
expect(initializeSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Testing login', () => {
|
||||
let loginSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
loginSpy = jest.spyOn(spnlogin, 'login');
|
||||
});
|
||||
test('ServicePrincipal login should pass', async () => {
|
||||
loginSpy.mockImplementationOnce(() => Promise.resolve());
|
||||
await spnlogin.login();
|
||||
expect(loginSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
45
__tests__/PowerShell/Utilities/Utils.test.ts
Normal file
45
__tests__/PowerShell/Utilities/Utils.test.ts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import Utils from '../../../src/PowerShell/Utilities/Utils';
|
||||
|
||||
const version: string = '9.0.0';
|
||||
const moduleName: string = 'az';
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('Testing isValidVersion', () => {
|
||||
const validVersion: string = '1.2.4';
|
||||
const invalidVersion: string = 'a.bcd';
|
||||
|
||||
test('isValidVersion should be true', () => {
|
||||
expect(Utils.isValidVersion(validVersion)).toBeTruthy();
|
||||
});
|
||||
test('isValidVersion should be false', () => {
|
||||
expect(Utils.isValidVersion(invalidVersion)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Testing setPSModulePath', () => {
|
||||
test('PSModulePath with azPSVersion non-empty', () => {
|
||||
Utils.setPSModulePath(version);
|
||||
expect(process.env.PSModulePath).toContain(version);
|
||||
});
|
||||
test('PSModulePath with azPSVersion empty', () => {
|
||||
const prevPSModulePath = process.env.PSModulePath;
|
||||
Utils.setPSModulePath();
|
||||
expect(process.env.PSModulePath).not.toEqual(prevPSModulePath);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Testing getLatestModule', () => {
|
||||
let getLatestModuleSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
getLatestModuleSpy = jest.spyOn(Utils, 'getLatestModule');
|
||||
});
|
||||
test('getLatestModule should pass', async () => {
|
||||
getLatestModuleSpy.mockImplementationOnce((_moduleName: string) => Promise.resolve(version));
|
||||
await Utils.getLatestModule(moduleName);
|
||||
expect(getLatestModuleSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,10 +1,14 @@
|
|||
# Login to Azure subscription
|
||||
name: 'Azure Login'
|
||||
description: 'Login Azure wraps the az login, allowing Azure actions to log into Azure or to run Az CLI scripts. github.com/Azure/Actions'
|
||||
description: 'Authenticate to Azure and run your Az CLI or Az PowerShell based Actions or scripts. github.com/Azure/Actions'
|
||||
inputs:
|
||||
creds:
|
||||
description: 'Paste output of `az ad sp create-for-rbac` as value of secret variable: AZURE_CREDENTIALS'
|
||||
required: true
|
||||
enable-AzPSSession:
|
||||
description: 'Set this value to true to enable Azure PowerShell Login in addition to Az CLI login'
|
||||
required: false
|
||||
default: false
|
||||
branding:
|
||||
icon: 'login.svg'
|
||||
color: 'blue'
|
||||
|
|
|
|||
14
jest.config.js
Normal file
14
jest.config.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// For a detailed explanation regarding each configuration property, visit:
|
||||
// https://jestjs.io/docs/en/configuration.html
|
||||
|
||||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/*.test.ts'],
|
||||
testRunner: 'jest-circus/runner',
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
verbose: true
|
||||
};
|
||||
14
lib/PowerShell/Constants.js
Normal file
14
lib/PowerShell/Constants.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
class Constants {
|
||||
}
|
||||
exports.default = Constants;
|
||||
Constants.prefix = "az_";
|
||||
Constants.moduleName = "Az.Accounts";
|
||||
Constants.versionPattern = /[0-9]\.[0-9]\.[0-9]/;
|
||||
Constants.AzureCloud = "AzureCloud";
|
||||
Constants.Subscription = "Subscription";
|
||||
Constants.ServicePrincipal = "ServicePrincipal";
|
||||
Constants.Success = "Success";
|
||||
Constants.Error = "Error";
|
||||
Constants.AzVersion = "AzVersion";
|
||||
0
lib/PowerShell/IAzurePowerShellSession.js
Normal file
0
lib/PowerShell/IAzurePowerShellSession.js
Normal file
73
lib/PowerShell/ServicePrincipalLogin.js
Normal file
73
lib/PowerShell/ServicePrincipalLogin.js
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
"use strict";
|
||||
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 __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const Utils_1 = __importDefault(require("./Utilities/Utils"));
|
||||
const PowerShellToolRunner_1 = __importDefault(require("./Utilities/PowerShellToolRunner"));
|
||||
const ScriptBuilder_1 = __importDefault(require("./Utilities/ScriptBuilder"));
|
||||
const Constants_1 = __importDefault(require("./Constants"));
|
||||
class ServicePrincipalLogin {
|
||||
constructor(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId) {
|
||||
this.servicePrincipalId = servicePrincipalId;
|
||||
this.servicePrincipalKey = servicePrincipalKey;
|
||||
this.tenantId = tenantId;
|
||||
this.subscriptionId = subscriptionId;
|
||||
}
|
||||
initialize() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
Utils_1.default.setPSModulePath();
|
||||
const azLatestVersion = yield Utils_1.default.getLatestModule(Constants_1.default.moduleName);
|
||||
core.debug(`Az Module version used: ${azLatestVersion}`);
|
||||
Utils_1.default.setPSModulePath(`${Constants_1.default.prefix}${azLatestVersion}`);
|
||||
});
|
||||
}
|
||||
login() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let output = "";
|
||||
const options = {
|
||||
listeners: {
|
||||
stdout: (data) => {
|
||||
output += data.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
const args = {
|
||||
servicePrincipalId: this.servicePrincipalId,
|
||||
servicePrincipalKey: this.servicePrincipalKey,
|
||||
subscriptionId: this.subscriptionId,
|
||||
environment: ServicePrincipalLogin.environment,
|
||||
scopeLevel: ServicePrincipalLogin.scopeLevel
|
||||
};
|
||||
const script = new ScriptBuilder_1.default().getAzPSLoginScript(ServicePrincipalLogin.scheme, this.tenantId, args);
|
||||
yield PowerShellToolRunner_1.default.init();
|
||||
yield PowerShellToolRunner_1.default.executePowerShellScriptBlock(script, options);
|
||||
const result = JSON.parse(output.trim());
|
||||
if (!(Constants_1.default.Success in result)) {
|
||||
throw new Error(`Azure PowerShell login failed with error: ${result[Constants_1.default.Error]}`);
|
||||
}
|
||||
console.log(`Azure PowerShell session successfully initialized`);
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.ServicePrincipalLogin = ServicePrincipalLogin;
|
||||
ServicePrincipalLogin.environment = Constants_1.default.AzureCloud;
|
||||
ServicePrincipalLogin.scopeLevel = Constants_1.default.Subscription;
|
||||
ServicePrincipalLogin.scheme = Constants_1.default.ServicePrincipal;
|
||||
35
lib/PowerShell/Utilities/PowerShellToolRunner.js
Normal file
35
lib/PowerShell/Utilities/PowerShellToolRunner.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
"use strict";
|
||||
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 __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const io = __importStar(require("@actions/io"));
|
||||
const exec = __importStar(require("@actions/exec"));
|
||||
class PowerShellToolRunner {
|
||||
static init() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (!PowerShellToolRunner.psPath) {
|
||||
PowerShellToolRunner.psPath = yield io.which("pwsh", true);
|
||||
}
|
||||
});
|
||||
}
|
||||
static executePowerShellScriptBlock(scriptBlock, options = {}) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
yield exec.exec(`${PowerShellToolRunner.psPath} -Command`, [scriptBlock], options);
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.default = PowerShellToolRunner;
|
||||
62
lib/PowerShell/Utilities/ScriptBuilder.js
Normal file
62
lib/PowerShell/Utilities/ScriptBuilder.js
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
"use strict";
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const Constants_1 = __importDefault(require("../Constants"));
|
||||
class ScriptBuilder {
|
||||
constructor() {
|
||||
this.script = "";
|
||||
}
|
||||
getAzPSLoginScript(scheme, tenantId, args) {
|
||||
let command = `Clear-AzContext -Scope Process;
|
||||
Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue;`;
|
||||
if (scheme === Constants_1.default.ServicePrincipal) {
|
||||
command += `Connect-AzAccount -ServicePrincipal -Tenant ${tenantId} -Credential \
|
||||
(New-Object System.Management.Automation.PSCredential('${args.servicePrincipalId}',(ConvertTo-SecureString ${args.servicePrincipalKey} -AsPlainText -Force))) \
|
||||
-Environment ${args.environment} | out-null;`;
|
||||
if (args.scopeLevel === Constants_1.default.Subscription) {
|
||||
command += `Set-AzContext -SubscriptionId ${args.subscriptionId} -TenantId ${tenantId} | out-null;`;
|
||||
}
|
||||
}
|
||||
this.script += `try {
|
||||
$ErrorActionPreference = "Stop"
|
||||
$WarningPreference = "SilentlyContinue"
|
||||
$output = @{}
|
||||
${command}
|
||||
$output['${Constants_1.default.Success}'] = "true"
|
||||
}
|
||||
catch {
|
||||
$output['${Constants_1.default.Error}'] = $_.exception.Message
|
||||
}
|
||||
return ConvertTo-Json $output`;
|
||||
core.debug(`Azure PowerShell Login Script: ${this.script}`);
|
||||
return this.script;
|
||||
}
|
||||
getLatestModuleScript(moduleName) {
|
||||
const command = `Get-Module -Name ${moduleName} -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1`;
|
||||
this.script += `try {
|
||||
$ErrorActionPreference = "Stop"
|
||||
$WarningPreference = "SilentlyContinue"
|
||||
$output = @{}
|
||||
$data = ${command}
|
||||
$output['${Constants_1.default.AzVersion}'] = $data.Version.ToString()
|
||||
$output['${Constants_1.default.Success}'] = "true"
|
||||
}
|
||||
catch {
|
||||
$output['${Constants_1.default.Error}'] = $_.exception.Message
|
||||
}
|
||||
return ConvertTo-Json $output`;
|
||||
core.debug(`GetLatestModuleScript: ${this.script}`);
|
||||
return this.script;
|
||||
}
|
||||
}
|
||||
exports.default = ScriptBuilder;
|
||||
80
lib/PowerShell/Utilities/Utils.js
Normal file
80
lib/PowerShell/Utilities/Utils.js
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
"use strict";
|
||||
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 __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const os = __importStar(require("os"));
|
||||
const Constants_1 = __importDefault(require("../Constants"));
|
||||
const ScriptBuilder_1 = __importDefault(require("./ScriptBuilder"));
|
||||
const PowerShellToolRunner_1 = __importDefault(require("./PowerShellToolRunner"));
|
||||
class Utils {
|
||||
/**
|
||||
* Add the folder path where Az modules are present to PSModulePath based on runner
|
||||
* @param azPSVersion
|
||||
* If azPSVersion is empty, folder path in which all Az modules are present are set
|
||||
* If azPSVersion is not empty, folder path of exact Az module version is set
|
||||
*/
|
||||
static setPSModulePath(azPSVersion = "") {
|
||||
let modulePath = "";
|
||||
const runner = process.env.RUNNER_OS || os.type();
|
||||
switch (runner.toLowerCase()) {
|
||||
case "linux":
|
||||
modulePath = `/usr/share/${azPSVersion}:`;
|
||||
break;
|
||||
case "windows":
|
||||
case "windows_nt":
|
||||
modulePath = `C:\\Modules\\${azPSVersion};`;
|
||||
break;
|
||||
case "macos":
|
||||
case "darwin":
|
||||
throw new Error(`OS not supported`);
|
||||
default:
|
||||
throw new Error(`Unknown os: ${runner.toLowerCase()}`);
|
||||
}
|
||||
process.env.PSModulePath = `${modulePath}${process.env.PSModulePath}`;
|
||||
}
|
||||
static getLatestModule(moduleName) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let output = "";
|
||||
const options = {
|
||||
listeners: {
|
||||
stdout: (data) => {
|
||||
output += data.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
yield PowerShellToolRunner_1.default.init();
|
||||
yield PowerShellToolRunner_1.default.executePowerShellScriptBlock(new ScriptBuilder_1.default()
|
||||
.getLatestModuleScript(moduleName), options);
|
||||
const result = JSON.parse(output.trim());
|
||||
if (!(Constants_1.default.Success in result)) {
|
||||
throw new Error(result[Constants_1.default.Error]);
|
||||
}
|
||||
const azLatestVersion = result[Constants_1.default.AzVersion];
|
||||
if (!Utils.isValidVersion(azLatestVersion)) {
|
||||
throw new Error(`Invalid AzPSVersion: ${azLatestVersion}`);
|
||||
}
|
||||
return azLatestVersion;
|
||||
});
|
||||
}
|
||||
static isValidVersion(version) {
|
||||
return !!version.match(Constants_1.default.versionPattern);
|
||||
}
|
||||
}
|
||||
exports.default = Utils;
|
||||
29
lib/main.js
29
lib/main.js
|
|
@ -21,16 +21,21 @@ const crypto = __importStar(require("crypto"));
|
|||
const exec = __importStar(require("@actions/exec"));
|
||||
const io = __importStar(require("@actions/io"));
|
||||
const actions_secret_parser_1 = require("actions-secret-parser");
|
||||
const ServicePrincipalLogin_1 = require("./PowerShell/ServicePrincipalLogin");
|
||||
var azPath;
|
||||
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 {
|
||||
// Set user agent varable
|
||||
// Set user agent variable
|
||||
var isAzCLISuccess = false;
|
||||
let usrAgentRepo = crypto.createHash('sha256').update(`${process.env.GITHUB_REPOSITORY}`).digest('hex');
|
||||
let actionName = 'AzureLogin';
|
||||
let userAgentString = (!!prefix ? `${prefix}+` : '') + `GITHUBACTIONS_${actionName}_${usrAgentRepo}`;
|
||||
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);
|
||||
azPath = yield io.which("az", true);
|
||||
yield executeAzCliCommand("--version");
|
||||
let creds = core.getInput('creds', { required: true });
|
||||
|
|
@ -39,20 +44,36 @@ function main() {
|
|||
let servicePrincipalKey = secrets.getSecret("$.clientSecret", true);
|
||||
let tenantId = secrets.getSecret("$.tenantId", false);
|
||||
let subscriptionId = secrets.getSecret("$.subscriptionId", false);
|
||||
const enableAzPSSession = core.getInput('enable-AzPSSession').toLowerCase() === "true";
|
||||
if (!servicePrincipalId || !servicePrincipalKey || !tenantId || !subscriptionId) {
|
||||
throw new Error("Not all values are present in the creds object. Ensure clientId, clientSecret, tenantId and subscriptionId are supplied.");
|
||||
}
|
||||
// Attempting Az cli login
|
||||
yield executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`, true);
|
||||
yield executeAzCliCommand(`account set --subscription "${subscriptionId}"`, true);
|
||||
isAzCLISuccess = true;
|
||||
if (enableAzPSSession) {
|
||||
// Attempting Az PS login
|
||||
console.log(`Running Azure PS Login`);
|
||||
const spnlogin = new ServicePrincipalLogin_1.ServicePrincipalLogin(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId);
|
||||
yield spnlogin.initialize();
|
||||
yield spnlogin.login();
|
||||
}
|
||||
console.log("Login successful.");
|
||||
}
|
||||
catch (error) {
|
||||
core.error("Login failed. Please check the credentials. For more information refer https://aka.ms/create-secrets-for-GitHub-workflows");
|
||||
if (!isAzCLISuccess) {
|
||||
core.error("Az CLI Login failed. Please check the credentials. For more information refer https://aka.ms/create-secrets-for-GitHub-workflows");
|
||||
}
|
||||
else {
|
||||
core.error(`Azure PowerShell Login failed. Please check the credentials. For more information refer https://aka.ms/create-secrets-for-GitHub-workflows"`);
|
||||
}
|
||||
core.setFailed(error);
|
||||
}
|
||||
finally {
|
||||
// Reset AZURE_HTTP_USER_AGENT
|
||||
core.exportVariable('AZURE_HTTP_USER_AGENT', prefix);
|
||||
core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azPSHostEnv);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -66,4 +87,4 @@ function executeAzCliCommand(command, silent) {
|
|||
}
|
||||
});
|
||||
}
|
||||
main();
|
||||
main();
|
||||
109
package-lock.json
generated
109
package-lock.json
generated
|
|
@ -36,6 +36,35 @@
|
|||
"xpath": "0.0.27"
|
||||
}
|
||||
},
|
||||
"asyncc": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/asyncc/-/asyncc-2.0.4.tgz",
|
||||
"integrity": "sha512-5ohHLrRC6ZJ7ypVlJh3XJlINBdErz7VeQnNNLXq2T9hVsph58x49oykgg+KNbpnOiMF0X2vDmR2i2LVtWBL7Mw=="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"commander": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
|
||||
"integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"deep-is": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
|
||||
|
|
@ -80,6 +109,38 @@
|
|||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"jsonpath": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.0.2.tgz",
|
||||
|
|
@ -99,6 +160,27 @@
|
|||
"type-check": "~0.3.2"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"optionator": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
|
||||
|
|
@ -112,6 +194,23 @@
|
|||
"word-wrap": "~1.2.3"
|
||||
}
|
||||
},
|
||||
"package-lock": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/package-lock/-/package-lock-1.0.3.tgz",
|
||||
"integrity": "sha512-rEiz3fs0M8jyH1OtWE3TP7MdtWJnsE69qEOipZ4CDF3KoN3XY5mcDucXugTli6Lqig9rhQ/6ST2atxjU2/aIFQ==",
|
||||
"requires": {
|
||||
"asyncc": "^2.0.4",
|
||||
"commander": "^5.0.0",
|
||||
"glob": "^7.1.6",
|
||||
"lodash": "^4.17.15",
|
||||
"traverse": "^0.6.6"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"prelude-ls": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
|
||||
|
|
@ -131,6 +230,11 @@
|
|||
"escodegen": "^1.8.1"
|
||||
}
|
||||
},
|
||||
"traverse": {
|
||||
"version": "0.6.6",
|
||||
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz",
|
||||
"integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc="
|
||||
},
|
||||
"type-check": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
|
||||
|
|
@ -155,6 +259,11 @@
|
|||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"xmldom": {
|
||||
"version": "0.1.27",
|
||||
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz",
|
||||
|
|
|
|||
|
|
@ -5,18 +5,23 @@
|
|||
"main": "lib/main.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"test": "jest"
|
||||
},
|
||||
"author": "Sumiran Aggarwal",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/jest": "^25.1.4",
|
||||
"@types/node": "^12.7.11",
|
||||
"jest": "^25.2.4",
|
||||
"jest-circus": "^25.2.7",
|
||||
"ts-jest": "^25.3.0",
|
||||
"typescript": "^3.6.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.1.3",
|
||||
"@actions/exec": "^1.0.1",
|
||||
"@actions/io": "^1.0.1",
|
||||
"actions-secret-parser": "^1.0.2"
|
||||
"actions-secret-parser": "^1.0.2",
|
||||
"package-lock": "^1.0.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
13
src/PowerShell/Constants.ts
Normal file
13
src/PowerShell/Constants.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
export default class Constants {
|
||||
static readonly prefix: string = "az_";
|
||||
static readonly moduleName: string = "Az.Accounts";
|
||||
static readonly versionPattern = /[0-9]\.[0-9]\.[0-9]/;
|
||||
|
||||
static readonly AzureCloud: string = "AzureCloud";
|
||||
static readonly Subscription: string = "Subscription";
|
||||
static readonly ServicePrincipal: string = "ServicePrincipal";
|
||||
|
||||
static readonly Success: string = "Success";
|
||||
static readonly Error: string = "Error";
|
||||
static readonly AzVersion: string = "AzVersion";
|
||||
}
|
||||
4
src/PowerShell/IAzurePowerShellSession.ts
Normal file
4
src/PowerShell/IAzurePowerShellSession.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
interface IAzurePowerShellSession {
|
||||
initialize();
|
||||
login();
|
||||
}
|
||||
57
src/PowerShell/ServicePrincipalLogin.ts
Normal file
57
src/PowerShell/ServicePrincipalLogin.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import * as core from '@actions/core';
|
||||
|
||||
import Utils from './Utilities/Utils';
|
||||
import PowerShellToolRunner from './Utilities/PowerShellToolRunner';
|
||||
import ScriptBuilder from './Utilities/ScriptBuilder';
|
||||
import Constants from './Constants';
|
||||
|
||||
export class ServicePrincipalLogin implements IAzurePowerShellSession {
|
||||
static readonly environment: string = Constants.AzureCloud;
|
||||
static readonly scopeLevel: string = Constants.Subscription;
|
||||
static readonly scheme: string = Constants.ServicePrincipal;
|
||||
servicePrincipalId: string;
|
||||
servicePrincipalKey: string;
|
||||
tenantId: string;
|
||||
subscriptionId: string;
|
||||
|
||||
constructor(servicePrincipalId: string, servicePrincipalKey: string, tenantId: string, subscriptionId: string) {
|
||||
this.servicePrincipalId = servicePrincipalId;
|
||||
this.servicePrincipalKey = servicePrincipalKey;
|
||||
this.tenantId = tenantId;
|
||||
this.subscriptionId = subscriptionId;
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
Utils.setPSModulePath();
|
||||
const azLatestVersion: string = await Utils.getLatestModule(Constants.moduleName);
|
||||
core.debug(`Az Module version used: ${azLatestVersion}`);
|
||||
Utils.setPSModulePath(`${Constants.prefix}${azLatestVersion}`);
|
||||
}
|
||||
|
||||
async login() {
|
||||
let output: string = "";
|
||||
const options: any = {
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
output += data.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
const args: any = {
|
||||
servicePrincipalId: this.servicePrincipalId,
|
||||
servicePrincipalKey: this.servicePrincipalKey,
|
||||
subscriptionId: this.subscriptionId,
|
||||
environment: ServicePrincipalLogin.environment,
|
||||
scopeLevel: ServicePrincipalLogin.scopeLevel
|
||||
}
|
||||
const script: string = new ScriptBuilder().getAzPSLoginScript(ServicePrincipalLogin.scheme, this.tenantId, args);
|
||||
await PowerShellToolRunner.init();
|
||||
await PowerShellToolRunner.executePowerShellScriptBlock(script, options);
|
||||
const result: any = JSON.parse(output.trim());
|
||||
if (!(Constants.Success in result)) {
|
||||
throw new Error(`Azure PowerShell login failed with error: ${result[Constants.Error]}`);
|
||||
}
|
||||
console.log(`Azure PowerShell session successfully initialized`);
|
||||
}
|
||||
|
||||
}
|
||||
16
src/PowerShell/Utilities/PowerShellToolRunner.ts
Normal file
16
src/PowerShell/Utilities/PowerShellToolRunner.ts
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import * as io from '@actions/io';
|
||||
import * as exec from '@actions/exec';
|
||||
|
||||
export default class PowerShellToolRunner {
|
||||
static psPath: string;
|
||||
|
||||
static async init() {
|
||||
if(!PowerShellToolRunner.psPath) {
|
||||
PowerShellToolRunner.psPath = await io.which("pwsh", true);
|
||||
}
|
||||
}
|
||||
|
||||
static async executePowerShellScriptBlock(scriptBlock: string, options: any = {}) {
|
||||
await exec.exec(`${PowerShellToolRunner.psPath} -Command`, [scriptBlock], options)
|
||||
}
|
||||
}
|
||||
51
src/PowerShell/Utilities/ScriptBuilder.ts
Normal file
51
src/PowerShell/Utilities/ScriptBuilder.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import * as core from '@actions/core';
|
||||
|
||||
import Constants from "../Constants";
|
||||
|
||||
export default class ScriptBuilder {
|
||||
script: string = "";
|
||||
|
||||
getAzPSLoginScript(scheme: string, tenantId: string, args: any): string {
|
||||
let command = `Clear-AzContext -Scope Process;
|
||||
Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue;`;
|
||||
if (scheme === Constants.ServicePrincipal) {
|
||||
command += `Connect-AzAccount -ServicePrincipal -Tenant ${tenantId} -Credential \
|
||||
(New-Object System.Management.Automation.PSCredential('${args.servicePrincipalId}',(ConvertTo-SecureString ${args.servicePrincipalKey} -AsPlainText -Force))) \
|
||||
-Environment ${args.environment} | out-null;`;
|
||||
if (args.scopeLevel === Constants.Subscription) {
|
||||
command += `Set-AzContext -SubscriptionId ${args.subscriptionId} -TenantId ${tenantId} | out-null;`;
|
||||
}
|
||||
}
|
||||
this.script += `try {
|
||||
$ErrorActionPreference = "Stop"
|
||||
$WarningPreference = "SilentlyContinue"
|
||||
$output = @{}
|
||||
${command}
|
||||
$output['${Constants.Success}'] = "true"
|
||||
}
|
||||
catch {
|
||||
$output['${Constants.Error}'] = $_.exception.Message
|
||||
}
|
||||
return ConvertTo-Json $output`;
|
||||
core.debug(`Azure PowerShell Login Script: ${this.script}`);
|
||||
return this.script;
|
||||
}
|
||||
|
||||
getLatestModuleScript(moduleName: string): string {
|
||||
const command: string = `Get-Module -Name ${moduleName} -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1`;
|
||||
this.script += `try {
|
||||
$ErrorActionPreference = "Stop"
|
||||
$WarningPreference = "SilentlyContinue"
|
||||
$output = @{}
|
||||
$data = ${command}
|
||||
$output['${Constants.AzVersion}'] = $data.Version.ToString()
|
||||
$output['${Constants.Success}'] = "true"
|
||||
}
|
||||
catch {
|
||||
$output['${Constants.Error}'] = $_.exception.Message
|
||||
}
|
||||
return ConvertTo-Json $output`;
|
||||
core.debug(`GetLatestModuleScript: ${this.script}`);
|
||||
return this.script;
|
||||
}
|
||||
}
|
||||
61
src/PowerShell/Utilities/Utils.ts
Normal file
61
src/PowerShell/Utilities/Utils.ts
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
import * as os from 'os';
|
||||
|
||||
import Constants from '../Constants';
|
||||
import ScriptBuilder from './ScriptBuilder';
|
||||
import PowerShellToolRunner from './PowerShellToolRunner';
|
||||
|
||||
export default class Utils {
|
||||
/**
|
||||
* Add the folder path where Az modules are present to PSModulePath based on runner
|
||||
* @param azPSVersion
|
||||
* If azPSVersion is empty, folder path in which all Az modules are present are set
|
||||
* If azPSVersion is not empty, folder path of exact Az module version is set
|
||||
*/
|
||||
static setPSModulePath(azPSVersion: string = "") {
|
||||
let modulePath: string = "";
|
||||
const runner: string = process.env.RUNNER_OS || os.type();
|
||||
switch (runner.toLowerCase()) {
|
||||
case "linux":
|
||||
modulePath = `/usr/share/${azPSVersion}:`;
|
||||
break;
|
||||
case "windows":
|
||||
case "windows_nt":
|
||||
modulePath = `C:\\Modules\\${azPSVersion};`;
|
||||
break;
|
||||
case "macos":
|
||||
case "darwin":
|
||||
throw new Error(`OS not supported`);
|
||||
default:
|
||||
throw new Error(`Unknown os: ${runner.toLowerCase()}`);
|
||||
}
|
||||
process.env.PSModulePath = `${modulePath}${process.env.PSModulePath}`;
|
||||
}
|
||||
|
||||
static async getLatestModule(moduleName: string): Promise<string> {
|
||||
let output: string = "";
|
||||
const options: any = {
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
output += data.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
await PowerShellToolRunner.init();
|
||||
await PowerShellToolRunner.executePowerShellScriptBlock(new ScriptBuilder()
|
||||
.getLatestModuleScript(moduleName), options);
|
||||
const result = JSON.parse(output.trim());
|
||||
if (!(Constants.Success in result)) {
|
||||
throw new Error(result[Constants.Error]);
|
||||
}
|
||||
const azLatestVersion: string = result[Constants.AzVersion];
|
||||
if (!Utils.isValidVersion(azLatestVersion)) {
|
||||
throw new Error(`Invalid AzPSVersion: ${azLatestVersion}`);
|
||||
}
|
||||
return azLatestVersion;
|
||||
}
|
||||
|
||||
static isValidVersion(version: string): boolean {
|
||||
return !!version.match(Constants.versionPattern);
|
||||
}
|
||||
}
|
||||
|
||||
30
src/main.ts
30
src/main.ts
|
|
@ -4,17 +4,22 @@ import * as exec from '@actions/exec';
|
|||
import * as io from '@actions/io';
|
||||
|
||||
import { FormatType, SecretParser } from 'actions-secret-parser';
|
||||
import { ServicePrincipalLogin } from './PowerShell/ServicePrincipalLogin';
|
||||
|
||||
var azPath: string;
|
||||
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{
|
||||
// Set user agent varable
|
||||
try {
|
||||
// Set user agent variable
|
||||
var isAzCLISuccess = false;
|
||||
let usrAgentRepo = crypto.createHash('sha256').update(`${process.env.GITHUB_REPOSITORY}`).digest('hex');
|
||||
let actionName = 'AzureLogin';
|
||||
let userAgentString = (!!prefix ? `${prefix}+` : '') + `GITHUBACTIONS_${actionName}_${usrAgentRepo}`;
|
||||
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);
|
||||
|
||||
azPath = await io.which("az", true);
|
||||
await executeAzCliCommand("--version");
|
||||
|
|
@ -25,19 +30,33 @@ async function main() {
|
|||
let servicePrincipalKey = secrets.getSecret("$.clientSecret", true);
|
||||
let tenantId = secrets.getSecret("$.tenantId", false);
|
||||
let subscriptionId = secrets.getSecret("$.subscriptionId", false);
|
||||
const enableAzPSSession = core.getInput('enable-AzPSSession').toLowerCase() === "true";
|
||||
if (!servicePrincipalId || !servicePrincipalKey || !tenantId || !subscriptionId) {
|
||||
throw new Error("Not all values are present in the creds object. Ensure clientId, clientSecret, tenantId and subscriptionId are supplied.");
|
||||
}
|
||||
|
||||
// Attempting Az cli login
|
||||
await executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`, true);
|
||||
await executeAzCliCommand(`account set --subscription "${subscriptionId}"`, true);
|
||||
isAzCLISuccess = true;
|
||||
if (enableAzPSSession) {
|
||||
// Attempting Az PS login
|
||||
console.log(`Running Azure PS Login`);
|
||||
const spnlogin: ServicePrincipalLogin = new ServicePrincipalLogin(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId);
|
||||
await spnlogin.initialize();
|
||||
await spnlogin.login();
|
||||
}
|
||||
console.log("Login successful.");
|
||||
} catch (error) {
|
||||
core.error("Login failed. Please check the credentials. For more information refer https://aka.ms/create-secrets-for-GitHub-workflows");
|
||||
if (!isAzCLISuccess) {
|
||||
core.error("Az CLI Login failed. Please check the credentials. For more information refer https://aka.ms/create-secrets-for-GitHub-workflows");
|
||||
} else {
|
||||
core.error(`Azure PowerShell Login failed. Please check the credentials. For more information refer https://aka.ms/create-secrets-for-GitHub-workflows"`);
|
||||
}
|
||||
core.setFailed(error);
|
||||
} finally {
|
||||
// Reset AZURE_HTTP_USER_AGENT
|
||||
core.exportVariable('AZURE_HTTP_USER_AGENT', prefix);
|
||||
core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azPSHostEnv);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -50,5 +69,4 @@ async function executeAzCliCommand(command: string, silent?: boolean) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
main();
|
||||
|
|
@ -56,5 +56,8 @@
|
|||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
}
|
||||
}
|
||||
},
|
||||
"exclude" : [
|
||||
"./__tests__"
|
||||
]
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue