From 45e5e991bf0fe0312c97e9c47d209319f8f66f75 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 23 Aug 2020 16:53:51 +0200 Subject: [PATCH 01/19] Updated 'secrets' url in the README Updated the URL regarding the 'secret' docs. The issue was opened here: https://github.com/Azure/login/issues/47. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5e5266e3..be40d565 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ Refer [Azure PowerShell](https://github.com/azure/powershell) Github action to r ## Configure deployment credentials: -For any credentials like Azure Service Principal, Publish Profile etc add them as [secrets](https://help.github.com/en/articles/virtual-environments-for-github-actions#creating-and-using-secrets-encrypted-variables) in the GitHub repository and then use them in the workflow. +For any credentials like Azure Service Principal, Publish Profile etc add them as [secrets](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets) in the GitHub repository and then use them in the workflow. The above example uses user-level credentials i.e., Azure Service Principal for deployment. From 604f0eb80b2bc530831e2561484b5bf493d4ebf3 Mon Sep 17 00:00:00 2001 From: Usha N Date: Wed, 26 Aug 2020 13:41:07 +0530 Subject: [PATCH 02/19] Update README.md --- README.md | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index be40d565..9109e730 100644 --- a/README.md +++ b/README.md @@ -86,8 +86,9 @@ For any credentials like Azure Service Principal, Publish Profile etc add them a The above example uses user-level credentials i.e., Azure Service Principal for deployment. Follow the steps to configure the secret: - * Define a new secret under your repository settings, Add secret menu - * Store the output of the below [az cli](https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest) command as the value of secret variable, for example 'AZURE_CREDENTIALS' + * Define a new secret variable under your repository **Settings** -> **Secrets** -> **New secret**. Provide a secret variable **Name**, for example 'AZURE_CREDENTIALS'. + * Run the below [az cli](https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest) command and Store the output as the **Value** of the secret variable + * Below *az ad* command scopes the service principal to a specific resource group *{resource-group}* within a specific Azure subscription *{subscription-id}* ```bash az ad sp create-for-rbac --name "myApp" --role contributor \ @@ -106,34 +107,18 @@ Follow the steps to configure the secret: (...) } +``` + * You can also further scope down the Azure Credentials to a specific Azure resource, for example - a Web App by specifying the path to the specic resource in the *--scopes* attribute. Below script is for scoping the credentials to a web app of name *{app-name}* +```bash + az ad sp create-for-rbac --name "myApp" --role contributor \ + --scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Web/sites/{app-name} \ + --sdk-auth + + # Replace {subscription-id}, {resource-group}, and {app-name} with the names of your subscription, resource group, and Azure Web App. ``` * Now in the workflow file in your branch: `.github/workflows/workflow.yml` replace the secret in Azure login action with your secret (Refer to the example above) -# Azure Login metadata file - -```yaml - -# action.yml - -# Login to Azure subscription -name: 'Azure Login' -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' -runs: - using: 'node12' - main: 'lib/main.js' -``` # Contributing From 7e173d1a149e25731edf6857f7e506328c7c1d05 Mon Sep 17 00:00:00 2001 From: Justin Hutchings Date: Tue, 22 Sep 2020 01:03:27 -0700 Subject: [PATCH 03/19] Add CodeQL security scanning (#35) --- .github/workflows/codeql.yml | 52 ++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..9771ca0f --- /dev/null +++ b/.github/workflows/codeql.yml @@ -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 From 5dbba71255e6f1ec32d91a1621a144d8b24f41a9 Mon Sep 17 00:00:00 2001 From: Max Held Date: Tue, 29 Sep 2020 14:17:06 +0200 Subject: [PATCH 04/19] fix typo (#58) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9109e730..ec249d54 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ Follow the steps to configure the secret: } ``` - * You can also further scope down the Azure Credentials to a specific Azure resource, for example - a Web App by specifying the path to the specic resource in the *--scopes* attribute. Below script is for scoping the credentials to a web app of name *{app-name}* + * You can also further scope down the Azure Credentials to a specific Azure resource, for example - a Web App by specifying the path to the specific resource in the *--scopes* attribute. Below script is for scoping the credentials to a web app of name *{app-name}* ```bash az ad sp create-for-rbac --name "myApp" --role contributor \ --scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Web/sites/{app-name} \ From 6fc8a38800cd4d22846e21a50282c361ff00552c Mon Sep 17 00:00:00 2001 From: Kraig Brockschmidt Date: Wed, 30 Sep 2020 03:55:49 +0000 Subject: [PATCH 05/19] Add explanation of az ad sp create-for-rbac (#57) * Add explanation of az ad sp create-for-rbac Fulfills an internal Microsoft request to explain what the command is doing. Also cleans up the readmd a little and add a note about forking a sample repository when applicable. * Add note on managing service principals * Update secrets link --- README.md | 274 +++++++++++++++++++++++++++--------------------------- 1 file changed, 139 insertions(+), 135 deletions(-) diff --git a/README.md b/README.md index ec249d54..012bb12f 100644 --- a/README.md +++ b/README.md @@ -1,135 +1,139 @@ -# 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. - -# 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/en-us/azure/active-directory/develop/app-objects-and-service-principals) and run Az CLI and Azure PowerShell scripts. - -By default, only az cli login will be done. In addition to az cli, you can login using Az module to run Azure PowerShell scripts by setting enable-AzPSSession to true. - -Get started today with a [free Azure account](https://azure.com/free/open-source)! - -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.1 - 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.1 - 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 [Azure PowerShell](https://github.com/azure/powershell) Github action to run your Azure PowerShell scripts. - -## Configure deployment credentials: - -For any credentials like Azure Service Principal, Publish Profile etc add them as [secrets](https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets) in the GitHub repository and then use them in the workflow. - -The above example uses user-level credentials i.e., Azure Service Principal for deployment. - -Follow the steps to configure the secret: - * Define a new secret variable under your repository **Settings** -> **Secrets** -> **New secret**. Provide a secret variable **Name**, for example 'AZURE_CREDENTIALS'. - * Run the below [az cli](https://docs.microsoft.com/en-us/cli/azure/?view=azure-cli-latest) command and Store the output as the **Value** of the secret variable - * Below *az ad* command scopes the service principal to a specific resource group *{resource-group}* within a specific Azure subscription *{subscription-id}* -```bash - - az ad sp create-for-rbac --name "myApp" --role contributor \ - --scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group} \ - --sdk-auth - - # Replace {subscription-id}, {resource-group} with the subscription, resource group details - - # The command should output a JSON object similar to this: - - { - "clientId": "", - "clientSecret": "", - "subscriptionId": "", - "tenantId": "", - (...) - } - -``` - * You can also further scope down the Azure Credentials to a specific Azure resource, for example - a Web App by specifying the path to the specific resource in the *--scopes* attribute. Below script is for scoping the credentials to a web app of name *{app-name}* -```bash - az ad sp create-for-rbac --name "myApp" --role contributor \ - --scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/Microsoft.Web/sites/{app-name} \ - --sdk-auth - - # Replace {subscription-id}, {resource-group}, and {app-name} with the names of your subscription, resource group, and Azure Web App. -``` - * Now in the workflow file in your branch: `.github/workflows/workflow.yml` replace the secret in Azure login action with your secret (Refer to the example above) - - - -# 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. +# 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. + +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.1 + 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.1 + 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 dp 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": "", + "clientSecret": "", + "subscriptionId": "", + "tenantId": "", + (...) + } + ``` + +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. + +# 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. From 756a6f0316b9e80247485ab760c30852157c5f84 Mon Sep 17 00:00:00 2001 From: Amruta Kawade <65217380+AmrutaKawade@users.noreply.github.com> Date: Tue, 6 Oct 2020 10:30:41 +0530 Subject: [PATCH 06/19] Create issue-label-bot.yaml --- .github/issue-label-bot.yaml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .github/issue-label-bot.yaml diff --git a/.github/issue-label-bot.yaml b/.github/issue-label-bot.yaml new file mode 100644 index 00000000..b6422262 --- /dev/null +++ b/.github/issue-label-bot.yaml @@ -0,0 +1,4 @@ +label-alias: + bug: 'bug' + feature_request: 'enhancement' + question: 'question' From 498ec10cdf402ce119986b92bccae06475b25911 Mon Sep 17 00:00:00 2001 From: aksm-ms <58936966+aksm-ms@users.noreply.github.com> Date: Mon, 12 Oct 2020 13:59:03 +0530 Subject: [PATCH 07/19] Bump lodash from 4.17.15 to 4.17.19 (#52) Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Amruta Kawade <65217380+AmrutaKawade@users.noreply.github.com> --- package-lock.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index fba1fab8..dcb71e67 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "login", - "version": "1.0.0", + "version": "1.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -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": { From 9eb3db5a71f6012ac726f3bcc148fcea8f40512e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2020 14:01:59 +0530 Subject: [PATCH 08/19] Bump @actions/core from 1.1.3 to 1.2.6 (#60) Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.1.3 to 1.2.6. - [Release notes](https://github.com/actions/toolkit/releases) - [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md) - [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Amruta Kawade <65217380+AmrutaKawade@users.noreply.github.com> --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index dcb71e67..ee35e7a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "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", diff --git a/package.json b/package.json index bb947665..570b58f1 100644 --- a/package.json +++ b/package.json @@ -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" From 8158dc484601acea367192618e402d310078aa28 Mon Sep 17 00:00:00 2001 From: aksm-ms <58936966+aksm-ms@users.noreply.github.com> Date: Wed, 21 Oct 2020 09:49:38 +0530 Subject: [PATCH 09/19] Update README.md (#72) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 012bb12f..367dba8e 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: azure/login@v1.1 + - uses: azure/login@v1 with: creds: ${{ secrets.AZURE_CREDENTIALS }} @@ -57,7 +57,7 @@ jobs: steps: - name: Login via Az module - uses: azure/login@v1.1 + uses: azure/login@v1 with: creds: ${{secrets.AZURE_CREDENTIALS}} enable-AzPSSession: true From f86425d665cd813a1017a69d1eca882d4714fb52 Mon Sep 17 00:00:00 2001 From: Usha N Date: Wed, 21 Oct 2020 10:25:56 +0530 Subject: [PATCH 10/19] Updating telemetry to remove Hashing of repo name (#66) * Updating telemetry to remove Hashing of repo name We have CELA sign off to log user name in telemetry instead of a Hash.. It will also help us map repo names with Azure subscriptions directly. * Update main.ts * adding lib/main.js * adding main.ts Co-authored-by: Ashish Ranjan Co-authored-by: aksm-ms <58936966+aksm-ms@users.noreply.github.com> --- lib/main.js | 3 +-- src/main.ts | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/main.js b/lib/main.js index 8aeed1bf..194af6a2 100644 --- a/lib/main.js +++ b/lib/main.js @@ -17,7 +17,6 @@ var __importStar = (this && this.__importStar) || function (mod) { }; Object.defineProperty(exports, "__esModule", { value: true }); const core = __importStar(require("@actions/core")); -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"); @@ -30,7 +29,7 @@ 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}`; diff --git a/src/main.ts b/src/main.ts index cbe0b20e..cd355f0e 100644 --- a/src/main.ts +++ b/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'; @@ -14,7 +13,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}`; @@ -69,4 +68,4 @@ async function executeAzCliCommand(command: string, silent?: boolean) { } } -main(); \ No newline at end of file +main(); From fa833a8f44f7f471445769c813ca87985840d52d Mon Sep 17 00:00:00 2001 From: Noel Date: Wed, 28 Oct 2020 21:59:51 -0700 Subject: [PATCH 11/19] fix typo (#75) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 367dba8e..3a6a92ea 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ The following steps describe how to create the service principal, assign the rol 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 dp 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: +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 \ From 481142a71d63ab15a2263c5d704006027370877b Mon Sep 17 00:00:00 2001 From: Ganeshrockz Date: Tue, 3 Nov 2020 13:49:13 +0530 Subject: [PATCH 12/19] Added no subscription support (#73) * Added no subscription support * Added L0s * added no subcriptions login support * test changes Co-authored-by: Ganesh S Co-authored-by: aksm-ms <58936966+aksm-ms@users.noreply.github.com> --- .../PowerShell/ServicePrinicipalLogin.test.ts | 2 +- .../Utilities/ScriptBuilder.test.ts | 25 +++++++++++++++++++ action.yml | 4 +++ src/PowerShell/ServicePrincipalLogin.ts | 11 ++++++-- src/PowerShell/Utilities/ScriptBuilder.ts | 2 +- src/main.ts | 21 ++++++++++++---- 6 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 __tests__/PowerShell/Utilities/ScriptBuilder.test.ts diff --git a/__tests__/PowerShell/ServicePrinicipalLogin.test.ts b/__tests__/PowerShell/ServicePrinicipalLogin.test.ts index f8fdbb24..ffd59881 100644 --- a/__tests__/PowerShell/ServicePrinicipalLogin.test.ts +++ b/__tests__/PowerShell/ServicePrinicipalLogin.test.ts @@ -5,7 +5,7 @@ jest.mock('../../src/PowerShell/Utilities/PowerShellToolRunner'); let spnlogin: ServicePrincipalLogin; beforeAll(() => { - spnlogin = new ServicePrincipalLogin("servicePrincipalID", "servicePrinicipalkey", "tenantId", "subscriptionId"); + spnlogin = new ServicePrincipalLogin("servicePrincipalID", "servicePrinicipalkey", "tenantId", "subscriptionId", false); }); afterEach(() => { diff --git a/__tests__/PowerShell/Utilities/ScriptBuilder.test.ts b/__tests__/PowerShell/Utilities/ScriptBuilder.test.ts new file mode 100644 index 00000000..291cbd04 --- /dev/null +++ b/__tests__/PowerShell/Utilities/ScriptBuilder.test.ts @@ -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(); + }); +}); \ No newline at end of file diff --git a/action.yml b/action.yml index c166d10e..e7bd4f63 100644 --- a/action.yml +++ b/action.yml @@ -9,6 +9,10 @@ inputs: description: 'Set this value to true to enable Azure PowerShell Login in addition to Az CLI login' required: false default: false + 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' diff --git a/src/PowerShell/ServicePrincipalLogin.ts b/src/PowerShell/ServicePrincipalLogin.ts index 8aa293a4..580bff56 100644 --- a/src/PowerShell/ServicePrincipalLogin.ts +++ b/src/PowerShell/ServicePrincipalLogin.ts @@ -13,12 +13,18 @@ export class ServicePrincipalLogin implements IAzurePowerShellSession { servicePrincipalKey: string; tenantId: string; subscriptionId: string; + allowNoSubscriptionsLogin: boolean; - constructor(servicePrincipalId: string, servicePrincipalKey: string, tenantId: string, subscriptionId: string) { + constructor(servicePrincipalId: string, + servicePrincipalKey: string, + tenantId: string, + subscriptionId: string, + allowNoSubscriptionsLogin: boolean) { this.servicePrincipalId = servicePrincipalId; this.servicePrincipalKey = servicePrincipalKey; this.tenantId = tenantId; this.subscriptionId = subscriptionId; + this.allowNoSubscriptionsLogin = allowNoSubscriptionsLogin; } async initialize() { @@ -42,7 +48,8 @@ export class ServicePrincipalLogin implements IAzurePowerShellSession { servicePrincipalKey: this.servicePrincipalKey, subscriptionId: this.subscriptionId, environment: ServicePrincipalLogin.environment, - scopeLevel: ServicePrincipalLogin.scopeLevel + scopeLevel: ServicePrincipalLogin.scopeLevel, + allowNoSubscriptionsLogin: this.allowNoSubscriptionsLogin } const script: string = new ScriptBuilder().getAzPSLoginScript(ServicePrincipalLogin.scheme, this.tenantId, args); await PowerShellToolRunner.init(); diff --git a/src/PowerShell/Utilities/ScriptBuilder.ts b/src/PowerShell/Utilities/ScriptBuilder.ts index d43060e8..9f383891 100644 --- a/src/PowerShell/Utilities/ScriptBuilder.ts +++ b/src/PowerShell/Utilities/ScriptBuilder.ts @@ -12,7 +12,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;`; } } diff --git a/src/main.ts b/src/main.ts index cd355f0e..572c352c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -30,17 +30,28 @@ async function main() { 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."); + 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 - await executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`, true); - await executeAzCliCommand(`account set --subscription "${subscriptionId}"`, true); + if (allowNoSubscriptionsLogin) { + await executeAzCliCommand(`login --allow-no-subscriptions --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`, true); + } + else { + 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); + const spnlogin: ServicePrincipalLogin = new ServicePrincipalLogin(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId, allowNoSubscriptionsLogin); await spnlogin.initialize(); await spnlogin.login(); } From 3ca410cd24bd40dd27043e27ec31577a85a3c9c2 Mon Sep 17 00:00:00 2001 From: aksm-ms Date: Tue, 3 Nov 2020 14:14:40 +0530 Subject: [PATCH 13/19] adding lib --- lib/PowerShell/ServicePrincipalLogin.js | 6 +- lib/PowerShell/Utilities/ScriptBuilder.js | 2 +- lib/main.js | 187 ++++++++++++---------- 3 files changed, 103 insertions(+), 92 deletions(-) diff --git a/lib/PowerShell/ServicePrincipalLogin.js b/lib/PowerShell/ServicePrincipalLogin.js index 7a4be40b..519b0d2c 100644 --- a/lib/PowerShell/ServicePrincipalLogin.js +++ b/lib/PowerShell/ServicePrincipalLogin.js @@ -25,11 +25,12 @@ const PowerShellToolRunner_1 = __importDefault(require("./Utilities/PowerShellTo const ScriptBuilder_1 = __importDefault(require("./Utilities/ScriptBuilder")); const Constants_1 = __importDefault(require("./Constants")); class ServicePrincipalLogin { - constructor(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId) { + constructor(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId, allowNoSubscriptionsLogin) { this.servicePrincipalId = servicePrincipalId; this.servicePrincipalKey = servicePrincipalKey; this.tenantId = tenantId; this.subscriptionId = subscriptionId; + this.allowNoSubscriptionsLogin = allowNoSubscriptionsLogin; } initialize() { return __awaiter(this, void 0, void 0, function* () { @@ -54,7 +55,8 @@ class ServicePrincipalLogin { servicePrincipalKey: this.servicePrincipalKey, subscriptionId: this.subscriptionId, environment: ServicePrincipalLogin.environment, - scopeLevel: ServicePrincipalLogin.scopeLevel + scopeLevel: ServicePrincipalLogin.scopeLevel, + allowNoSubscriptionsLogin: this.allowNoSubscriptionsLogin }; const script = new ScriptBuilder_1.default().getAzPSLoginScript(ServicePrincipalLogin.scheme, this.tenantId, args); yield PowerShellToolRunner_1.default.init(); diff --git a/lib/PowerShell/Utilities/ScriptBuilder.js b/lib/PowerShell/Utilities/ScriptBuilder.js index 113f8f35..30cb4421 100644 --- a/lib/PowerShell/Utilities/ScriptBuilder.js +++ b/lib/PowerShell/Utilities/ScriptBuilder.js @@ -23,7 +23,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;`; } } diff --git a/lib/main.js b/lib/main.js index 194af6a2..eb708357 100644 --- a/lib/main.js +++ b/lib/main.js @@ -1,89 +1,98 @@ -"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); - yield executeAzCliCommand("--version"); - 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); - 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) { - 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) { - return __awaiter(this, void 0, void 0, function* () { - try { - yield exec.exec(`"${azPath}" ${command}`, [], { silent: !!silent }); - } - catch (error) { - throw new Error(error); - } - }); -} -main(); +"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); + yield executeAzCliCommand("--version"); + 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); + 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) { + yield executeAzCliCommand(`login --allow-no-subscriptions --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`, true); + } + else { + 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, allowNoSubscriptionsLogin); + 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) { + return __awaiter(this, void 0, void 0, function* () { + try { + yield exec.exec(`"${azPath}" ${command}`, [], { silent: !!silent }); + } + catch (error) { + throw new Error(error); + } + }); +} +main(); From 45f2ccef1145db3ca616b2295e3257d012aa2813 Mon Sep 17 00:00:00 2001 From: aksm-ms <58936966+aksm-ms@users.noreply.github.com> Date: Tue, 3 Nov 2020 17:12:56 +0530 Subject: [PATCH 14/19] adding az cli version debug logs (#76) --- lib/main.js | 19 ++++++++++++++++--- src/main.ts | 20 +++++++++++++++----- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/lib/main.js b/lib/main.js index eb708357..1527cd26 100644 --- a/lib/main.js +++ b/lib/main.js @@ -36,7 +36,17 @@ function main() { core.exportVariable('AZURE_HTTP_USER_AGENT', userAgentString); core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azurePSHostEnv); azPath = yield io.which("az", true); - yield executeAzCliCommand("--version"); + let output = ""; + const options = { + listeners: { + stdout: (data) => { + output += data.toString(); + } + } + }; + yield executeAzCliCommand("--version", true, options); + core.debug(`az cli version used:\n${output}`); + 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); @@ -45,6 +55,7 @@ function main() { let subscriptionId = secrets.getSecret("$.subscriptionId", false); 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."); } @@ -85,10 +96,12 @@ function main() { } }); } -function executeAzCliCommand(command, silent) { + +function executeAzCliCommand(command, silent, options = {}) { return __awaiter(this, void 0, void 0, function* () { + options.silent = !!silent; try { - yield exec.exec(`"${azPath}" ${command}`, [], { silent: !!silent }); + yield exec.exec(`"${azPath}" ${command}`, [], options); } catch (error) { throw new Error(error); diff --git a/src/main.ts b/src/main.ts index 572c352c..3288986e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -21,8 +21,17 @@ async function main() { core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azurePSHostEnv); azPath = await io.which("az", true); - await executeAzCliCommand("--version"); - + let output: string = ""; + const options: any = { + listeners: { + stdout: (data: Buffer) => { + output += data.toString(); + } + } + }; + await executeAzCliCommand("--version", true, options); + 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); @@ -70,13 +79,14 @@ async function main() { } } -async function executeAzCliCommand(command: string, silent?: boolean) { +async function executeAzCliCommand(command: string, silent?: boolean, options: any = {}) { + options.silent = !!silent; try { - await exec.exec(`"${azPath}" ${command}`, [], {silent: !!silent}); + await exec.exec(`"${azPath}" ${command}`, [], options); } catch(error) { throw new Error(error); } } -main(); +main(); \ No newline at end of file From 21f0955fe4af56636b8da4df927d69c4a92d528b Mon Sep 17 00:00:00 2001 From: Ganeshrockz Date: Thu, 5 Nov 2020 12:15:27 +0530 Subject: [PATCH 15/19] Updated readme for allow-no-subscriptions input support (#79) * Updated readme for no-subscriptions support * Minor changes * Updated readme --- README.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a6a92ea..000fa7ee 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Get started today with a [free Azure account](https://azure.com/free/open-source 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. +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). @@ -130,6 +130,29 @@ The following steps describe how to create the service principal, assign the rol 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. From e7b230d17ab65013bab5edb0ad1212ab4f98b589 Mon Sep 17 00:00:00 2001 From: aksm-ms <58936966+aksm-ms@users.noreply.github.com> Date: Fri, 6 Nov 2020 15:37:06 +0530 Subject: [PATCH 16/19] adding params to escape symbols in az cli (#80) * adding params to escape symbols in az cli * addressed review comments --- lib/main.js | 36 +++++++++++++++++++++++++----------- src/main.ts | 33 +++++++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/lib/main.js b/lib/main.js index 1527cd26..c3933519 100644 --- a/lib/main.js +++ b/lib/main.js @@ -37,16 +37,15 @@ function main() { core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azurePSHostEnv); azPath = yield io.which("az", true); let output = ""; - const options = { + const execOptions = { listeners: { stdout: (data) => { output += data.toString(); } } }; - yield executeAzCliCommand("--version", true, options); + yield executeAzCliCommand("--version", true, execOptions); core.debug(`az cli version used:\n${output}`); - 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); @@ -55,7 +54,6 @@ function main() { let subscriptionId = secrets.getSecret("$.subscriptionId", false); 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."); } @@ -64,11 +62,28 @@ function main() { } // Attempting Az cli login if (allowNoSubscriptionsLogin) { - yield executeAzCliCommand(`login --allow-no-subscriptions --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`, true); + let args = [ + "--allow-no-subscriptions", + "--service-principal", + "-u", servicePrincipalId, + "-p", servicePrincipalKey, + "--tenant", tenantId + ]; + yield executeAzCliCommand(`login`, true, {}, args); } else { - yield executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`, true); - yield executeAzCliCommand(`account set --subscription "${subscriptionId}"`, true); + let args = [ + "--service-principal", + "-u", servicePrincipalId, + "-p", servicePrincipalKey, + "--tenant", tenantId + ]; + yield executeAzCliCommand(`login`, true, {}, args); + args = [ + "--subscription", + subscriptionId + ]; + yield executeAzCliCommand(`account set`, true, {}, args); } isAzCLISuccess = true; if (enableAzPSSession) { @@ -96,12 +111,11 @@ function main() { } }); } - -function executeAzCliCommand(command, silent, options = {}) { +function executeAzCliCommand(command, silent, execOptions = {}, args = []) { return __awaiter(this, void 0, void 0, function* () { - options.silent = !!silent; + execOptions.silent = !!silent; try { - yield exec.exec(`"${azPath}" ${command}`, [], options); + yield exec.exec(`"${azPath}" ${command}`, args, execOptions); } catch (error) { throw new Error(error); diff --git a/src/main.ts b/src/main.ts index 3288986e..3fd4b03a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -22,14 +22,14 @@ async function main() { azPath = await io.which("az", true); let output: string = ""; - const options: any = { + const execOptions: any = { listeners: { stdout: (data: Buffer) => { output += data.toString(); } } }; - await executeAzCliCommand("--version", true, options); + await executeAzCliCommand("--version", true, execOptions); core.debug(`az cli version used:\n${output}`); let creds = core.getInput('creds', { required: true }); @@ -50,11 +50,28 @@ async function main() { // Attempting Az cli login if (allowNoSubscriptionsLogin) { - await executeAzCliCommand(`login --allow-no-subscriptions --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`, true); + let args = [ + "--allow-no-subscriptions", + "--service-principal", + "-u", servicePrincipalId, + "-p", servicePrincipalKey, + "--tenant", tenantId + ]; + await executeAzCliCommand(`login`, true, {}, args); } else { - await executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`, true); - await executeAzCliCommand(`account set --subscription "${subscriptionId}"`, true); + 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) { @@ -79,10 +96,10 @@ async function main() { } } -async function executeAzCliCommand(command: string, silent?: boolean, options: any = {}) { - options.silent = !!silent; +async function executeAzCliCommand(command: string, silent?: boolean, execOptions: any = {}, args: any = []) { + execOptions.silent = !!silent; try { - await exec.exec(`"${azPath}" ${command}`, [], options); + await exec.exec(`"${azPath}" ${command}`, args, execOptions); } catch(error) { throw new Error(error); From 14ff6a1af159d329c42139286446bb2396463b39 Mon Sep 17 00:00:00 2001 From: Amruta Kawade <65217380+AmrutaKawade@users.noreply.github.com> Date: Mon, 28 Dec 2020 14:44:16 +0530 Subject: [PATCH 17/19] Update issue templates (#92) --- .github/ISSUE_TEMPLATE/custom.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/custom.md diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md new file mode 100644 index 00000000..311fcc1a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/custom.md @@ -0,0 +1,10 @@ +--- +name: Custom issue template +about: Describe this issue template's purpose here. +title: '' +labels: need-to-triage +assignees: '' + +--- + + From 80b45a252f3b960e41a10e50c16e5c79121c78f4 Mon Sep 17 00:00:00 2001 From: Amruta Kawade <65217380+AmrutaKawade@users.noreply.github.com> Date: Mon, 28 Dec 2020 14:50:50 +0530 Subject: [PATCH 18/19] Update issue templates --- .github/ISSUE_TEMPLATE/bug-report---feature-request.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug-report---feature-request.md diff --git a/.github/ISSUE_TEMPLATE/bug-report---feature-request.md b/.github/ISSUE_TEMPLATE/bug-report---feature-request.md new file mode 100644 index 00000000..214d54b6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report---feature-request.md @@ -0,0 +1,10 @@ +--- +name: Bug Report / Feature Request +about: Create a report to help us improve +title: '' +labels: need-to-triage +assignees: '' + +--- + + From aa362ff93ff22a75fd3681ddea6a26eae2e881eb Mon Sep 17 00:00:00 2001 From: Amruta Kawade <65217380+AmrutaKawade@users.noreply.github.com> Date: Mon, 28 Dec 2020 14:51:43 +0530 Subject: [PATCH 19/19] Delete custom.md --- .github/ISSUE_TEMPLATE/custom.md | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/custom.md diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md deleted file mode 100644 index 311fcc1a..00000000 --- a/.github/ISSUE_TEMPLATE/custom.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Custom issue template -about: Describe this issue template's purpose here. -title: '' -labels: need-to-triage -assignees: '' - ---- - -