diff --git a/lib/loginAzurePowerShell.js b/lib/loginAzurePowerShell.js new file mode 100644 index 00000000..f275a99a --- /dev/null +++ b/lib/loginAzurePowerShell.js @@ -0,0 +1,66 @@ +"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 exec = __importStar(require("@actions/exec")); +const io = __importStar(require("@actions/io")); +var psPath; +exports.initializeAz = (servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId) => __awaiter(void 0, void 0, void 0, function* () { + psPath = yield io.which("pwsh", true); + setPSModulePath(); + yield loginToAzure(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId); +}); +function setPSModulePath() { + // TODO: get latest module/setup action + let azPSVersion = "2.6.0"; + let modulePath = ""; + const runner = JSON.parse(process.env.RUNNER_CONTEXT); + switch (runner.os) { + case "Linux": + modulePath = `/usr/share/az_${azPSVersion}:`; + break; + case "Windows": + modulePath = `C:\\Modules\\az_${azPSVersion};`; + break; + case "macOS": + // TODO: add modulepath + break; + } + process.env.PSModulePath = `${modulePath}${process.env.PSModulePath}`; +} +function loginToAzure(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId) { + return __awaiter(this, void 0, void 0, function* () { + const environment = "AzureCloud"; + yield executePowerShellCommand(`Clear-AzContext -Scope Process`); + yield executePowerShellCommand(`Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue`); + yield executePowerShellCommand(`Connect-AzAccount -ServicePrincipal -Tenant ${tenantId} -Credential \ + (New-Object System.Management.Automation.PSCredential('${servicePrincipalId}',(ConvertTo-SecureString ${servicePrincipalKey} -AsPlainText -Force))) \ + -Environment ${environment}`); + yield executePowerShellCommand(`Set-AzContext -SubscriptionId ${subscriptionId} -TenantId ${tenantId}`); + yield executePowerShellCommand(`Get-AzContext`); + }); +} +function executePowerShellCommand(command) { + return __awaiter(this, void 0, void 0, function* () { + try { + yield exec.exec(`"${psPath}" -Command "${command}"`, [], {}); + } + catch (error) { + throw new Error(error); + } + }); +} diff --git a/lib/main.js b/lib/main.js index 0a1efa97..226622d4 100644 --- a/lib/main.js +++ b/lib/main.js @@ -21,12 +21,13 @@ 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 loginAzurePowerShell_1 = require("./loginAzurePowerShell"); var azPath; var prefix = !!process.env.AZURE_HTTP_USER_AGENT ? `${process.env.AZURE_HTTP_USER_AGENT}` : ""; function main() { return __awaiter(this, void 0, void 0, function* () { try { - // Set user agent varable + // Set user agent variable let usrAgentRepo = crypto.createHash('sha256').update(`${process.env.GITHUB_REPOSITORY}`).digest('hex'); let actionName = 'AzureLogin'; let userAgentString = (!!prefix ? `${prefix}+` : '') + `GITHUBACTIONS_${actionName}_${usrAgentRepo}`; @@ -44,6 +45,7 @@ function main() { } yield executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`); yield executeAzCliCommand(`account set --subscription "${subscriptionId}"`); + yield loginAzurePowerShell_1.initializeAz(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId); console.log("Login successful."); } catch (error) { diff --git a/src/loginAzurePowerShell.ts b/src/loginAzurePowerShell.ts new file mode 100644 index 00000000..afd51bdd --- /dev/null +++ b/src/loginAzurePowerShell.ts @@ -0,0 +1,48 @@ +import * as exec from '@actions/exec'; +import * as io from '@actions/io'; + +var psPath: string; + +export const initializeAz = async (servicePrincipalId: string, servicePrincipalKey: string, tenantId: string, subscriptionId: string) => { + psPath = await io.which("pwsh", true); + setPSModulePath(); + await loginToAzure(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId); +} + +function setPSModulePath() { + // TODO: get latest module/setup action + let azPSVersion: string = "2.6.0"; + let modulePath: string = ""; + const runner = JSON.parse(process.env.RUNNER_CONTEXT); + switch (runner.os) { + case "Linux": + modulePath = `/usr/share/az_${azPSVersion}:`; + break; + case "Windows": + modulePath = `C:\\Modules\\az_${azPSVersion};`; + break; + case "macOS": + // TODO: add modulepath + break; + } + process.env.PSModulePath = `${modulePath}${process.env.PSModulePath}`; +} + +async function loginToAzure(servicePrincipalId: string, servicePrincipalKey: string, tenantId: string, subscriptionId: string) { + const environment: string = "AzureCloud"; + await executePowerShellCommand(`Clear-AzContext -Scope Process`); + await executePowerShellCommand(`Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue`); + await executePowerShellCommand(`Connect-AzAccount -ServicePrincipal -Tenant ${tenantId} -Credential \ + (New-Object System.Management.Automation.PSCredential('${servicePrincipalId}',(ConvertTo-SecureString ${servicePrincipalKey} -AsPlainText -Force))) \ + -Environment ${environment}`); + await executePowerShellCommand(`Set-AzContext -SubscriptionId ${subscriptionId} -TenantId ${tenantId}`); + await executePowerShellCommand(`Get-AzContext`); +} + +async function executePowerShellCommand(command: string) { + try { + await exec.exec(`"${psPath}" -Command "${command}"`, [], {}) + } catch (error) { + throw new Error(error); + } +} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index a3a32fd5..b73f50bb 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,13 +4,14 @@ import * as exec from '@actions/exec'; import * as io from '@actions/io'; import { FormatType, SecretParser } from 'actions-secret-parser'; +import { initializeAz } from './loginAzurePowerShell'; var azPath: string; var prefix = !!process.env.AZURE_HTTP_USER_AGENT ? `${process.env.AZURE_HTTP_USER_AGENT}` : ""; async function main() { - try{ - // Set user agent varable + try { + // Set user agent variable let usrAgentRepo = crypto.createHash('sha256').update(`${process.env.GITHUB_REPOSITORY}`).digest('hex'); let actionName = 'AzureLogin'; let userAgentString = (!!prefix ? `${prefix}+` : '') + `GITHUBACTIONS_${actionName}_${usrAgentRepo}`; @@ -28,10 +29,10 @@ async function main() { 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."); } - await executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`); await executeAzCliCommand(`account set --subscription "${subscriptionId}"`); - console.log("Login successful."); + await initializeAz(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId); + 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"); core.setFailed(error); @@ -43,12 +44,11 @@ async function main() { async function executeAzCliCommand(command: string) { try { - await exec.exec(`"${azPath}" ${command}`, [], {}); + await exec.exec(`"${azPath}" ${command}`, [], {}); } catch(error) { throw new Error(error); } } - main(); \ No newline at end of file