mirror of
https://github.com/azure/login.git
synced 2026-03-15 09:20:56 -04:00
resolve merge conflict attempt #1.
This commit is contained in:
10
.github/ISSUE_TEMPLATE/bug-report---feature-request.md
vendored
Normal file
10
.github/ISSUE_TEMPLATE/bug-report---feature-request.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Bug Report / Feature Request
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: need-to-triage
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
4
.github/issue-label-bot.yaml
vendored
Normal file
4
.github/issue-label-bot.yaml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
label-alias:
|
||||
bug: 'bug'
|
||||
feature_request: 'enhancement'
|
||||
question: 'question'
|
||||
52
.github/workflows/codeql.yml
vendored
Normal file
52
.github/workflows/codeql.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
name: "Code scanning - action"
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '0 19 * * 0'
|
||||
|
||||
jobs:
|
||||
CodeQL-Build:
|
||||
|
||||
# CodeQL runs on ubuntu-latest and windows-latest
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
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@v1
|
||||
# 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)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
|
||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
162
README.md
162
README.md
@@ -159,3 +159,165 @@ provided by the bot. You will only need to do this once across all repos using o
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
|
||||
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
||||
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
# GitHub Actions for deploying to Azure
|
||||
|
||||
## Automate your GitHub workflows using Azure Actions
|
||||
|
||||
[GitHub Actions](https://help.github.com/en/articles/about-github-actions) gives you the flexibility to build an automated software development lifecycle workflow.
|
||||
|
||||
With [GitHub Actions for Azure](https://github.com/Azure/actions/) you can create workflows that you can set up in your repository to build, test, package, release and **deploy** to Azure.
|
||||
|
||||
NOTE: you must have write permissions to the repository in question. If you're using a sample repository from Microsoft, be sure to first fork the repository to your own GitHub account.
|
||||
|
||||
Get started today with a [free Azure account](https://azure.com/free/open-source).
|
||||
|
||||
# GitHub Action for Azure Login
|
||||
|
||||
With the Azure login Action, you can automate your workflow to do an Azure login using [Azure service principal](https://docs.microsoft.com/azure/active-directory/develop/app-objects-and-service-principals) and run Azure CLI and Azure PowerShell scripts.
|
||||
|
||||
By default, the action only logs in with the Azure CLI (using the `az login` command). To log in with the Az PowerShell module, set `enable-AzPSSession` to true. To login to Azure tenants without any subscriptions, set the optional parameter `allow-no-subscriptions` to true.
|
||||
|
||||
This repository contains GitHub Action for [Azure Login](https://github.com/Azure/login/blob/master/action.yml).
|
||||
|
||||
## Sample workflow that uses Azure login action to run az cli
|
||||
|
||||
```yaml
|
||||
# File: .github/workflows/workflow.yml
|
||||
|
||||
on: [push]
|
||||
|
||||
name: AzureLoginSample
|
||||
|
||||
jobs:
|
||||
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
|
||||
- run: |
|
||||
az webapp list --query "[?state=='Running']"
|
||||
```
|
||||
|
||||
## Sample workflow that uses Azure login action to run Azure PowerShell
|
||||
|
||||
```yaml
|
||||
# File: .github/workflows/workflow.yml
|
||||
|
||||
on: [push]
|
||||
|
||||
name: AzurePowerShellSample
|
||||
|
||||
jobs:
|
||||
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Login via Az module
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{secrets.AZURE_CREDENTIALS}}
|
||||
enable-AzPSSession: true
|
||||
|
||||
- name: Run Az CLI script
|
||||
run: |
|
||||
az webapp list --query "[?state=='Running']"
|
||||
|
||||
- name: Run Azure PowerShell script
|
||||
uses: azure/powershell@v1
|
||||
with:
|
||||
azPSVersion: '3.1.0'
|
||||
inlineScript: |
|
||||
Get-AzVM -ResourceGroupName "ActionsDemo"
|
||||
```
|
||||
|
||||
Refer to the [Azure PowerShell](https://github.com/azure/powershell) Github action to run your Azure PowerShell scripts.
|
||||
|
||||
## Configure deployment credentials:
|
||||
|
||||
The previous sample workflows depend on a [secrets](https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets) named `AZURE_CREDENTIALS` in your repository. The value of this secret is expected to be a JSON object that represents a service principal (an identifer for an application or process) that authenticates the workflow with Azure.
|
||||
|
||||
To function correctly, this service principal must be assigned the [Contributor]((https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#contributor)) role for the web app or the resource group that contains the web app.
|
||||
|
||||
The following steps describe how to create the service principal, assign the role, and create a secret in your repository with the resulting credentials.
|
||||
|
||||
1. Open the Azure Cloud Shell at [https://shell.azure.com](https://shell.azure.com). You can alternately use the [Azure CLI](https://docs.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest) if you've installed it locally. (For more information on Cloud Shell, see the [Cloud Shell Overview](https://docs.microsoft.com/azure/cloud-shell/overview).)
|
||||
|
||||
2. Use the [az ad sp create-for-rbac](https://docs.microsoft.com/cli/azure/ad/sp?view=azure-cli-latest#az_ad_sp_create_for_rbac) command to create a service principal and assign a Contributor role:
|
||||
|
||||
```azurecli
|
||||
az ad sp create-for-rbac --name "{sp-name}" --sdk-auth --role contributor \
|
||||
--scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Web/sites/{app-name}
|
||||
```
|
||||
|
||||
Replace the following:
|
||||
* `{sp-name}` with a suitable name for your service principal, such as the name of the app itself. The name must be unique within your organization.
|
||||
* `{subscription-id}` with the subscription you want to use
|
||||
* `{resource-group}` the resource group containing the web app.
|
||||
* `{app-name}` with the name of the web app.
|
||||
|
||||
This command invokes Azure Active Directory (via the `ad` part of the command) to create a service principal (via `sp`) specifically for [Role-Based Access Control (RBAC)](https://docs.microsoft.com/azure/role-based-access-control/overview) (via `create-for-rbac`).
|
||||
|
||||
The `--role` argument specifies the permissions to grant to the service principal at the specified `--scope`. In this case, you grant the built-in [Contributor](https://docs.microsoft.com/azure/role-based-access-control/built-in-roles#contributor) role at the scope of the web app in the specified resource group in the specified subscription.
|
||||
|
||||
If desired, you can omit the part of the scope starting with `/providers/...` to grant the service principal the Contributor role for the entire resource group:
|
||||
|
||||
```azurecli
|
||||
az ad sp create-for-rbac --name "{sp-name}" --sdk-auth --role contributor \
|
||||
--scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group}
|
||||
```
|
||||
|
||||
For security purposes, however, it's always preferable to grant permissions at the most restrictive scope possible.
|
||||
|
||||
3. When complete, the `az ad sp create-for-rbac` command displays JSON output in the following form (which is specified by the `--sdk-auth` argument):
|
||||
|
||||
```json
|
||||
{
|
||||
"clientId": "<GUID>",
|
||||
"clientSecret": "<GUID>",
|
||||
"subscriptionId": "<GUID>",
|
||||
"tenantId": "<GUID>",
|
||||
(...)
|
||||
}
|
||||
```
|
||||
|
||||
4. In your repository, use **Add secret** to create a new secret named `AZURE_CREDENTIALS` (as shown in the example workflow), or using whatever name is in your workflow file.
|
||||
|
||||
5. Paste the entire JSON object produced by the `az ad sp create-for-rbac` command as the secret value and save the secret.
|
||||
|
||||
NOTE: to manage service principals created with `az ad sp create-for-rbac`, visit the [Azure portal](https://portal.azure.com), navigate to your Azure Active Directory, then select **Manage** > **App registrations** on the left-hand menu. Your service principal should appear in the list. Select a principal to navigate to its properties. You can also manage role assignments using the [az role assignment](https://docs.microsoft.com/cli/azure/role/assignment?view=azure-cli-latest) command.
|
||||
|
||||
## Support for using `allow-no-subscriptions` flag with az login
|
||||
|
||||
Capability has been added to support access to tenants without subscriptions. This can be useful to run tenant level commands, such as `az ad`. The action accepts an optional parameter `allow-no-subscriptions` which is `false` by default.
|
||||
|
||||
```yaml
|
||||
# File: .github/workflows/workflow.yml
|
||||
|
||||
on: [push]
|
||||
|
||||
name: AzureLoginWithNoSubscriptions
|
||||
|
||||
jobs:
|
||||
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
allow-no-subscriptions: true
|
||||
```
|
||||
|
||||
# Contributing
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
|
||||
|
||||
When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.
|
||||
|
||||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
||||
|
||||
@@ -5,7 +5,7 @@ jest.mock('../../src/PowerShell/Utilities/PowerShellToolRunner');
|
||||
let spnlogin: ServicePrincipalLogin;
|
||||
|
||||
beforeAll(() => {
|
||||
spnlogin = new ServicePrincipalLogin("servicePrincipalID", "servicePrinicipalkey", "tenantId", "subscriptionId", null, null);
|
||||
spnlogin = new ServicePrincipalLogin("servicePrincipalID", "servicePrinicipalkey", "tenantId", "subscriptionId", false, null, null);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
25
__tests__/PowerShell/Utilities/ScriptBuilder.test.ts
Normal file
25
__tests__/PowerShell/Utilities/ScriptBuilder.test.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import ScriptBuilder from "../../../src/PowerShell/Utilities/ScriptBuilder";
|
||||
import Constants from "../../../src/PowerShell/Constants";
|
||||
|
||||
describe("Getting AzLogin PS script" , () => {
|
||||
const scheme = Constants.ServicePrincipal;
|
||||
let args: any = {
|
||||
servicePrincipalId: "service-principal-id",
|
||||
servicePrincipalKey: "service-principal-key",
|
||||
environment: "environment",
|
||||
scopeLevel: Constants.Subscription,
|
||||
subscriptionId: "subId",
|
||||
allowNoSubscriptionsLogin: true
|
||||
}
|
||||
|
||||
test("PS script should not set context while passing allowNoSubscriptionsLogin as true", () => {
|
||||
const loginScript = new ScriptBuilder().getAzPSLoginScript(scheme, "tenant-id", args);
|
||||
expect(loginScript.includes("Set-AzContext -SubscriptionId")).toBeFalsy();
|
||||
});
|
||||
|
||||
test("PS script should set context while passing allowNoSubscriptionsLogin as false", () => {
|
||||
args["allowNoSubscriptionsLogin"] = false;
|
||||
const loginScript = new ScriptBuilder().getAzPSLoginScript(scheme, "tenant-id", args);
|
||||
expect(loginScript.includes("Set-AzContext -SubscriptionId")).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -13,6 +13,10 @@ inputs:
|
||||
description: 'Name of the environment. Supported values are AzureStack, AzureCloud. Default being AzureCloud'
|
||||
required: false
|
||||
default: AzureCloud
|
||||
allow-no-subscriptions:
|
||||
description: 'Set this value to true to enable support for accessing tenants without subscriptions'
|
||||
required: false
|
||||
default: false
|
||||
branding:
|
||||
icon: 'login.svg'
|
||||
color: 'blue'
|
||||
|
||||
@@ -25,13 +25,21 @@ const PowerShellToolRunner_1 = __importDefault(require("./Utilities/PowerShellTo
|
||||
const ScriptBuilder_1 = __importDefault(require("./Utilities/ScriptBuilder"));
|
||||
const Constants_1 = __importDefault(require("./Constants"));
|
||||
class ServicePrincipalLogin {
|
||||
<<<<<<< HEAD
|
||||
constructor(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId, environment, resourceManagerEndpointUrl) {
|
||||
=======
|
||||
constructor(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId, allowNoSubscriptionsLogin) {
|
||||
>>>>>>> master
|
||||
this.servicePrincipalId = servicePrincipalId;
|
||||
this.servicePrincipalKey = servicePrincipalKey;
|
||||
this.tenantId = tenantId;
|
||||
this.subscriptionId = subscriptionId;
|
||||
<<<<<<< HEAD
|
||||
this.environment = environment;
|
||||
this.resourceManagerEndpointUrl = resourceManagerEndpointUrl;
|
||||
=======
|
||||
this.allowNoSubscriptionsLogin = allowNoSubscriptionsLogin;
|
||||
>>>>>>> master
|
||||
}
|
||||
initialize() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
@@ -55,9 +63,15 @@ class ServicePrincipalLogin {
|
||||
servicePrincipalId: this.servicePrincipalId,
|
||||
servicePrincipalKey: this.servicePrincipalKey,
|
||||
subscriptionId: this.subscriptionId,
|
||||
<<<<<<< HEAD
|
||||
environment: this.environment,
|
||||
scopeLevel: ServicePrincipalLogin.scopeLevel,
|
||||
resourceManagerEndpointUrl: this.resourceManagerEndpointUrl,
|
||||
=======
|
||||
environment: ServicePrincipalLogin.environment,
|
||||
scopeLevel: ServicePrincipalLogin.scopeLevel,
|
||||
allowNoSubscriptionsLogin: this.allowNoSubscriptionsLogin
|
||||
>>>>>>> master
|
||||
};
|
||||
const script = new ScriptBuilder_1.default().getAzPSLoginScript(ServicePrincipalLogin.scheme, this.tenantId, args);
|
||||
yield PowerShellToolRunner_1.default.init();
|
||||
|
||||
@@ -26,7 +26,7 @@ class ScriptBuilder {
|
||||
command += `Connect-AzAccount -ServicePrincipal -Tenant '${tenantId}' -Credential \
|
||||
(New-Object System.Management.Automation.PSCredential('${args.servicePrincipalId}',(ConvertTo-SecureString '${args.servicePrincipalKey.replace("'", "''")}' -AsPlainText -Force))) \
|
||||
-Environment '${args.environment}' | out-null;`;
|
||||
if (args.scopeLevel === Constants_1.default.Subscription) {
|
||||
if (args.scopeLevel === Constants_1.default.Subscription && !args.allowNoSubscriptionsLogin) {
|
||||
command += `Set-AzContext -SubscriptionId '${args.subscriptionId}' -TenantId '${tenantId}' | out-null;`;
|
||||
}
|
||||
}
|
||||
|
||||
83
lib/main.js
83
lib/main.js
@@ -1,4 +1,5 @@
|
||||
"use strict";
|
||||
<<<<<<< HEAD
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
@@ -18,6 +19,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
=======
|
||||
>>>>>>> master
|
||||
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) {
|
||||
@@ -27,9 +30,21 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
<<<<<<< HEAD
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const crypto = __importStar(require("crypto"));
|
||||
=======
|
||||
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"));
|
||||
>>>>>>> master
|
||||
const exec = __importStar(require("@actions/exec"));
|
||||
const io = __importStar(require("@actions/io"));
|
||||
const actions_secret_parser_1 = require("actions-secret-parser");
|
||||
@@ -42,21 +57,39 @@ function main() {
|
||||
try {
|
||||
// Set user agent variable
|
||||
var isAzCLISuccess = false;
|
||||
<<<<<<< HEAD
|
||||
let usrAgentRepo = crypto.createHash('sha256').update(`${process.env.GITHUB_REPOSITORY}`).digest('hex');
|
||||
=======
|
||||
let usrAgentRepo = `${process.env.GITHUB_REPOSITORY}`;
|
||||
>>>>>>> master
|
||||
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);
|
||||
<<<<<<< HEAD
|
||||
yield executeAzCliCommand("--version");
|
||||
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}`);
|
||||
>>>>>>> master
|
||||
let creds = core.getInput('creds', { required: true });
|
||||
let secrets = new actions_secret_parser_1.SecretParser(creds, actions_secret_parser_1.FormatType.JSON);
|
||||
let servicePrincipalId = secrets.getSecret("$.clientId", false);
|
||||
let servicePrincipalKey = secrets.getSecret("$.clientSecret", true);
|
||||
let tenantId = secrets.getSecret("$.tenantId", false);
|
||||
let subscriptionId = secrets.getSecret("$.subscriptionId", false);
|
||||
<<<<<<< HEAD
|
||||
let resourceManagerEndpointUrl = secrets.getSecret("$.resourceManagerEndpointUrl", false);
|
||||
let environment = core.getInput("environment").toLowerCase();
|
||||
const enableAzPSSession = core.getInput('enable-AzPSSession').toLowerCase() === "true";
|
||||
@@ -97,10 +130,46 @@ function main() {
|
||||
}
|
||||
yield executeAzCliCommand(`cloud set -n "${environment}"`, false);
|
||||
console.log(`Done setting cloud: "${environment}"`);
|
||||
=======
|
||||
const enableAzPSSession = core.getInput('enable-AzPSSession').toLowerCase() === "true";
|
||||
const allowNoSubscriptionsLogin = core.getInput('allow-no-subscriptions').toLowerCase() === "true";
|
||||
if (!servicePrincipalId || !servicePrincipalKey || !tenantId) {
|
||||
throw new Error("Not all values are present in the creds object. Ensure clientId, clientSecret and tenantId are supplied.");
|
||||
}
|
||||
if (!subscriptionId && !allowNoSubscriptionsLogin) {
|
||||
throw new Error("Not all values are present in the creds object. Ensure subscriptionId is supplied.");
|
||||
}
|
||||
// Attempting Az cli login
|
||||
if (allowNoSubscriptionsLogin) {
|
||||
let args = [
|
||||
"--allow-no-subscriptions",
|
||||
"--service-principal",
|
||||
"-u", servicePrincipalId,
|
||||
"-p", servicePrincipalKey,
|
||||
"--tenant", tenantId
|
||||
];
|
||||
yield executeAzCliCommand(`login`, true, {}, args);
|
||||
}
|
||||
else {
|
||||
let args = [
|
||||
"--service-principal",
|
||||
"-u", servicePrincipalId,
|
||||
"-p", servicePrincipalKey,
|
||||
"--tenant", tenantId
|
||||
];
|
||||
yield executeAzCliCommand(`login`, true, {}, args);
|
||||
args = [
|
||||
"--subscription",
|
||||
subscriptionId
|
||||
];
|
||||
yield executeAzCliCommand(`account set`, true, {}, args);
|
||||
}
|
||||
>>>>>>> master
|
||||
isAzCLISuccess = true;
|
||||
if (enableAzPSSession) {
|
||||
// Attempting Az PS login
|
||||
console.log(`Running Azure PS Login`);
|
||||
<<<<<<< HEAD
|
||||
const spnlogin = new ServicePrincipalLogin_1.ServicePrincipalLogin(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId, environment, resourceManagerEndpointUrl);
|
||||
yield spnlogin.initialize();
|
||||
yield spnlogin.login();
|
||||
@@ -110,6 +179,12 @@ function main() {
|
||||
yield executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`, true);
|
||||
yield executeAzCliCommand(`account set --subscription "${subscriptionId}"`, true);
|
||||
}
|
||||
=======
|
||||
const spnlogin = new ServicePrincipalLogin_1.ServicePrincipalLogin(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId, allowNoSubscriptionsLogin);
|
||||
yield spnlogin.initialize();
|
||||
yield spnlogin.login();
|
||||
}
|
||||
>>>>>>> master
|
||||
console.log("Login successful.");
|
||||
}
|
||||
catch (error) {
|
||||
@@ -128,10 +203,18 @@ function main() {
|
||||
}
|
||||
});
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
function executeAzCliCommand(command, silent) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
yield exec.exec(`"${azPath}" ${command}`, [], { silent: !!silent });
|
||||
=======
|
||||
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);
|
||||
>>>>>>> master
|
||||
}
|
||||
catch (error) {
|
||||
throw new Error(error);
|
||||
|
||||
14
package-lock.json
generated
14
package-lock.json
generated
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "login",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@actions/core": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.1.3.tgz",
|
||||
"integrity": "sha512-2BIib53Jh4Cfm+1XNuZYYGTeRo8yiWEAUMoliMh1qQGMaqTF4VUlhhcsBylTu4qWmUx45DrY0y0XskimAHSqhw=="
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.2.6.tgz",
|
||||
"integrity": "sha512-ZQYitnqiyBc3D+k7LsgSBmMDVkOVidaagDG7j3fOym77jNunWRuYx7VSHa9GNfFZh+zh61xsCjRj4JxMZlDqTA=="
|
||||
},
|
||||
"@actions/exec": {
|
||||
"version": "1.0.1",
|
||||
@@ -3331,9 +3331,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.15",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
|
||||
"version": "4.17.19",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
|
||||
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.memoize": {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"typescript": "^3.6.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.1.3",
|
||||
"@actions/core": "^1.2.6",
|
||||
"@actions/exec": "^1.0.1",
|
||||
"@actions/io": "^1.0.1",
|
||||
"actions-secret-parser": "^1.0.2"
|
||||
|
||||
@@ -14,14 +14,23 @@ export class ServicePrincipalLogin implements IAzurePowerShellSession {
|
||||
tenantId: string;
|
||||
subscriptionId: string;
|
||||
resourceManagerEndpointUrl: string;
|
||||
allowNoSubscriptionsLogin: boolean;
|
||||
|
||||
constructor(servicePrincipalId: string,
|
||||
servicePrincipalKey: string,
|
||||
tenantId: string,
|
||||
subscriptionId: string,
|
||||
allowNoSubscriptionsLogin: boolean,
|
||||
environment: string,
|
||||
resourceManagerEndpointUrl: string) {
|
||||
|
||||
constructor(servicePrincipalId: string, servicePrincipalKey: string, tenantId: string, subscriptionId: string, environment: string, resourceManagerEndpointUrl: string) {
|
||||
this.servicePrincipalId = servicePrincipalId;
|
||||
this.servicePrincipalKey = servicePrincipalKey;
|
||||
this.tenantId = tenantId;
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.environment = environment;
|
||||
this.resourceManagerEndpointUrl = resourceManagerEndpointUrl;
|
||||
this.allowNoSubscriptionsLogin = allowNoSubscriptionsLogin;
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
@@ -46,7 +55,8 @@ export class ServicePrincipalLogin implements IAzurePowerShellSession {
|
||||
subscriptionId: this.subscriptionId,
|
||||
environment: this.environment,
|
||||
scopeLevel: ServicePrincipalLogin.scopeLevel,
|
||||
resourceManagerEndpointUrl: this.resourceManagerEndpointUrl,
|
||||
allowNoSubscriptionsLogin: this.allowNoSubscriptionsLogin,
|
||||
resourceManagerEndpointUrl: this.resourceManagerEndpointUrl
|
||||
}
|
||||
const script: string = new ScriptBuilder().getAzPSLoginScript(ServicePrincipalLogin.scheme, this.tenantId, args);
|
||||
await PowerShellToolRunner.init();
|
||||
|
||||
@@ -15,7 +15,7 @@ export default class ScriptBuilder {
|
||||
command += `Connect-AzAccount -ServicePrincipal -Tenant '${tenantId}' -Credential \
|
||||
(New-Object System.Management.Automation.PSCredential('${args.servicePrincipalId}',(ConvertTo-SecureString '${args.servicePrincipalKey.replace("'", "''")}' -AsPlainText -Force))) \
|
||||
-Environment '${args.environment}' | out-null;`;
|
||||
if (args.scopeLevel === Constants.Subscription) {
|
||||
if (args.scopeLevel === Constants.Subscription && !args.allowNoSubscriptionsLogin) {
|
||||
command += `Set-AzContext -SubscriptionId '${args.subscriptionId}' -TenantId '${tenantId}' | out-null;`;
|
||||
}
|
||||
}
|
||||
|
||||
74
src/main.ts
74
src/main.ts
@@ -1,5 +1,4 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as crypto from "crypto";
|
||||
import * as exec from '@actions/exec';
|
||||
import * as io from '@actions/io';
|
||||
import { FormatType, SecretParser } from 'actions-secret-parser';
|
||||
@@ -13,7 +12,7 @@ async function main() {
|
||||
try {
|
||||
// Set user agent variable
|
||||
var isAzCLISuccess = false;
|
||||
let usrAgentRepo = crypto.createHash('sha256').update(`${process.env.GITHUB_REPOSITORY}`).digest('hex');
|
||||
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}`;
|
||||
@@ -21,9 +20,25 @@ async function main() {
|
||||
core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azurePSHostEnv);
|
||||
|
||||
azPath = await io.which("az", true);
|
||||
await executeAzCliCommand("--version");
|
||||
|
||||
let azureSupportedCloudName = new Set(["azureusgovernment", "azurechinacloud", "azuregermancloud","azurecloud","azurestack"]);
|
||||
let azureSupportedCloudName = new Set([
|
||||
"azureusgovernment",
|
||||
"azurechinacloud",
|
||||
"azuregermancloud",
|
||||
"azurecloud",
|
||||
"azurestack"]);
|
||||
|
||||
let output: string = "";
|
||||
const execOptions: any = {
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
output += data.toString();
|
||||
}
|
||||
}
|
||||
};
|
||||
await executeAzCliCommand("--version", true, execOptions);
|
||||
core.debug(`az cli version used:\n${output}`);
|
||||
|
||||
let creds = core.getInput('creds', { required: true });
|
||||
let secrets = new SecretParser(creds, FormatType.JSON);
|
||||
let servicePrincipalId = secrets.getSecret("$.clientId", false);
|
||||
@@ -33,12 +48,17 @@ async function main() {
|
||||
let resourceManagerEndpointUrl = secrets.getSecret("$.resourceManagerEndpointUrl", false);
|
||||
let environment = core.getInput("environment").toLowerCase();
|
||||
const enableAzPSSession = core.getInput('enable-AzPSSession').toLowerCase() === "true";
|
||||
const allowNoSubscriptionsLogin = core.getInput('allow-no-subscriptions').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.");
|
||||
if (!servicePrincipalId || !servicePrincipalKey || !tenantId) {
|
||||
throw new Error("Not all values are present in the creds object. Ensure clientId, clientSecret and tenantId are supplied.");
|
||||
}
|
||||
|
||||
if(!azureSupportedCloudName.has(environment)){
|
||||
if (!subscriptionId && !allowNoSubscriptionsLogin) {
|
||||
throw new Error("Not all values are present in the creds object. 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’");
|
||||
}
|
||||
|
||||
@@ -78,11 +98,44 @@ async function main() {
|
||||
await executeAzCliCommand(`cloud set -n "${environment}"`, false);
|
||||
console.log(`Done setting cloud: "${environment}"`);
|
||||
|
||||
// Attempting Az cli login
|
||||
if (allowNoSubscriptionsLogin) {
|
||||
let args = [
|
||||
"--allow-no-subscriptions",
|
||||
"--service-principal",
|
||||
"-u", servicePrincipalId,
|
||||
"-p", servicePrincipalKey,
|
||||
"--tenant", tenantId
|
||||
];
|
||||
await executeAzCliCommand(`login`, true, {}, args);
|
||||
}
|
||||
else {
|
||||
let args = [
|
||||
"--service-principal",
|
||||
"-u", servicePrincipalId,
|
||||
"-p", servicePrincipalKey,
|
||||
"--tenant", tenantId
|
||||
];
|
||||
await executeAzCliCommand(`login`, true, {}, args);
|
||||
args = [
|
||||
"--subscription",
|
||||
subscriptionId
|
||||
];
|
||||
await executeAzCliCommand(`account set`, true, {}, args);
|
||||
}
|
||||
|
||||
isAzCLISuccess = true;
|
||||
if (enableAzPSSession) {
|
||||
// Attempting Az PS login
|
||||
console.log(`Running Azure PS Login`);
|
||||
const spnlogin: ServicePrincipalLogin = new ServicePrincipalLogin(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId, environment, resourceManagerEndpointUrl);
|
||||
const spnlogin: ServicePrincipalLogin = new ServicePrincipalLogin(
|
||||
servicePrincipalId,
|
||||
servicePrincipalKey,
|
||||
tenantId,
|
||||
subscriptionId,
|
||||
allowNoSubscriptionsLogin,
|
||||
environment,
|
||||
resourceManagerEndpointUrl);
|
||||
await spnlogin.initialize();
|
||||
await spnlogin.login();
|
||||
}
|
||||
@@ -109,9 +162,10 @@ async function main() {
|
||||
}
|
||||
}
|
||||
|
||||
async function executeAzCliCommand(command: string, silent?: boolean) {
|
||||
async function executeAzCliCommand(command: string, silent?: boolean, execOptions: any = {}, args: any = []) {
|
||||
execOptions.silent = !!silent;
|
||||
try {
|
||||
await exec.exec(`"${azPath}" ${command}`, [], {silent: !!silent});
|
||||
await exec.exec(`"${azPath}" ${command}`, args, execOptions);
|
||||
}
|
||||
catch(error) {
|
||||
throw new Error(error);
|
||||
|
||||
Reference in New Issue
Block a user