-
Notifications
You must be signed in to change notification settings - Fork 264
/
main.js
216 lines (216 loc) · 11.7 KB
/
main.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
"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 core = __importStar(require("@actions/core"));
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 variable
var isAzCLISuccess = false;
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);
azPath = yield io.which("az", true);
core.debug(`az cli version used: ${azPath}`);
let azureSupportedCloudName = new Set([
"azureusgovernment",
"azurechinacloud",
"azuregermancloud",
"azurecloud",
"azurestack"
]);
let output = "";
const execOptions = {
listeners: {
stdout: (data) => {
output += data.toString();
}
}
};
yield executeAzCliCommand("--version", true, execOptions);
core.debug(`az cli version used:\n${output}`);
let creds = core.getInput('creds', { required: false });
let secrets = creds ? new actions_secret_parser_1.SecretParser(creds, actions_secret_parser_1.FormatType.JSON) : null;
let environment = core.getInput("environment").toLowerCase();
const enableAzPSSession = core.getInput('enable-AzPSSession').toLowerCase() === "true";
const allowNoSubscriptionsLogin = core.getInput('allow-no-subscriptions').toLowerCase() === "true";
//Check for the credentials in individual parameters in the workflow.
var servicePrincipalId = core.getInput('client-id', { required: false });
var servicePrincipalKey = null;
var tenantId = core.getInput('tenant-id', { required: false });
var subscriptionId = core.getInput('subscription-id', { required: false });
var resourceManagerEndpointUrl = "https://management.azure.com/";
var enableOIDC = true;
var federatedToken = null;
// If any of the individual credentials (clent_id, tenat_id, subscription_id) is present.
if (servicePrincipalId || tenantId || subscriptionId) {
//If few of the individual credentials (clent_id, tenat_id, subscription_id) are missing in action inputs.
if (!(servicePrincipalId && tenantId && (subscriptionId || allowNoSubscriptionsLogin)))
throw new Error("Few credentials are missing. ClientId,tenantId are mandatory. SubscriptionId is also mandatory if allow-no-subscriptions is not set.");
}
else {
if (creds) {
core.debug('using creds JSON...');
enableOIDC = false;
servicePrincipalId = secrets.getSecret("$.clientId", true);
servicePrincipalKey = secrets.getSecret("$.clientSecret", true);
tenantId = secrets.getSecret("$.tenantId", true);
subscriptionId = secrets.getSecret("$.subscriptionId", true);
resourceManagerEndpointUrl = secrets.getSecret("$.resourceManagerEndpointUrl", false);
}
else {
throw new Error("Credentials are not passed for Login action.");
}
}
//generic checks
//servicePrincipalKey is only required in non-oidc scenario.
if (!servicePrincipalId || !tenantId || !(servicePrincipalKey || enableOIDC)) {
throw new Error("Not all values are present in the credentials. Ensure clientId, clientSecret and tenantId are supplied.");
}
if (!subscriptionId && !allowNoSubscriptionsLogin) {
throw new Error("Not all values are present in the credentials. Ensure subscriptionId is supplied.");
}
if (!azureSupportedCloudName.has(environment)) {
throw new Error("Unsupported value for environment is passed.The list of supported values for environment are ‘azureusgovernment', ‘azurechinacloud’, ‘azuregermancloud’, ‘azurecloud’ or ’azurestack’");
}
// OIDC specific checks
if (enableOIDC) {
console.log('Using OIDC authentication...');
//generating ID-token
let audience = core.getInput('audience', { required: false });
federatedToken = yield core.getIDToken(audience);
if (!!federatedToken) {
if (environment != "azurecloud")
throw new Error(`Your current environment - "${environment}" is not supported for OIDC login.`);
}
else {
throw new Error("Could not get ID token for authentication.");
}
let [issuer, subjectClaim] = yield jwtParser(federatedToken);
console.log("Federated token details: \n issuer- " + issuer + " \n subject claim - " + subjectClaim);
}
// Attempting Az cli login
if (environment == "azurestack") {
if (!resourceManagerEndpointUrl) {
throw new Error("resourceManagerEndpointUrl is a required parameter when environment is defined.");
}
console.log(`Unregistering cloud: "${environment}" first if it exists`);
try {
yield executeAzCliCommand(`cloud set -n AzureCloud`, true);
yield executeAzCliCommand(`cloud unregister -n "${environment}"`, false);
}
catch (error) {
console.log(`Ignore cloud not registered error: "${error}"`);
}
console.log(`Registering cloud: "${environment}" with ARM endpoint: "${resourceManagerEndpointUrl}"`);
try {
let baseUri = resourceManagerEndpointUrl;
if (baseUri.endsWith('/')) {
baseUri = baseUri.substring(0, baseUri.length - 1); // need to remove trailing / from resourceManagerEndpointUrl to correctly derive suffixes below
}
let suffixKeyvault = ".vault" + baseUri.substring(baseUri.indexOf('.')); // keyvault suffix starts with .
let suffixStorage = baseUri.substring(baseUri.indexOf('.') + 1); // storage suffix starts without .
let profileVersion = "2019-03-01-hybrid";
yield executeAzCliCommand(`cloud register -n "${environment}" --endpoint-resource-manager "${resourceManagerEndpointUrl}" --suffix-keyvault-dns "${suffixKeyvault}" --suffix-storage-endpoint "${suffixStorage}" --profile "${profileVersion}"`, false);
}
catch (error) {
core.error(`Error while trying to register cloud "${environment}": "${error}"`);
}
console.log(`Done registering cloud: "${environment}"`);
}
yield executeAzCliCommand(`cloud set -n "${environment}"`, false);
console.log(`Done setting cloud: "${environment}"`);
// Attempting Az cli login
var commonArgs = ["--service-principal",
"-u", servicePrincipalId,
"--tenant", tenantId
];
if (allowNoSubscriptionsLogin) {
commonArgs = commonArgs.concat("--allow-no-subscriptions");
}
if (enableOIDC) {
commonArgs = commonArgs.concat("--federated-token", federatedToken);
}
else {
commonArgs = commonArgs.concat("-p", servicePrincipalKey);
}
yield executeAzCliCommand(`login`, true, {}, commonArgs);
if (!allowNoSubscriptionsLogin) {
var args = [
"--subscription",
subscriptionId
];
yield executeAzCliCommand(`account set`, true, {}, args);
}
isAzCLISuccess = true;
if (enableAzPSSession) {
// Attempting Az PS login
console.log(`Running Azure PS Login`);
var spnlogin;
spnlogin = new ServicePrincipalLogin_1.ServicePrincipalLogin(servicePrincipalId, servicePrincipalKey, federatedToken, tenantId, subscriptionId, allowNoSubscriptionsLogin, environment, resourceManagerEndpointUrl);
yield spnlogin.initialize();
yield spnlogin.login();
}
console.log("Login successful.");
}
catch (error) {
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);
}
});
}
function executeAzCliCommand(command, silent, execOptions = {}, args = []) {
return __awaiter(this, void 0, void 0, function* () {
execOptions.silent = !!silent;
try {
yield exec.exec(`"${azPath}" ${command}`, args, execOptions);
}
catch (error) {
core.error("Az-CLI" + error);
}
});
}
function jwtParser(federatedToken) {
return __awaiter(this, void 0, void 0, function* () {
let tokenPayload = federatedToken.split('.')[1];
let bufferObj = Buffer.from(tokenPayload, "base64");
let decodedPayload = JSON.parse(bufferObj.toString("utf8"));
return [decodedPayload['iss'], decodedPayload['sub']];
});
}
main();