Compare commits

..

148 Commits

Author SHA1 Message Date
jiasli
f97334770a add audience 2023-06-02 15:21:52 +08:00
YanaXu
da2e80cd21 print token for check 2023-06-02 13:21:56 +08:00
YanaXu
b54e6e2f76 use another env 2023-06-01 19:22:29 +08:00
YanaXu
2da0d5b800 update checkout version 2023-06-01 19:12:50 +08:00
YanaXu
b15e3257a9 [Test] Add test cases for PR checks 2023-06-01 18:09:21 +08:00
Yan Xu
bed977350c Refactor Code for better reading (#326)
* refactor

* fix test case
2023-05-29 14:15:49 +08:00
Yan Xu
990b22f2bc Update .gitignore for ts project (#323) 2023-05-25 17:18:52 +08:00
Shiying Chen
a354f8d8e8 Merge pull request #322 from MoChilia/fix-readme
Fix format error
2023-05-25 10:20:17 +08:00
MoChilia
41a42cd279 update 2023-05-25 10:13:15 +08:00
Shiying Chen
ef30cd425f Merge pull request #321 from MoChilia/OIDC-sovereign-cloud
Support OIDC for sovereign clouds
2023-05-24 17:39:19 +08:00
Shiying Chen
6cb3cd651b Merge branch 'master' into OIDC-sovereign-cloud 2023-05-24 17:19:08 +08:00
MoChilia
ddfe2f4c73 update 2023-05-24 17:14:24 +08:00
MoChilia
b1db778a6a change error handling method 2023-05-24 16:44:24 +08:00
MoChilia
3a00f07ef2 update 2023-05-24 15:39:07 +08:00
Shiying Chen
ae34beef25 Update README.md 2023-05-24 15:26:52 +08:00
MoChilia
13cc38b514 enable OIDC for sovereign clouds 2023-05-24 14:32:30 +08:00
Shiying Chen
1fe46a2c7b Close the issue with label needs-author-feedback for 20 days without activity (#313)
* auto check n-a-f

* Update days-before-stale to 20

* Update defaultLabels.yml

* Update close-issue-message
2023-05-08 14:01:52 +08:00
Shiying Chen
db0f4c9c27 Update README.md 2023-04-18 13:19:10 +08:00
Usha N
28c2e2b810 Update README.md 2023-04-12 22:09:10 -05:00
dependabot[bot]
a93d25c485 Bump json5 from 2.2.1 to 2.2.3 (#287)
Bumps [json5](https://github.com/json5/json5) from 2.2.1 to 2.2.3.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v2.2.1...v2.2.3)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Balaga Gayatri <balaga-gayatri@github.com>
2023-01-13 18:06:51 +05:30
Johan Karlsson
5d3578bb81 Allow passwords to start with hyphen (#241)
Co-authored-by: Balaga Gayatri <balaga-gayatri@github.com>
2023-01-13 17:51:33 +05:30
Sai Ganesh
5425855167 Link for the github environment secrets is changed (#289) 2023-01-13 17:42:09 +05:30
Usha N
32bfcb11b1 Update README.md 2023-01-10 15:40:36 -06:00
Usha N
4b9ec184bd Added support for OIDC + Managed Identities 2023-01-10 15:33:58 -06:00
Balaga Gayatri
50f8249ba7 Update README.md 2022-12-26 17:28:04 +05:30
eiffel-fl
28576d9764 Add caught error to core.setFailed() message. (#243)
This will help user to diagnose their problems using Azure/login.

Signed-off-by: Francis Laniel <flaniel@linux.microsoft.com>

Signed-off-by: Francis Laniel <flaniel@linux.microsoft.com>
Co-authored-by: Balaga Gayatri <balaga-gayatri@github.com>
2022-12-19 16:45:48 +05:30
Christoph Hannebauer
fb7f28b20f Improved debug output (#272)
* Improved debug output

* Improved debig output in JS file

Change in JS file corresponding to the one in the TS file

Co-authored-by: Balaga Gayatri <balaga-gayatri@github.com>
2022-12-19 16:36:23 +05:30
Youssef Victor
e486cf5b9b Update README.md and enforce markdownlint (#260) 2022-12-19 16:16:28 +05:30
BALAGA-GAYATRI
96c02d96d3 fixed yaml syntax 2022-12-19 16:11:01 +05:30
BALAGA-GAYATRI
2402d47c47 Added setup node step in CI 2022-12-19 16:05:17 +05:30
BALAGA-GAYATRI
a8ef87c8c0 removing node_modules 2022-12-19 15:51:07 +05:30
BALAGA-GAYATRI
df710979c3 UPdated dev dependencies with latest versions 2022-12-19 15:48:51 +05:30
Christoph Hannebauer
7636f25e6b Typo and more precise explanation of subscription-id parameter (#271) 2022-12-19 15:11:40 +05:30
Balaga Gayatri
dc26b5279a fix version for codeql-action in CI (#273)
* Update CodeQL v2

* fix lib object

* updated package-lock

Co-authored-by: jbenaventem <jesus.benavente@gruposantander.com>
2022-11-16 17:12:14 +05:30
Youssef Victor
9f262f3412 Update pr-check to use Node 16 (#268) 2022-11-16 17:07:49 +05:30
dependabot[bot]
e3e9acc64c Bump minimatch from 3.0.4 to 3.1.2 (#270)
Bumps [minimatch](https://github.com/isaacs/minimatch) from 3.0.4 to 3.1.2.
- [Release notes](https://github.com/isaacs/minimatch/releases)
- [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2)

---
updated-dependencies:
- dependency-name: minimatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-15 21:29:02 +05:30
dependabot[bot]
ec00cae078 Bump jsdom, jest and jest-circus (#266)
Removes [jsdom](https://github.com/jsdom/jsdom). It's no longer used after updating ancestor dependencies [jsdom](https://github.com/jsdom/jsdom), [jest](https://github.com/facebook/jest/tree/HEAD/packages/jest) and [jest-circus](https://github.com/facebook/jest/tree/HEAD/packages/jest-circus). These dependencies need to be updated together.


Removes `jsdom`

Updates `jest` from 25.5.4 to 29.2.2
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.2.2/packages/jest)

Updates `jest-circus` from 25.5.4 to 29.2.2
- [Release notes](https://github.com/facebook/jest/releases)
- [Changelog](https://github.com/facebook/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/jest/commits/v29.2.2/packages/jest-circus)

---
updated-dependencies:
- dependency-name: jsdom
  dependency-type: indirect
- dependency-name: jest
  dependency-type: direct:development
- dependency-name: jest-circus
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-15 21:27:57 +05:30
dependabot[bot]
fe9a855b8d Bump @actions/core from 1.6.0 to 1.9.1 (#240)
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.6.0 to 1.9.1.
- [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)

---
updated-dependencies:
- dependency-name: "@actions/core"
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-07 10:24:10 +05:30
Balaga Gayatri
68184fbd5a [BUG FIX] Version pattern quickfix master (#244)
* Update Constants.ts

* Update Constants.js
2022-10-26 15:14:31 +05:30
Usha N
cc70402281 Update action.yml (#247) 2022-10-26 15:14:12 +05:30
Y. Luis
642a43caaa Format README command to allow copy (#251)
* Update README.md

* Update README.md
2022-10-10 18:19:35 +05:30
Balaga Gayatri
6453efca84 Rename integration-tests.yml to azure-login-integration-tests.yml 2022-07-11 15:14:41 +05:30
Balaga Gayatri
e6ca011ab7 Create integration-tests.yml 2022-07-11 15:14:11 +05:30
Balaga Gayatri
c4459aba85 Deleting this workflow as this is no longer used 2022-07-11 13:33:42 +05:30
Nathan Gelman
c09ca4f217 Fixed spelling error (#237) 2022-07-11 13:04:44 +05:30
Balaga Gayatri
4443ffd660 Update README.md 2022-07-11 12:54:08 +05:30
Balaga Gayatri
b4a959b8bd Update README.md 2022-06-22 12:42:23 +05:30
Balaga Gayatri
5d09f4d5ca Update README.md 2022-06-22 12:41:16 +05:30
Balaga Gayatri
14a755a4e2 Id token errormsg (#234)
* putting id-token generation in try catch block

* Updating node version in action.yml
2022-06-21 16:43:50 +05:30
Balaga Gayatri
11ff950770 Update azure-login-canary.yml 2022-06-14 12:22:53 +05:30
Balaga Gayatri
980d0f57a2 Added Canary tests related documentation and few more cases(#232) 2022-06-10 17:20:07 +05:30
Balaga Gayatri
819ac8d2a9 Update azure-login-canary.yml (#230) 2022-06-03 17:11:18 +05:30
Balaga Gayatri
63b39ef8c4 Create azure-login-canary.yml (#229) 2022-06-03 16:03:36 +05:30
Balaga Gayatri
e021afe0dc Handling warnings and adding OIDC promotion message (#221)
* Handling warnings and adding OIDC promotion message

* Implementing NIT suggestions
2022-05-02 19:46:30 +05:30
Balaga Gayatri
85f8f21203 Update README.md 2022-04-18 22:50:06 +05:30
Sean MacKay
827604025b Update ClientSecret in the example to not call itself a GUID (#208)
* Update ClientSecret in the example to not call itself a GUID

If manually crafting or verifying a Service Principal credential JSON object, it is helpful to know that only the `clientId` is formatted as a GUID, and the `clientSecret` is just an alphanumeric string.

* Update README.md

Co-authored-by: Balaga Gayatri <balaga-gayatri@github.com>
2022-04-11 19:45:44 +05:30
Sean MacKay
06f50cc138 Add critical information if manually creating SP Credential object (#209)
* Add critical information if manually creating SP Credential object

If you must manually create the credential JSON (for instance, the Service Principal was created and assigned but the output credential was not saved), finding the `clientId`, `clientSecret`, `subscriptionId` and `tenantId` in azure is possible, but the `resourceManagerEndpointUrl` is also required by this Action and was much harder to track down.

By explaining it is possible and including the value for the public azure cloud (the default use case) it will help others be able to use this Action with existing Service Principal's as well.

* Update README.md

Co-authored-by: Balaga Gayatri <balaga-gayatri@github.com>
2022-04-11 19:22:52 +05:30
dependabot[bot]
23801eadd7 Bump ansi-regex from 4.1.0 to 4.1.1 (#219)
Bumps [ansi-regex](https://github.com/chalk/ansi-regex) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/chalk/ansi-regex/releases)
- [Commits](https://github.com/chalk/ansi-regex/compare/v4.1.0...v4.1.1)

---
updated-dependencies:
- dependency-name: ansi-regex
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-11 19:06:51 +05:30
dependabot[bot]
8f2def4beb Bump minimist from 1.2.5 to 1.2.6 (#212)
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Balaga Gayatri <balaga-gayatri@github.com>
2022-04-11 18:59:52 +05:30
Balaga Gayatri
412f48d98e Update README.md 2022-04-11 18:07:56 +05:30
Balaga Gayatri
c02223cd62 Update README.md 2022-03-29 18:44:11 +05:30
Balaga Gayatri
84519181a8 Adding az installation requirement to login error response (#198)
* Update main.ts

* Update main.js
2022-01-19 22:50:55 +05:30
Balaga Gayatri
db989b3060 Delete .DS_Store 2021-12-16 21:51:49 +05:30
Dhiwakar Kusuma
276f50e2dc Update README.md (#189)
Updated Readme.md with App Registration instructions. Without the instructions new user will be lost with the instructions provided as none of the menus/options appear.
2021-12-13 23:14:29 +05:30
Balaga Gayatri
25454e5e2d printing token logs (#185) 2021-12-07 00:16:39 +05:30
Balaga Gayatri
0dd02392d7 Update README.md 2021-11-29 13:48:09 +05:30
Balaga Gayatri
aa88e1ccbd Update README.md 2021-11-29 12:35:23 +05:30
Balaga Gayatri
c8bf401503 Update README.md 2021-11-19 19:22:51 +05:30
Balaga Gayatri
37a47ac753 Update README.md (#173) 2021-11-17 12:48:23 +05:30
Balaga Gayatri
298eef0366 Updating samples and readme links (#172) 2021-11-15 17:27:52 +05:30
Balaga Gayatri
4799d94391 Adding federated token logs & optional audience parameter (#159)
* cherry pick changes

* added audience field option in input params

* added js

* removed extra spaces

* Adding logs to surface AZ-CLI and powershell errors (#171)

* removing token logs
2021-11-15 12:45:07 +05:30
Balaga Gayatri
bd43696425 Update README.md 2021-11-12 13:09:38 +05:30
Balaga Gayatri
3e6f6e7d1b Update README.md 2021-10-22 18:46:47 +05:30
Balaga Gayatri
38942de1a5 Update README.md 2021-10-22 18:42:53 +05:30
Balaga Gayatri
151a993723 Update README.md 2021-10-22 16:41:44 +05:30
Balaga Gayatri
fd4c9019e3 oidc changes for master (#158)
* oidc changes

* Update ServicePrinicipalLogin.test.ts

Co-authored-by: Kanika Pasrija <58769601+kanika1894@users.noreply.github.com>
2021-10-22 16:27:01 +05:30
Sean MacKay
6bc1b5ecb9 Update Readme to improve examples for hand crafting credentials (#140)
The clientSecret is not a GUID, and this being labelled as such caused confusion when I tried to manually add a client secret and was met with a SecretId which was a GUID and a SecretValue which was not a GUID. Using the SecretId GUID from the Azure UI would not work.

Also, resourceManagerEndpointUrl was required but not shown in any examples. 

Finally, the value for it was hard to determine, as using several azure cli commands did not display it.

Co-authored-by: Kanika Pasrija <58769601+kanika1894@users.noreply.github.com>
2021-09-20 15:00:25 +05:30
Derek Seroky
f8979b3393 docs(README): update the Azure Gov cloud example (#134)
Updates the Azure Gov cloud example to have valid YAML syntax and to increase consistency between examples.

Co-authored-by: Kanika Pasrija <58769601+kanika1894@users.noreply.github.com>
2021-09-15 12:49:50 +05:30
Kanika Pasrija
7f56506e21 Adding repository parameter
This is to pick from forked branch
2021-09-15 12:39:33 +05:30
dependabot[bot]
0cf07a0171 Bump path-parse from 1.0.6 to 1.0.7 (#128)
Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/jbgutierrez/path-parse/releases)
- [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7)

---
updated-dependencies:
- dependency-name: path-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Kanika Pasrija <58769601+kanika1894@users.noreply.github.com>
2021-09-13 17:04:06 +05:30
Balaga Gayatri
c9dca98403 Workflow for testing automation (#131)
* Create azure-login-pr-check.yml

* Update azure-login-pr-check.yml

* Update azure-login-pr-check.yml

* Update azure-login-pr-check.yml

* Update azure-login-pr-check.yml

* Update azure-login-pr-check.yml

* Update azure-login-pr-check.yml
2021-08-23 13:44:28 +05:30
Balaga Gayatri
177ab1c8df Rename bug-report---feature-request.md to bug-report-feature-request.md (#127) 2021-08-09 14:00:43 +05:30
Kanika Pasrija
5dc2a74a43 Create CODEOWNERS 2021-08-05 13:20:35 +05:30
dependabot[bot]
852ef9dc86 Bump lodash from 4.17.19 to 4.17.21 (#110)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.19 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.19...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Kanika Pasrija <58769601+kanika1894@users.noreply.github.com>
2021-06-23 12:50:49 +05:30
dependabot[bot]
92605228cd Bump ws from 7.2.3 to 7.5.0 (#124)
Bumps [ws](https://github.com/websockets/ws) from 7.2.3 to 7.5.0.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/7.2.3...7.5.0)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-23 12:47:38 +05:30
dependabot[bot]
49a928a08c Bump y18n from 4.0.0 to 4.0.1 (#101)
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-06-23 12:45:36 +05:30
Anat Balzam
b65105a723 Updating README with workaround for passing login arguments (#106)
* Add login with params workaround to README

* Added additional params line

Co-authored-by: Anat Balzam <anatbalzam@microsoft.com>
Co-authored-by: Balaga Gayatri <balaga-gayatri@github.com>
2021-06-21 17:49:36 +05:30
Ishita Chawla
a0110a77ec Create auto-triage-issues (#120)
* Create auto-triage-issues

* Update auto-triage-issues

* Update auto-triage-issues
2021-06-21 16:19:31 +05:30
Balaga Gayatri
ed5c47a214 Merge pull request #123 from Azure/users/balaga-gayatri/docs
Update README.md
2021-06-21 14:16:55 +05:30
Balaga Gayatri
0d0ee46f76 Update README.md 2021-06-21 11:08:59 +05:30
Balaga Gayatri
114a8ef99d Update README.md 2021-06-21 10:19:29 +05:30
Balaga Gayatri
a78820d812 Update README.md 2021-06-21 10:12:12 +05:30
Balaga Gayatri
490d296e28 Merge pull request #121 from Azure/users/balaga-gayatri/docs
Update README.md
2021-06-17 17:11:14 +05:30
Balaga Gayatri
1a2f091d94 Update README.md 2021-06-17 13:43:45 +05:30
Balaga Gayatri
c590679de3 Merge pull request #116 from Azure/users/balaga-gayatri/defaultlabels
Update defaultLabels.yml
2021-06-03 18:23:36 +05:30
Balaga Gayatri
b6d623b57e Update defaultLabels.yml 2021-06-03 18:20:15 +05:30
Balaga Gayatri
bbbe7da52a Update defaultLabels.yml 2021-06-03 17:18:30 +05:30
Balaga Gayatri
799fd51bc6 Merge pull request #114 from Azure/users/balaga-gayatri/defaultlabels
Create defaultLabels.yml
2021-06-02 12:15:31 +05:30
Balaga Gayatri
a9a1dcd2f7 Create defaultLabels.yml 2021-05-28 16:50:38 +05:30
Kanchan Verma
e7b36a5753 Merge pull request #99 from Azure/users/balaga-gayatri/developer-guidelines
Updated contribution section with the developer guidelines for actions
2021-03-31 10:17:12 +05:30
Balaga Gayatri
7f6ed87d4a Added dev guidance link to the contribution section in readme 2021-03-24 13:00:48 +05:30
Balaga Gayatri
c6b99d2720 Updated contribution section with the developer guidelines for azure actions. 2021-03-22 17:36:23 +05:30
reilem
5de298368f Improved SP creation docs (#96)
* Improved SP creation docs

* Update README.md

Co-authored-by: aksm-ms <58936966+aksm-ms@users.noreply.github.com>
2021-01-22 12:05:08 +05:30
garvitarai
1ab2192eba updating login action reference on ASH sample workflow (#97)
* updating login action reference on ASH sample workflow

* added links to the official microsoft docs tutorial
2021-01-22 10:51:13 +05:30
Arjun Gupta
80970a8c03 Merge pull request #93 from Azure/azuresovereigncloud
GitHub Actions Beta Preview for deploying to Azure Stack Hub
2020-12-31 11:16:51 +05:30
Arjun Gupta
2e97c69135 update readme 2020-12-30 23:11:51 +05:30
Arjun Gupta
a614f3cbd0 add description for all supported clouds 2020-12-30 22:40:50 +05:30
Arjun Gupta
3e306521aa add main.js 2020-12-30 22:14:08 +05:30
Arjun Gupta
56641ce573 remove az login else block. bad merge. + tidy up some code 2020-12-30 22:12:01 +05:30
Arjun Gupta
0d0c4a32af Merge branch 'master' of https://github.com/Azure/login into azuresovereigncloud 2020-12-30 18:30:26 +05:30
garvitarai
14b73ca9b5 Updating instructions to include Azure Stack Hub (#89)
* Updating instructions to include Azure Stack Hub

Added sample work flow for ASH and service principle instructions

* Updating based on PR feedback

- Added a description to environment parameter
- Updated instructions to say "required only for ash" for service principle instructions

Co-authored-by: Amruta Kawade <65217380+AmrutaKawade@users.noreply.github.com>
2020-12-29 14:36:06 +05:30
Arjun Gupta
2e72d699b0 Merge branch 'master' of https://github.com/Azure/login into azuresovereigncloud 2020-12-28 16:44:13 +05:30
Arjun Gupta
ff610a161c add js build files 2020-12-28 16:36:51 +05:30
Arjun Gupta
c72b9ad43b add node_modules to gitignore 2020-12-28 16:36:32 +05:30
Arjun Gupta
9584e50c92 resolve merge conflict attempt #1. 2020-12-28 16:29:52 +05:30
Zainudeen V K
d773655321 Updating azlogin readme (#91)
* Update README.md

* Update README.md

Co-authored-by: Amruta Kawade <65217380+AmrutaKawade@users.noreply.github.com>
2020-12-28 16:21:55 +05:30
Arjun Gupta
de36370b39 remove node modules 2020-12-28 16:08:43 +05:30
Arjun Gupta
bb5ee3d98d comment node_modules from gitignore 2020-12-28 16:07:59 +05:30
Amruta Kawade
aa362ff93f Delete custom.md 2020-12-28 14:51:43 +05:30
Amruta Kawade
80b45a252f Update issue templates 2020-12-28 14:50:50 +05:30
Amruta Kawade
14ff6a1af1 Update issue templates (#92) 2020-12-28 14:44:16 +05:30
Zainudeen V K
4440d80620 PR to include support for Sovereign cloud in azlogin action (#85)
* added support for Azure Gov cloud

* changes to Azure cloud

* az gov cloud changes

* changes as per PR comment

* chnages to include enum and valdiation

* changes to include validation

* changes

* deleted Enums.js

* changes to constant file

* added library of Consts.js

* changes from arary to set

* changes to environment input
2020-12-10 19:13:33 +05:30
aksm-ms
e7b230d17a adding params to escape symbols in az cli (#80)
* adding params to escape symbols in az cli

* addressed review comments
2020-11-06 15:37:06 +05:30
Ganeshrockz
21f0955fe4 Updated readme for allow-no-subscriptions input support (#79)
* Updated readme for no-subscriptions support

* Minor changes

* Updated readme
2020-11-05 12:15:27 +05:30
aksm-ms
45f2ccef11 adding az cli version debug logs (#76) 2020-11-03 17:12:56 +05:30
aksm-ms
3ca410cd24 adding lib 2020-11-03 14:14:40 +05:30
Ganeshrockz
481142a71d Added no subscription support (#73)
* Added no subscription support

* Added L0s

* added no subcriptions login support

* test changes

Co-authored-by: Ganesh S <ganeshs@CBREV-KESTUR.redmond.corp.microsoft.com>
Co-authored-by: aksm-ms <58936966+aksm-ms@users.noreply.github.com>
2020-11-03 13:49:13 +05:30
Noel
fa833a8f44 fix typo (#75) 2020-10-29 10:29:51 +05:30
Usha N
f86425d665 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 <asranja@github.com>
Co-authored-by: aksm-ms <58936966+aksm-ms@users.noreply.github.com>
2020-10-21 10:25:56 +05:30
aksm-ms
8158dc4846 Update README.md (#72) 2020-10-21 09:49:38 +05:30
dependabot[bot]
9eb3db5a71 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] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Amruta Kawade <65217380+AmrutaKawade@users.noreply.github.com>
2020-10-12 14:01:59 +05:30
aksm-ms
498ec10cdf 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] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Amruta Kawade <65217380+AmrutaKawade@users.noreply.github.com>
2020-10-12 13:59:03 +05:30
Amruta Kawade
c494a29b96 Merge pull request #63 from Azure/AmrutaKawade-patch-1
Create issue-label-bot.yaml
2020-10-06 13:48:27 +05:30
Amruta Kawade
756a6f0316 Create issue-label-bot.yaml 2020-10-06 10:30:41 +05:30
Kraig Brockschmidt
6fc8a38800 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
2020-09-30 09:25:49 +05:30
Max Held
5dbba71255 fix typo (#58) 2020-09-29 17:47:06 +05:30
Rakesh Kumar
807bb60301 Update build files and add node_modules (#54)
* update build files

* add node_modules
2020-09-23 12:15:33 +05:30
Usha N
8ea3fa2ba0 Merge pull request #53 from garvitarai/AzureStackSupport-Beta
Update README.md
2020-09-23 10:18:31 +05:30
garvitarai
0bf4fdc1f9 Update README.md 2020-09-22 21:32:53 -07:00
Justin Hutchings
7e173d1a14 Add CodeQL security scanning (#35) 2020-09-22 13:33:27 +05:30
garvitarai
ee83f1dbb6 Update README.md 2020-09-21 15:39:12 -07:00
Rakesh Kumar
513cdfa020 login action for azurestack (#41)
* login action for azurestack

* test update for azurestack

* review changes

* review changes v2

* review changes v3
2020-08-28 09:18:43 +05:30
Usha N
604f0eb80b Update README.md 2020-08-26 13:41:07 +05:30
Usha N
e9a9c1efa4 Merge pull request #48 from johnlokerse/patch-1
Updated 'secrets' url in the README
2020-08-25 16:09:32 +05:30
John
45e5e991bf 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.
2020-08-23 16:53:51 +02:00
aksm-ms
91da0d4635 Update ci.yml 2020-07-21 15:17:27 +05:30
aksm-ms
ed39f6a8e2 Update package.json 2020-06-29 10:55:58 +05:30
aksm-ms
b25b548bf8 escaping single quotes (#38) 2020-06-15 14:31:32 +05:30
34 changed files with 7070 additions and 4601 deletions

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
@kaverma @kanika1894 @BALAGA-GAYATRI @pulkitaggarwl

View 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
View File

@@ -0,0 +1,4 @@
label-alias:
bug: 'bug'
feature_request: 'enhancement'
question: 'question'

View File

@@ -0,0 +1,94 @@
#This workflow is used to test azure login action for CLI edge build. Visit, https://github.com/Azure/azure-cli#edge-builds for more details.
name: Run Azure Login Canary Test
on:
workflow_dispatch:
schedule:
- cron: ' 0 8 * * *'
permissions:
id-token: write
contents: read
jobs:
az-login-test:
runs-on: ubuntu-latest
steps:
- name : Check Az version before installing
run: az --version
- name: Installing Az CLI Edge build
run: |
cd ../..
CWD="$(pwd)"
python3 -m venv canary-venv
. canary-venv/bin/activate
echo "***********activated virual environment**********"
python3 -m pip install --upgrade pip
echo "***************started installing cli edge build******************"
pip3 install -q --upgrade --pre azure-cli --extra-index-url https://azurecliprod.blob.core.windows.net/edge --no-cache-dir --upgrade-strategy=eager
echo "***************installed cli Edge build*******************"
echo "$CWD/canary-venv/bin" >> $GITHUB_PATH
az --version
- name: Check out repository
uses: actions/checkout@v3
- name: 'Az CLI login with subscription'
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- run: |
az account show
- name: 'Az CLI login without subscription'
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
allow-no-subscriptions: true
- run: |
az account show
- name: 'Az CLI login with subscription OIDC'
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENTID }}
tenant-id: ${{ secrets.AZURE_TENANTID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTIONID }}
- run: |
az account show
- name: 'Az CLI login without subscription OIDC'
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENTID }}
tenant-id: ${{ secrets.AZURE_TENANTID }}
allow-no-subscriptions: true
- run: |
az account show
slack-post-result:
runs-on: ubuntu-latest
# continue-on-error: true
if: ${{ always() }}
needs: [az-login-test]
steps:
- name: Create slack post
id: slack_report
run: |
TITLE="Login action canary tests update - "
DATEVAR=`date "+%d/%m/%YT%H:%M:%S"`
TITLE="${TITLE}${DATEVAR}"
REPORT="${TITLE}\r\nLink to run - https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\r\n"
RUN_URL="https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
REPORT="${REPORT}\r\n"
if [ ${{needs.az-login-test.result}} == 'success' ]; then REPORT="${REPORT}\r\n|✅|<${RUN_URL}|az-login-test>"; else REPORT="${REPORT}\r\n|❌|<${RUN_URL}|az-login-test>"; fi
echo "::set-output name=report::$REPORT"
- name: Post to slack
shell: bash
run: curl -X POST -H 'Content-type:application/json' --data '{"blocks":[{"type":"section","text":{"type":"mrkdwn","text":"${{steps.slack_report.outputs.report}}"}}]}' https://hooks.slack.com/services/${{SECRETS.SLACK_CHANNEL_SECRET}}

View File

@@ -0,0 +1,129 @@
name: Run Azure Login Integration Tests
on:
workflow_dispatch:
schedule:
- cron: '0 */3 * * *'
permissions:
id-token: write
contents: write
jobs:
az-login-test-non-oidc:
runs-on: ubuntu-latest
# continue-on-error: true
steps:
- name: 'Az CLI login with subscription'
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- run: |
az account show
# az webapp list
- name: 'Az CLI login without subscription'
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
allow-no-subscriptions: true
- run: |
az account show
- name: 'Azure PowerShell login with subscription'
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
enable-AzPSSession: true
- uses: azure/powershell@v1
with:
inlineScript: "Get-AzContext"
azPSVersion: "latest"
- name: 'Azure PowerShell login without subscription'
uses: azure/login@v1
with:
creds: ${{secrets.AZURE_CREDENTIALS}}
enable-AzPSSession: true
allow-no-subscriptions: true
- uses: azure/powershell@v1
with:
inlineScript: "Get-AzContext"
azPSVersion: "latest"
az-login-test-oidc:
runs-on: ubuntu-latest
# continue-on-error: true
steps:
- name: 'Az CLI login with subscription'
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENTID }}
tenant-id: ${{ secrets.AZURE_TENANTID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTIONID }}
- run: |
az account show
# az webapp list
- name: 'Az CLI login without subscription'
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENTID }}
tenant-id: ${{ secrets.AZURE_TENANTID }}
allow-no-subscriptions: true
- run: |
az account show
- name: 'Azure PowerShell login with subscription'
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENTID }}
tenant-id: ${{ secrets.AZURE_TENANTID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTIONID }}
enable-AzPSSession: true
- uses: azure/powershell@v1
with:
inlineScript: "Get-AzContext"
azPSVersion: "latest"
- name: 'Azure PowerShell login without subscription'
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENTID }}
tenant-id: ${{ secrets.AZURE_TENANTID }}
enable-AzPSSession: true
allow-no-subscriptions: true
- uses: azure/powershell@v1
with:
inlineScript: "Get-AzContext"
azPSVersion: "latest"
slack-post-result:
runs-on: ubuntu-latest
# continue-on-error: true
if: ${{ always() }}
needs: [az-login-test-non-oidc, az-login-test-oidc]
steps:
- name: Create slack post
id: slack_report
run: |
TITLE="Login action OIDC flow tests update - "
DATEVAR=`date "+%d/%m/%YT%H:%M:%S"`
TITLE="${TITLE}${DATEVAR}"
REPORT="${TITLE}\r\nLink to run - https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\r\n"
RUN_URL="https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID"
REPORT="${REPORT}\r\n"
if [ ${{needs.az-login-test-non-oidc.result}} == 'success' ]; then REPORT="${REPORT}\r\n|✅|<${RUN_URL}|az-login-test-non-oidc>"; else REPORT="${REPORT}\r\n|❌|<${RUN_URL}|az-login-test-non-oidc>"; fi
if [ ${{needs.az-login-test-oidc.result}} == 'success' ]; then REPORT="${REPORT}\r\n|✅|<${RUN_URL}|az-login-test-oidc>"; else REPORT="${REPORT}\r\n|❌|<${RUN_URL}|az-login-test-oidc>"; fi
echo "::set-output name=report::$REPORT"
- name: Post to slack
shell: bash
run: curl -X POST -H 'Content-type:application/json' --data '{"blocks":[{"type":"section","text":{"type":"mrkdwn","text":"${{steps.slack_report.outputs.report}}"}}]}' https://hooks.slack.com/services/${{SECRETS.SLACK_CHANNEL_SECRET}}

View File

@@ -0,0 +1,359 @@
name: Azure Login Action Negative Test
on:
workflow_dispatch:
push:
permissions:
id-token: write
contents: read
jobs:
OSTest:
runs-on: macos-latest
environment: autotest
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v3.5.2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v1
with:
node-version: 16.x
- name: 'Validate build'
run: |
npm install
npm run build
- name: 'Run L0 tests'
id: run_test
continue-on-error: true
run: |
npm run test
- name: Check Last step failed
if: steps.run_test.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Login with creds
id: login_1
continue-on-error: true
uses: ./
with:
creds: ${{secrets.SP1}}
enable-AzPSSession: true
- name: Check Last step failed
if: steps.login_1.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Run Azure Cli
run: |
az account show
az group show --name GitHubActionGroup
az vm list
- name: Run Azure PowerShell
id: ps_1
continue-on-error: true
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
Get-AzContext | Format-List
Get-AzResourceGroup -Name GitHubActionGroup
Get-AzVM
- name: Check Last step failed
if: steps.ps_1.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Login with individual parameters
id: login_2
continue-on-error: true
uses: ./
with:
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
subscription-id: ${{ secrets.OIDC_SP2_SUBSCRIPTION_ID }}
allow-no-subscriptions: true
enable-AzPSSession: true
- name: Check Last step failed
if: steps.login_2.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Run Azure Cli again
run: |
az account show
- name: Run Azure PowerShell again
id: ps_2
continue-on-error: true
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
Get-AzContext | Format-List
- name: Check Last step failed
if: steps.ps_2.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
PermissionTest:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
environment: autotest
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v3.5.2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v1
with:
node-version: 16.x
- name: 'Validate build'
run: |
npm install
npm run build
- name: Login with individual parameters
uses: ./
with:
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
subscription-id: ${{ secrets.OIDC_SP2_SUBSCRIPTION_ID }}
allow-no-subscriptions: true
enable-AzPSSession: true
- name: Run Azure Cli
id: cli_3
continue-on-error: true
run: |
az account show
az group show --name GitHubActionGroup
az vm list
- name: Check Last step failed
if: steps.cli_3.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Run Azure PowerShell
id: ps_3
continue-on-error: true
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
Get-AzContext | Format-List
Get-AzResourceGroup -Name GitHubActionGroup
Get-AzVM
- name: Check Last step failed
if: steps.ps_3.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
ParameterTest:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
environment: autotest
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v3.5.2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v1
with:
node-version: 16.x
- name: 'Validate build'
run: |
npm install
npm run build
- name: Login with creds, missing parameters in creds
id: login_4
continue-on-error: true
uses: ./
with:
creds: ${{secrets.SP3_NO_Secret}}
enable-AzPSSession: true
- name: Check Last step failed
if: steps.login_4.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Login with creds, wrong keys
id: login_5
continue-on-error: true
uses: ./
with:
creds: ${{secrets.SP4_Wrong_Key}}
enable-AzPSSession: true
- name: Check Last step failed
if: steps.login_5.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Login with creds, no creds or individual parameters
id: login_6
continue-on-error: true
uses: ./
with:
enable-AzPSSession: true
- name: Check Last step failed
if: steps.login_6.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Login with individual parameters, only client-id, no tenant-id, subscription-id
id: login_7
continue-on-error: true
uses: ./
with:
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
allow-no-subscriptions: true
enable-AzPSSession: true
- name: Check Last step failed
if: steps.login_7.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Login with individual parameters, only tenant-id, subscription-id, no client-id
id: login_8
continue-on-error: true
uses: ./
with:
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
subscription-id: ${{ secrets.OIDC_SP2_SUBSCRIPTION_ID }}
allow-no-subscriptions: true
enable-AzPSSession: true
- name: Check Last step failed
if: steps.login_8.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Login with creds, disable ps session
uses: ./
with:
creds: ${{secrets.SP1}}
enable-AzPSSession: false
- name: Run Azure Cli
run: |
az account show
az group show --name GitHubActionGroup
az vm list
- name: Run Azure PowerShell
id: ps_8
continue-on-error: true
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
Get-AzContext | Format-List
Get-AzResourceGroup -Name GitHubActionGroup
Get-AzVM
- name: Check Last step failed
if: steps.ps_8.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Login with creds, wrong boolean value
uses: ./
with:
creds: ${{secrets.SP1}}
enable-AzPSSession: notboolean
- name: Run Azure Cli
run: |
az account show
az group show --name GitHubActionGroup
az vm list
- name: Run Azure PowerShell
id: ps_9
continue-on-error: true
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
Get-AzContext | Format-List
Get-AzResourceGroup -Name GitHubActionGroup
Get-AzVM
- name: Check Last step failed
if: steps.ps_9.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')
- name: Login with individual parameters, with a wrong audience
id: login_10
continue-on-error: true
uses: ./
with:
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
subscription-id: ${{ secrets.OIDC_SP2_SUBSCRIPTION_ID }}
audience: "https://github.com/actions"
allow-no-subscriptions: true
enable-AzPSSession: true
- name: Check Last step failed
if: steps.login_10.outcome == 'success'
uses: actions/github-script@v3
with:
script: |
core.setFailed('Last action should fail but not. Please check it.')

View File

@@ -0,0 +1,194 @@
name: Azure Login Action Positive Test
on:
workflow_dispatch:
push:
permissions:
id-token: write
contents: read
jobs:
BasicTest:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, self_linux, self_windows]
runs-on: ${{ matrix.os }}
environment: autotest
steps:
- name: TestGetToken
uses: actions/github-script@v3
with:
script: |
const tempToken = await core.getIDToken('api://AzureADTokenExchange')
console.log(tempToken.split('').join(' '))
- name: 'Checking out repo code'
uses: actions/checkout@v3.5.2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v1
with:
node-version: 16.x
- name: 'Validate build'
run: |
npm install
npm run build
- name: 'Run L0 tests'
run: |
npm run test
- name: Login with creds
uses: ./
with:
creds: ${{secrets.SP1}}
enable-AzPSSession: true
- name: Run Azure Cli
run: |
az account show
az group show --name GitHubActionGroup
az vm list
- name: Run Azure PowerShell
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
Get-AzContext | Format-List
Get-AzResourceGroup -Name GitHubActionGroup
Get-AzVM
- name: Login with individual parameters
uses: ./
with:
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
subscription-id: ${{ secrets.OIDC_SP2_SUBSCRIPTION_ID }}
allow-no-subscriptions: true
enable-AzPSSession: true
- name: Run Azure Cli again
run: |
az account show
- name: Run Azure PowerShell again
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
Get-AzContext | Format-List
ParameterTest:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
environment: autotest
steps:
- name: 'Checking out repo code'
uses: actions/checkout@v3.5.2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v1
with:
node-version: 16.x
- name: 'Validate build'
run: |
npm install
npm run build
- name: Login with both creds and individual parameters
uses: ./
with:
creds: ${{secrets.SP1}}
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
subscription-id: ${{ secrets.OIDC_SP2_SUBSCRIPTION_ID }}
enable-AzPSSession: true
- name: Run Azure Cli
run: |
az account show
az group show --name GitHubActionGroup
az vm list
- name: Run Azure PowerShell
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
Get-AzContext | Format-List
Get-AzResourceGroup -Name GitHubActionGroup
Get-AzVM
- name: Login with creds, disable ps session
uses: ./
with:
creds: ${{secrets.SP1}}
enable-AzPSSession: false
- name: Run Azure Cli
run: |
az account show
az group show --name GitHubActionGroup
az vm list
- name: Login with creds, wrong boolean value
uses: ./
with:
creds: ${{secrets.SP1}}
enable-AzPSSession: notboolean
- name: Run Azure Cli
run: |
az account show
az group show --name GitHubActionGroup
az vm list
- name: Login with creds, allow no subscription
uses: ./
with:
creds: ${{secrets.SP1}}
allow-no-subscriptions: true
enable-AzPSSession: true
- name: Run Azure Cli
run: |
az account show
az group show --name GitHubActionGroup
az vm list
- name: Run Azure PowerShell
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
Get-AzContext | Format-List
Get-AzResourceGroup -Name GitHubActionGroup
Get-AzVM
- name: Login with individual parameters, no subscription, allow no subscription
uses: ./
with:
client-id: ${{ secrets.OIDC_SP2_CLIENT_ID }}
tenant-id: ${{ secrets.OIDC_SP2_TENANT_ID }}
allow-no-subscriptions: true
enable-AzPSSession: true
- name: Run Azure Cli
run: |
az account show
- name: Run Azure PowerShell
uses: azure/powershell@v1.2.0
with:
azPSVersion: "latest"
inlineScript: |
Get-AzContext | Format-List

View File

@@ -0,0 +1,70 @@
name: pr-check
on:
pull_request_target:
branches:
- master
- 'releases/*'
jobs:
az-login-test:
environment: Automation test
runs-on: windows-latest
steps:
- name: Checkout from PR branch
uses: actions/checkout@v2
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.ref }}
# Using 16.x version as an example
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v1
with:
node-version: 16.x
- name: installing node_modules
run: npm install
- name: Build GitHub Action
run: npm run build
- name: 'Az CLI login with subscription'
uses: ./
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- run: |
az account show
# az webapp list
- name: 'Az CLI login without subscription'
uses: ./
with:
creds: ${{ secrets.AZURE_CREDENTIALS_NO_SUB }}
allow-no-subscriptions: true
- run: |
az account show
- name: 'Azure PowerShell login with subscription'
uses: ./
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
enable-AzPSSession: true
- uses: azure/powershell@v1
with:
inlineScript: "Get-AzContext"
azPSVersion: "latest"
- name: 'Azure PowerShell login without subscription'
uses: ./
with:
creds: ${{secrets.AZURE_CREDENTIALS_NO_SUB}}
enable-AzPSSession: true
allow-no-subscriptions: true
- uses: azure/powershell@v1
with:
inlineScript: "Get-AzContext"
azPSVersion: "latest"

View File

@@ -12,12 +12,17 @@ jobs:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
matrix: matrix:
os: [windows-latest, ubuntu-latest, macos-latest] os: [windows-latest, ubuntu-latest]
steps: steps:
- name: 'Checking out repo code' - name: 'Checking out repo code'
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set Node.js 16.x for GitHub Action
uses: actions/setup-node@v1
with:
node-version: 16.x
- name: 'Validate build' - name: 'Validate build'
run: | run: |
npm install npm install

52
.github/workflows/codeql.yml vendored Normal file
View 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@v2
# 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@v2
# 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@v2

48
.github/workflows/defaultLabels.yml vendored Normal file
View File

@@ -0,0 +1,48 @@
name: setting-default-labels
# Controls when the action will run.
on:
schedule:
- cron: "0 0/3 * * *"
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: actions/stale@v3
name: Setting issue as idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is idle because it has been open for 14 days with no activity.'
stale-issue-label: 'idle'
days-before-stale: 14
days-before-close: -1
operations-per-run: 100
exempt-issue-labels: 'backlog'
- uses: actions/stale@v3
name: Setting PR as idle
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-pr-message: 'This PR is idle because it has been open for 14 days with no activity.'
stale-pr-label: 'idle'
days-before-stale: 14
days-before-close: -1
operations-per-run: 100
- uses: actions/stale@v8
name: Close issue with no feedback for 20 days
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
close-issue-message: 'This issue has been labeled as `needs-author-feedback` for 20 days with no activity. We will close it for now. If you require additional assistance, please feel free to reopen it with the required information.'
days-before-stale: -1
days-before-close: 20
stale-issue-label: 'needs-author-feedback'
only-issue-labels: 'needs-author-feedback'
close-issue-reason: 'completed'
operations-per-run: 100

18
.github/workflows/markdownlint.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: Markdownlint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 16.x
- name: Run Markdownlint
run: |
npm i -g markdownlint-cli2
markdownlint-cli2 "**/*.md"

371
.gitignore vendored
View File

@@ -1,330 +1,99 @@
## Ignore Visual Studio temporary files, build results, and # Dependency directory
## files generated by popular Visual Studio add-ons. node_modules
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files # Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
*.suo # Logs
*.user logs
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log *.log
*.vspscc npm-debug.log*
*.vssscc yarn-debug.log*
.builds yarn-error.log*
*.pidb lerna-debug.log*
*.svclog
*.scc
# Chutzpah Test files # Diagnostic reports (https://nodejs.org/api/report.html)
_Chutzpah* report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Visual C++ cache files # Runtime data
ipch/ pids
*.aps *.pid
*.ncb *.seed
*.opendb *.pid.lock
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler # Directory for instrumented libs generated by jscoverage/JSCover
*.psess lib-cov
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files # Coverage directory used by tools like istanbul
*.e2e coverage
*.lcov
# TFS 2012 Local Workspace # nyc test coverage
$tf/ .nyc_output
# Guidance Automation Toolkit # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
*.gpState .grunt
# ReSharper is a .NET coding add-in # Bower dependency directory (https://bower.io/)
_ReSharper*/ bower_components
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in # node-waf configuration
.JustCode .lock-wscript
# TeamCity is a build add-in # Compiled binary addons (https://nodejs.org/api/addons.html)
_TeamCity* build/Release
# DotCover is a Code Coverage Tool # Dependency directories
*.dotCover jspm_packages/
# AxoCover is a Code Coverage Tool # TypeScript v1 declaration files
.axoCover/* typings/
!.axoCover/settings.json
# Visual Studio code coverage results # TypeScript cache
*.coverage *.tsbuildinfo
*.coveragexml
# NCrunch # Optional npm cache directory
_NCrunch_* .npm
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose # Optional eslint cache
*.mm.* .eslintcache
AutoTest.Net/
# Web workbench (sass) # Optional REPL history
.sass-cache/ .node_repl_history
# Installshield output folder # Output of 'npm pack'
[Ee]xpress/ *.tgz
# DocProject is a documentation generator add-in # Yarn Integrity file
DocProject/buildhelp/ .yarn-integrity
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory # dotenv environment variables file
publish/ .env
.env.test
# Publish Web Output # parcel-bundler cache (https://parceljs.org/)
*.[Pp]ublish.xml .cache
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to # next.js build output
# checkin your Azure Web App publish settings, but sensitive information contained .next
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages # nuxt.js build output
*.nupkg .nuxt
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output # vuepress build output
csx/ .vuepress/dist
*.build.csdef
# Microsoft Azure Emulator # Serverless directories
ecf/ .serverless/
rcf/
# Windows Store app package directories and files # FuseBox cache
AppPackages/ .fusebox/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files # DynamoDB Local files
# files ending in .cache can be ignored .dynamodb/
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others # OS metadata
ClientBin/ .DS_Store
~$* Thumbs.db
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk # Ignore built ts files
# (https://github.com/github/gitignore/pull/2483#issue-259490424) __tests__/runner/*
#*.snk lib/**/*
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/

9
.markdownlint-cli2.jsonc Normal file
View File

@@ -0,0 +1,9 @@
{
"config": {
"default": true,
"MD013": false
},
"ignores": [
"SECURITY.md"
]
}

320
README.md
View File

@@ -2,23 +2,32 @@
## Automate your GitHub workflows using Azure Actions ## 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. [GitHub Actions](https://help.github.com/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. 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 ## 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. With the [Azure Login](https://github.com/Azure/login/blob/master/action.yml) Action, you can do an Azure login using [Azure Managed Identities and Azure service principal](https://learn.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview#managed-identity-types) to run Az CLI and Azure PowerShell scripts.
Get started today with a [free Azure account](https://azure.com/free/open-source)! - 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). - To login into one of the Azure Government clouds or Azure Stack, set the optional parameter `environment` with one of the supported values `AzureUSGovernment` or `AzureChinaCloud` or `AzureStack`. If this parameter is not specified, it takes the default value `AzureCloud` and connects to the Azure Public Cloud. Additionally, the parameter `creds` takes the Azure service principal created in the particular cloud to connect (Refer to the [Configure a service principal with a secret](#configure-a-service-principal-with-a-secret) section below for details).
- The Action supports two different ways of authentication with Azure. One using the Azure Service Principal with secrets. The other is OpenID connect (OIDC) method of authentication using Azure [Workload Identity Federation](https://learn.microsoft.com/en-us/azure/active-directory/develop/workload-identity-federation). **We recommend using OIDC based authentication for increased security.**
- To login using Azure Service Principal with a secret, follow [this](#configure-a-service-principal-with-a-secret) guidance.
- To login using **OpenID Connect (OIDC) based Federated Identity Credentials**, you need to first configure trust between GitHub workflow and an Azure Managed Identity or an Azure AD App (Service Principal)
1. Follow [this](#configure-a-federated-credential-to-use-oidc-based-authentication) guidance to create a Federated Credential associated with your Azure Managed Identity or AD App (Service Principal). This is needed to establish OIDC trust between GitHub deployment workflows and the specific Azure resources scoped by the Managed Identity/service principal.
2. In your GitHub workflow, Set `permissions:` with `id-token: write` at workflow level or job level based on whether the OIDC token needs to be auto-generated for all Jobs or a specific Job.
3. Within the Job deploying to Azure, add Azure/login action and pass the `client-id` and `tenant-id` of the Azure Managed Identity/service principal associated with an OIDC Federated Identity Credential created in step (i). You also need to pass `subscription-id` or set `allow-no-subscriptions` to true.
Note:
- Ensure the CLI version is 2.30 or above to use OIDC support.
- By default, Azure access tokens issued during OIDC based login could have limited validity. Azure access token issued by AD App (Service Principal) is expected to have an expiration of 1 hour by default. And with Managed Identities, it would be 24 hrs. This expiration time is further configurable in Azure. Refger to [access-token lifetime](https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens#access-token-lifetime) for more details.
## Sample workflow that uses Azure login action to run az cli ## Sample workflow that uses Azure login action to run az cli
```yaml ```yaml
# File: .github/workflows/workflow.yml # File: .github/workflows/workflow.yml
on: [push] on: [push]
@@ -31,7 +40,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: azure/login@v1.1 - uses: azure/login@v1
with: with:
creds: ${{ secrets.AZURE_CREDENTIALS }} creds: ${{ secrets.AZURE_CREDENTIALS }}
@@ -43,12 +52,210 @@ jobs:
## Sample workflow that uses Azure login action to run Azure PowerShell ## Sample workflow that uses Azure login action to run Azure PowerShell
```yaml ```yaml
# File: .github/workflows/workflow.yml # File: .github/workflows/workflow.yml
on: [push] on: [push]
name: AzurePowerShellSample name: AzurePowerShellLoginSample
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Login via Az module
uses: azure/login@v1
with:
creds: ${{secrets.AZURE_CREDENTIALS}}
enable-AzPSSession: true
- run: |
Get-AzVM -ResourceGroupName "ResourceGroup11"
```
## Sample workflow that uses Azure login action using OIDC to run az cli (Linux)
```yaml
# File: .github/workflows/OIDC_workflow.yml
name: Run Azure Login with OIDC
on: [push]
permissions:
id-token: write
contents: read
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Az CLI login
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Azure CLI script
uses: azure/CLI@v1
with:
azcliversion: latest
inlineScript: |
az account show
az group list
```
Users can also specify `audience` field for access-token in the input parameters of the action. If not specified, it is defaulted to `api://AzureADTokenExchange`. This action supports login az powershell as well for both Windows and Linux runners by setting an input parameter `enable-AzPSSession: true`. Below is the sample workflow for the same using the Windows runner. Please note that powershell login is not supported in macOS runners.
## Sample workflow that uses Azure login action using OIDC to run az PowerShell (Windows)
```yaml
# File: .github/workflows/OIDC_workflow.yml
name: Run Azure Login with OIDC
on: [push]
permissions:
id-token: write
contents: read
jobs:
Windows-latest:
runs-on: windows-latest
steps:
- name: OIDC Login to Azure Public Cloud with AzPowershell (enableAzPSSession true)
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true
- name: 'Get RG with powershell action'
uses: azure/powershell@v1
with:
inlineScript: |
Get-AzResourceGroup
azPSVersion: "latest"
```
Refer to the [Azure PowerShell](https://github.com/azure/powershell) GitHub Action to run your Azure PowerShell scripts.
## Sample to connect to Azure US Government cloud
```yaml
# File: .github/workflows/workflow.yml
- name: Login to Azure US Gov Cloud with CLI
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_US_GOV_CREDENTIALS }}
environment: 'AzureUSGovernment'
enable-AzPSSession: false
- name: Login to Azure US Gov Cloud with Az Powershell
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_US_GOV_CREDENTIALS }}
environment: 'AzureUSGovernment'
enable-AzPSSession: true
```
Refer to the [Azure PowerShell](https://github.com/azure/powershell) GitHub Action to run your Azure PowerShell scripts.
## Sample Azure Login workflow that uses Azure login action to run az cli on Azure Stack Hub
```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 }}
environment: 'AzureStack'
- run: |
az webapp list --query "[?state=='Running']"
```
Refer to the [Azure Stack Hub Login Action Tutorial](https://learn.microsoft.com/azure-stack/user/ci-cd-github-action-login-cli?view=azs-2008) for more detailed instructions.
## Configure deployment credentials
### Configure a service principal with a secret
For using any credentials like Azure Service Principal, Publish Profile etc add them as [secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets) in the GitHub repository and then use them in the workflow.
Follow the following steps to configure Azure Service Principal with a secret:
- Define a new secret under your repository settings, Add secret menu
- Store the output of the below [az cli](https://learn.microsoft.com/cli/azure/?view=azure-cli-latest) command as the value of secret variable, for example 'AZURE_CREDENTIALS'
```bash
az ad sp create-for-rbac --name "myApp" --role contributor \
--scopes /subscriptions/{subscription-id}/resourceGroups/{resource-group} \
--sdk-auth
```
Replace `{subscription-id}` and `{resource-group}` with the subscription and resource group details, respectively.
The command should output a JSON object similar to this:
```bash
{
"clientId": "<GUID>",
"clientSecret": "<STRING>",
"subscriptionId": "<GUID>",
"tenantId": "<GUID>",
"resourceManagerEndpointUrl": "<URL>"
(...)
}
```
- 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)
- Note: The above `az ad sp create-for-rbac` command will give you the `--sdk-auth` deprecation warning. As we are working with CLI for this deprecation process, we strongly recommend users to use this `--sdk-auth` flag as the result dictionary output changes and not accepted by login action if `--sdk-auth` is not used.
- If you want to pass Subscription ID, Tenant ID, Client ID, and Client Secret as individual parameters instead of bundling them in a single JSON object (creds) to address the [security concerns](https://docs.github.com/actions/security-guides/encrypted-secrets) for Non-OIDC login, below snippet can help with the same.
```yaml
- uses: Azure/login@v1
with:
creds: '{"clientId":"${{ secrets.CLIENT_ID }}","clientSecret":"${{ secrets.CLIENT_SECRET }}","subscriptionId":"${{ secrets.SUBSCRIPTION_ID }}","tenantId":"${{ secrets.TENANT_ID }}"}'
```
In a similar way, any additional parameter can be added to creds such as resourceManagerEndpointUrl for Azure Stack, for example.
### Manually creating the Credentials object
If you already created and assigned a Service Principal in Azure you can manually create the .json object above by finding the `clientId` and `clientSecret` on the Service Principal, and your `subscriptionId` and `tenantId` of the subscription and tenant respectively. The `resourceManagerEndpointUrl` will be `https://management.azure.com/` if you are using the public Azure cloud.
### Configure a Federated Credential to use OIDC based authentication
Please refer to Microsoft's documentation at ["Configure a federated identity credential on an app”](https://learn.microsoft.com/en-us/azure/active-directory/develop/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp#github-actions) and ["Configure a user-assigned managed identity"](https://learn.microsoft.com/en-us/azure/active-directory/develop/workload-identity-federation-create-trust-user-assigned-managed-identity?pivots=identity-wif-mi-methods-azp#github-actions-deploying-azure-resources) to trust an external identity provider (preview) which has more details about the Azure Workload Identity Federation (OIDC) support.
You can add federated credentials in the Azure portal or with the Microsoft Graph REST API.
## Support for using `allow-no-subscriptions` flag with az login
Capability has been added to support access to tenants without subscriptions for both OIDC and non-OIDC. 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: jobs:
@@ -56,90 +263,35 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Login via Az module - uses: azure/login@v1
uses: azure/login@v1.1
with: with:
creds: ${{secrets.AZURE_CREDENTIALS}} creds: ${{ secrets.AZURE_CREDENTIALS }}
enable-AzPSSession: true allow-no-subscriptions: 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. ## Az logout and security hardening
## Configure deployment credentials: This action doesn't implement ```az logout``` by default at the end of execution. However there is no way of tampering the credentials or account information because the github hosted runner is on a VM that will get reimaged for every customer run which gets everything deleted. But if the runner is self-hosted which is not github provided it is recommended to manually logout at the end of the workflow as shown below. More details on security of the runners can be found [here](https://docs.github.com/actions/learn-github-actions/security-hardening-for-github-actions#hardening-for-self-hosted-runners).
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.
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'
```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": "<GUID>",
"clientSecret": "<GUID>",
"subscriptionId": "<GUID>",
"tenantId": "<GUID>",
(...)
}
```
* 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 ```yaml
- name: Azure CLI script
# action.yml uses: azure/CLI@v1
with:
# Login to Azure subscription inlineScript: |
name: 'Azure Login' az logout
description: 'AuthenticatetoAzureandrunyourAzCLIorAzPowerShellbasedActionsorscripts.github.com/Azure/Actions' az cache purge
inputs: az account clear
creds:
description: 'Paste output of `az ad sp create-for-rbac` as value of secret variable: AZURE_CREDENTIALS'
required: true
enable-AzPSSession:
description: 'SetthisvaluetotruetoenableAzurePowerShellLogininadditiontoAzCLIlogin'
required: false
default: false
branding:
icon: 'login.svg'
color: 'blue'
runs:
using: 'node12'
main: 'lib/main.js'
``` ```
# Contributing ## Az CLI dependency
Internally in this action, we use azure CLI and execute `az login` with the credentials provided through secrets. In order to validate the new az CLI releases for this action, [canary test workflow](.github/workflows/azure-login-canary.yml) is written which will execute the action on [az CLI's edge build](https://github.com/Azure/azure-cli#edge-builds) which will fail incase of any breaking change is being introduced in the new upcoming release. The test results can be posted on a slack or teams channel using the corresponding integrations. Incase of a failure, the concern will be raised to [azure-cli](https://github.com/Azure/azure-cli) for taking a necessary action and also the latest CLI installation will be postponed in [Runner VMs](https://github.com/actions/virtual-environments) as well for hosted runner to prevent the workflows failing due to the new CLI changes.
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a 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 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. 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 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 a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions

View File

@@ -1,11 +1,17 @@
import { ServicePrincipalLogin } from '../../src/PowerShell/ServicePrincipalLogin'; import { ServicePrincipalLogin } from '../../src/PowerShell/ServicePrincipalLogin';
import { LoginConfig } from '../../src/common/LoginConfig';
jest.mock('../../src/PowerShell/Utilities/Utils'); jest.mock('../../src/PowerShell/Utilities/Utils');
jest.mock('../../src/PowerShell/Utilities/PowerShellToolRunner'); jest.mock('../../src/PowerShell/Utilities/PowerShellToolRunner');
let spnlogin: ServicePrincipalLogin; let spnlogin: ServicePrincipalLogin;
beforeAll(() => { beforeAll(() => {
spnlogin = new ServicePrincipalLogin("servicePrincipalID", "servicePrinicipalkey", "tenantId", "subscriptionId"); var loginConfig = new LoginConfig();
loginConfig.servicePrincipalId = "servicePrincipalID";
loginConfig.servicePrincipalKey = "servicePrinicipalkey";
loginConfig.tenantId = "tenantId";
loginConfig.subscriptionId = "subscriptionId";
spnlogin = new ServicePrincipalLogin(loginConfig);
}); });
afterEach(() => { afterEach(() => {

View 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();
});
});

View File

@@ -1,17 +1,38 @@
# Login to Azure subscription # Login to Azure subscription
name: 'Azure Login' name: 'Azure Login'
description: 'AuthenticatetoAzureandrunyourAzCLIorAzPowerShellbasedActionsorscripts.github.com/Azure/Actions' description: 'Authenticate to Azure using OIDC and run your Az CLI or Az PowerShell based actions or scripts. github.com/Azure/Actions'
inputs: inputs:
creds: creds:
description: 'Paste output of `az ad sp create-for-rbac` as value of secret variable: AZURE_CREDENTIALS' description: 'Paste output of `az ad sp create-for-rbac` as value of secret variable: AZURE_CREDENTIALS'
required: true required: false
client-id:
description: 'ClientId of the Azure Service principal created.'
required: false
tenant-id:
description: 'TenantId of the Azure Service principal created.'
required: false
subscription-id:
description: 'Azure subscriptionId'
required: false
enable-AzPSSession: enable-AzPSSession:
description: 'SetthisvaluetotruetoenableAzurePowerShellLogininadditiontoAzCLIlogin' description: 'Set this value to true to enable Azure PowerShell Login in addition to Az CLI login'
required: false required: false
default: false default: false
environment:
description: 'Name of the environment. Supported values are azurecloud, azurestack, azureusgovernment, azurechinacloud, azuregermancloud. 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
audience:
description: 'Provide audience field for access-token. Default value is api://AzureADTokenExchange'
required: false
default: 'api://AzureADTokenExchange'
branding: branding:
icon: 'login.svg' icon: 'login.svg'
color: 'blue' color: 'blue'
runs: runs:
using: 'node12' using: 'node16'
main: 'lib/main.js' main: 'lib/main.js'

View File

@@ -1,14 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class Constants {
}
exports.default = Constants;
Constants.prefix = "az_";
Constants.moduleName = "Az.Accounts";
Constants.versionPattern = /[0-9]\.[0-9]\.[0-9]/;
Constants.AzureCloud = "AzureCloud";
Constants.Subscription = "Subscription";
Constants.ServicePrincipal = "ServicePrincipal";
Constants.Success = "Success";
Constants.Error = "Error";
Constants.AzVersion = "AzVersion";

View File

@@ -1,73 +0,0 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(require("@actions/core"));
const Utils_1 = __importDefault(require("./Utilities/Utils"));
const PowerShellToolRunner_1 = __importDefault(require("./Utilities/PowerShellToolRunner"));
const ScriptBuilder_1 = __importDefault(require("./Utilities/ScriptBuilder"));
const Constants_1 = __importDefault(require("./Constants"));
class ServicePrincipalLogin {
constructor(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId) {
this.servicePrincipalId = servicePrincipalId;
this.servicePrincipalKey = servicePrincipalKey;
this.tenantId = tenantId;
this.subscriptionId = subscriptionId;
}
initialize() {
return __awaiter(this, void 0, void 0, function* () {
Utils_1.default.setPSModulePath();
const azLatestVersion = yield Utils_1.default.getLatestModule(Constants_1.default.moduleName);
core.debug(`Az Module version used: ${azLatestVersion}`);
Utils_1.default.setPSModulePath(`${Constants_1.default.prefix}${azLatestVersion}`);
});
}
login() {
return __awaiter(this, void 0, void 0, function* () {
let output = "";
const options = {
listeners: {
stdout: (data) => {
output += data.toString();
}
}
};
const args = {
servicePrincipalId: this.servicePrincipalId,
servicePrincipalKey: this.servicePrincipalKey,
subscriptionId: this.subscriptionId,
environment: ServicePrincipalLogin.environment,
scopeLevel: ServicePrincipalLogin.scopeLevel
};
const script = new ScriptBuilder_1.default().getAzPSLoginScript(ServicePrincipalLogin.scheme, this.tenantId, args);
yield PowerShellToolRunner_1.default.init();
yield PowerShellToolRunner_1.default.executePowerShellScriptBlock(script, options);
const result = JSON.parse(output.trim());
if (!(Constants_1.default.Success in result)) {
throw new Error(`Azure PowerShell login failed with error: ${result[Constants_1.default.Error]}`);
}
console.log(`Azure PowerShell session successfully initialized`);
});
}
}
exports.ServicePrincipalLogin = ServicePrincipalLogin;
ServicePrincipalLogin.environment = Constants_1.default.AzureCloud;
ServicePrincipalLogin.scopeLevel = Constants_1.default.Subscription;
ServicePrincipalLogin.scheme = Constants_1.default.ServicePrincipal;

View File

@@ -1,35 +0,0 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const io = __importStar(require("@actions/io"));
const exec = __importStar(require("@actions/exec"));
class PowerShellToolRunner {
static init() {
return __awaiter(this, void 0, void 0, function* () {
if (!PowerShellToolRunner.psPath) {
PowerShellToolRunner.psPath = yield io.which("pwsh", true);
}
});
}
static executePowerShellScriptBlock(scriptBlock, options = {}) {
return __awaiter(this, void 0, void 0, function* () {
yield exec.exec(`"${PowerShellToolRunner.psPath}" -Command`, [scriptBlock], options);
});
}
}
exports.default = PowerShellToolRunner;

View File

@@ -1,62 +0,0 @@
"use strict";
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const core = __importStar(require("@actions/core"));
const Constants_1 = __importDefault(require("../Constants"));
class ScriptBuilder {
constructor() {
this.script = "";
}
getAzPSLoginScript(scheme, tenantId, args) {
let command = `Clear-AzContext -Scope Process;
Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue;`;
if (scheme === Constants_1.default.ServicePrincipal) {
command += `Connect-AzAccount -ServicePrincipal -Tenant '${tenantId}' -Credential \
(New-Object System.Management.Automation.PSCredential('${args.servicePrincipalId}',(ConvertTo-SecureString '${args.servicePrincipalKey.replace("'", "''")}' -AsPlainText -Force))) \
-Environment '${args.environment}' | out-null;`;
if (args.scopeLevel === Constants_1.default.Subscription) {
command += `Set-AzContext -SubscriptionId '${args.subscriptionId}' -TenantId '${tenantId}' | out-null;`;
}
}
this.script += `try {
$ErrorActionPreference = "Stop"
$WarningPreference = "SilentlyContinue"
$output = @{}
${command}
$output['${Constants_1.default.Success}'] = "true"
}
catch {
$output['${Constants_1.default.Error}'] = $_.exception.Message
}
return ConvertTo-Json $output`;
core.debug(`Azure PowerShell Login Script: ${this.script}`);
return this.script;
}
getLatestModuleScript(moduleName) {
const command = `Get-Module -Name ${moduleName} -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1`;
this.script += `try {
$ErrorActionPreference = "Stop"
$WarningPreference = "SilentlyContinue"
$output = @{}
$data = ${command}
$output['${Constants_1.default.AzVersion}'] = $data.Version.ToString()
$output['${Constants_1.default.Success}'] = "true"
}
catch {
$output['${Constants_1.default.Error}'] = $_.exception.Message
}
return ConvertTo-Json $output`;
core.debug(`GetLatestModuleScript: ${this.script}`);
return this.script;
}
}
exports.default = ScriptBuilder;

View File

@@ -1,80 +0,0 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const os = __importStar(require("os"));
const Constants_1 = __importDefault(require("../Constants"));
const ScriptBuilder_1 = __importDefault(require("./ScriptBuilder"));
const PowerShellToolRunner_1 = __importDefault(require("./PowerShellToolRunner"));
class Utils {
/**
* Add the folder path where Az modules are present to PSModulePath based on runner
* @param azPSVersion
* If azPSVersion is empty, folder path in which all Az modules are present are set
* If azPSVersion is not empty, folder path of exact Az module version is set
*/
static setPSModulePath(azPSVersion = "") {
let modulePath = "";
const runner = process.env.RUNNER_OS || os.type();
switch (runner.toLowerCase()) {
case "linux":
modulePath = `/usr/share/${azPSVersion}:`;
break;
case "windows":
case "windows_nt":
modulePath = `C:\\Modules\\${azPSVersion};`;
break;
case "macos":
case "darwin":
throw new Error(`OS not supported`);
default:
throw new Error(`Unknown os: ${runner.toLowerCase()}`);
}
process.env.PSModulePath = `${modulePath}${process.env.PSModulePath}`;
}
static getLatestModule(moduleName) {
return __awaiter(this, void 0, void 0, function* () {
let output = "";
const options = {
listeners: {
stdout: (data) => {
output += data.toString();
}
}
};
yield PowerShellToolRunner_1.default.init();
yield PowerShellToolRunner_1.default.executePowerShellScriptBlock(new ScriptBuilder_1.default()
.getLatestModuleScript(moduleName), options);
const result = JSON.parse(output.trim());
if (!(Constants_1.default.Success in result)) {
throw new Error(result[Constants_1.default.Error]);
}
const azLatestVersion = result[Constants_1.default.AzVersion];
if (!Utils.isValidVersion(azLatestVersion)) {
throw new Error(`Invalid AzPSVersion: ${azLatestVersion}`);
}
return azLatestVersion;
});
}
static isValidVersion(version) {
return !!version.match(Constants_1.default.versionPattern);
}
}
exports.default = Utils;

View File

@@ -1,90 +0,0 @@
"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 crypto = __importStar(require("crypto"));
const exec = __importStar(require("@actions/exec"));
const io = __importStar(require("@actions/io"));
const actions_secret_parser_1 = require("actions-secret-parser");
const ServicePrincipalLogin_1 = require("./PowerShell/ServicePrincipalLogin");
var azPath;
var prefix = !!process.env.AZURE_HTTP_USER_AGENT ? `${process.env.AZURE_HTTP_USER_AGENT}` : "";
var azPSHostEnv = !!process.env.AZUREPS_HOST_ENVIRONMENT ? `${process.env.AZUREPS_HOST_ENVIRONMENT}` : "";
function main() {
return __awaiter(this, void 0, void 0, function* () {
try {
// Set user agent variable
var isAzCLISuccess = false;
let usrAgentRepo = crypto.createHash('sha256').update(`${process.env.GITHUB_REPOSITORY}`).digest('hex');
let actionName = 'AzureLogin';
let userAgentString = (!!prefix ? `${prefix}+` : '') + `GITHUBACTIONS/${actionName}@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();

8972
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -10,17 +10,18 @@
"author": "Sumiran Aggarwal", "author": "Sumiran Aggarwal",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@types/jest": "^25.1.4", "@types/jest": "^29.2.4",
"@types/node": "^12.7.11", "@types/node": "^12.7.11",
"jest": "^25.2.4", "jest": "^29.3.1",
"jest-circus": "^25.2.7", "jest-circus": "^29.3.1",
"ts-jest": "^25.3.0", "ts-jest": "^29.0.3",
"typescript": "^3.6.3" "typescript": "^4.9.4"
}, },
"dependencies": { "dependencies": {
"@actions/core": "^1.1.3", "@actions/core": "1.9.1",
"@actions/exec": "^1.0.1", "@actions/exec": "^1.0.1",
"@actions/io": "^1.0.1", "@actions/io": "^1.0.1",
"actions-secret-parser": "^1.0.2" "actions-secret-parser": "^1.0.2",
"package-lock": "^1.0.3"
} }
} }

128
src/Cli/AzureCliLogin.ts Normal file
View File

@@ -0,0 +1,128 @@
import * as exec from '@actions/exec';
import { LoginConfig } from "../common/LoginConfig";
import { ExecOptions } from '@actions/exec/lib/interfaces';
import * as core from '@actions/core';
import * as io from '@actions/io';
export class AzureCliLogin {
loginConfig: LoginConfig;
azPath: string;
constructor(loginConfig: LoginConfig) {
this.loginConfig = loginConfig;
}
async login() {
this.azPath = await io.which("az", true);
core.debug(`az cli path: ${this.azPath}`);
let output: string = "";
const execOptions: any = {
listeners: {
stdout: (data: Buffer) => {
output += data.toString();
}
}
};
await this.executeAzCliCommand("--version", true, execOptions);
core.debug(`az cli version used:\n${output}`);
this.setAzurestackEnvIfNecessary();
await this.executeAzCliCommand(`cloud set -n "${this.loginConfig.environment}"`, false);
console.log(`Done setting cloud: "${this.loginConfig.environment}"`);
// Attempting Az cli login
var commonArgs = ["--service-principal",
"-u", this.loginConfig.servicePrincipalId,
"--tenant", this.loginConfig.tenantId
];
if (this.loginConfig.allowNoSubscriptionsLogin) {
commonArgs = commonArgs.concat("--allow-no-subscriptions");
}
if (this.loginConfig.enableOIDC) {
commonArgs = commonArgs.concat("--federated-token", this.loginConfig.federatedToken);
}
else {
console.log("Note: Azure/login action also supports OIDC login mechanism. Refer https://github.com/azure/login#configure-a-service-principal-with-a-federated-credential-to-use-oidc-based-authentication for more details.")
commonArgs = commonArgs.concat(`--password=${this.loginConfig.servicePrincipalKey}`);
}
const loginOptions: ExecOptions = defaultExecOptions();
await this.executeAzCliCommand(`login`, true, loginOptions, commonArgs);
if (!this.loginConfig.allowNoSubscriptionsLogin) {
var args = [
"--subscription",
this.loginConfig.subscriptionId
];
await this.executeAzCliCommand(`account set`, true, loginOptions, args);
}
}
async setAzurestackEnvIfNecessary() {
if (this.loginConfig.environment != "azurestack") {
return;
}
if (!this.loginConfig.resourceManagerEndpointUrl) {
throw new Error("resourceManagerEndpointUrl is a required parameter when environment is defined.");
}
console.log(`Unregistering cloud: "${this.loginConfig.environment}" first if it exists`);
try {
await this.executeAzCliCommand(`cloud set -n AzureCloud`, true);
await this.executeAzCliCommand(`cloud unregister -n "${this.loginConfig.environment}"`, false);
}
catch (error) {
console.log(`Ignore cloud not registered error: "${error}"`);
}
console.log(`Registering cloud: "${this.loginConfig.environment}" with ARM endpoint: "${this.loginConfig.resourceManagerEndpointUrl}"`);
try {
let baseUri = this.loginConfig.resourceManagerEndpointUrl;
if (baseUri.endsWith('/')) {
baseUri = baseUri.substring(0, baseUri.length - 1); // need to remove trailing / from resourceManagerEndpointUrl to correctly derive suffixes below
}
let suffixKeyvault = ".vault" + baseUri.substring(baseUri.indexOf('.')); // keyvault suffix starts with .
let suffixStorage = baseUri.substring(baseUri.indexOf('.') + 1); // storage suffix starts without .
let profileVersion = "2019-03-01-hybrid";
await this.executeAzCliCommand(`cloud register -n "${this.loginConfig.environment}" --endpoint-resource-manager "${this.loginConfig.resourceManagerEndpointUrl}" --suffix-keyvault-dns "${suffixKeyvault}" --suffix-storage-endpoint "${suffixStorage}" --profile "${profileVersion}"`, false);
}
catch (error) {
core.error(`Error while trying to register cloud "${this.loginConfig.environment}": "${error}"`);
}
console.log(`Done registering cloud: "${this.loginConfig.environment}"`)
}
async executeAzCliCommand(
command: string,
silent?: boolean,
execOptions: any = {},
args: any = []) {
execOptions.silent = !!silent;
await exec.exec(`"${this.azPath}" ${command}`, args, execOptions);
}
}
function defaultExecOptions(): exec.ExecOptions {
return {
silent: true,
listeners: {
stderr: (data: Buffer) => {
let error = data.toString();
let startsWithWarning = error.toLowerCase().startsWith('warning');
let startsWithError = error.toLowerCase().startsWith('error');
// printing ERROR
if (error && error.trim().length !== 0 && !startsWithWarning) {
if (startsWithError) {
//removing the keyword 'ERROR' to avoid duplicates while throwing error
error = error.slice(5);
}
core.setFailed(error);
}
}
}
};
}

View File

@@ -1,7 +1,7 @@
export default class Constants { export default class Constants {
static readonly prefix: string = "az_"; static readonly prefix: string = "az_";
static readonly moduleName: string = "Az.Accounts"; static readonly moduleName: string = "Az.Accounts";
static readonly versionPattern = /[0-9]\.[0-9]\.[0-9]/; static readonly versionPattern = /[0-9]+\.[0-9]+\.[0-9]+/;
static readonly AzureCloud: string = "AzureCloud"; static readonly AzureCloud: string = "AzureCloud";
static readonly Subscription: string = "Subscription"; static readonly Subscription: string = "Subscription";

View File

@@ -4,21 +4,15 @@ import Utils from './Utilities/Utils';
import PowerShellToolRunner from './Utilities/PowerShellToolRunner'; import PowerShellToolRunner from './Utilities/PowerShellToolRunner';
import ScriptBuilder from './Utilities/ScriptBuilder'; import ScriptBuilder from './Utilities/ScriptBuilder';
import Constants from './Constants'; import Constants from './Constants';
import { LoginConfig } from '../common/LoginConfig';
export class ServicePrincipalLogin implements IAzurePowerShellSession { export class ServicePrincipalLogin implements IAzurePowerShellSession {
static readonly environment: string = Constants.AzureCloud;
static readonly scopeLevel: string = Constants.Subscription; static readonly scopeLevel: string = Constants.Subscription;
static readonly scheme: string = Constants.ServicePrincipal; static readonly scheme: string = Constants.ServicePrincipal;
servicePrincipalId: string; loginConfig: LoginConfig;
servicePrincipalKey: string;
tenantId: string;
subscriptionId: string;
constructor(servicePrincipalId: string, servicePrincipalKey: string, tenantId: string, subscriptionId: string) { constructor(loginConfig: LoginConfig) {
this.servicePrincipalId = servicePrincipalId; this.loginConfig = loginConfig;
this.servicePrincipalKey = servicePrincipalKey;
this.tenantId = tenantId;
this.subscriptionId = subscriptionId;
} }
async initialize() { async initialize() {
@@ -30,21 +24,32 @@ export class ServicePrincipalLogin implements IAzurePowerShellSession {
async login() { async login() {
let output: string = ""; let output: string = "";
let commandStdErr = false;
const options: any = { const options: any = {
listeners: { listeners: {
stdout: (data: Buffer) => { stdout: (data: Buffer) => {
output += data.toString(); output += data.toString();
},
stderr: (data: Buffer) => {
let error = data.toString();
if (error && error.trim().length !== 0) {
commandStdErr = true;
core.error(error);
}
} }
} }
}; };
const args: any = { const args: any = {
servicePrincipalId: this.servicePrincipalId, servicePrincipalId: this.loginConfig.servicePrincipalId,
servicePrincipalKey: this.servicePrincipalKey, servicePrincipalKey: this.loginConfig.servicePrincipalKey,
subscriptionId: this.subscriptionId, federatedToken: this.loginConfig.federatedToken,
environment: ServicePrincipalLogin.environment, subscriptionId: this.loginConfig.subscriptionId,
scopeLevel: ServicePrincipalLogin.scopeLevel environment: this.loginConfig.environment,
scopeLevel: ServicePrincipalLogin.scopeLevel,
allowNoSubscriptionsLogin: this.loginConfig.allowNoSubscriptionsLogin,
resourceManagerEndpointUrl: this.loginConfig.resourceManagerEndpointUrl
} }
const script: string = new ScriptBuilder().getAzPSLoginScript(ServicePrincipalLogin.scheme, this.tenantId, args); const script: string = new ScriptBuilder().getAzPSLoginScript(ServicePrincipalLogin.scheme, this.loginConfig.tenantId, args);
await PowerShellToolRunner.init(); await PowerShellToolRunner.init();
await PowerShellToolRunner.executePowerShellScriptBlock(script, options); await PowerShellToolRunner.executePowerShellScriptBlock(script, options);
const result: any = JSON.parse(output.trim()); const result: any = JSON.parse(output.trim());

View File

@@ -3,7 +3,6 @@ import * as exec from '@actions/exec';
export default class PowerShellToolRunner { export default class PowerShellToolRunner {
static psPath: string; static psPath: string;
static async init() { static async init() {
if(!PowerShellToolRunner.psPath) { if(!PowerShellToolRunner.psPath) {
PowerShellToolRunner.psPath = await io.which("pwsh", true); PowerShellToolRunner.psPath = await io.which("pwsh", true);
@@ -11,6 +10,7 @@ export default class PowerShellToolRunner {
} }
static async executePowerShellScriptBlock(scriptBlock: string, options: any = {}) { static async executePowerShellScriptBlock(scriptBlock: string, options: any = {}) {
//Options for error handling
await exec.exec(`"${PowerShellToolRunner.psPath}" -Command`, [scriptBlock], options) await exec.exec(`"${PowerShellToolRunner.psPath}" -Command`, [scriptBlock], options)
} }
} }

View File

@@ -8,14 +8,28 @@ export default class ScriptBuilder {
getAzPSLoginScript(scheme: string, tenantId: string, args: any): string { getAzPSLoginScript(scheme: string, tenantId: string, args: any): string {
let command = `Clear-AzContext -Scope Process; let command = `Clear-AzContext -Scope Process;
Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue;`; Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue;`;
if (scheme === Constants.ServicePrincipal) { if (scheme === Constants.ServicePrincipal) {
if (args.environment.toLowerCase() == "azurestack") {
command += `Add-AzEnvironment -Name ${args.environment} -ARMEndpoint ${args.resourceManagerEndpointUrl} | out-null;`;
}
// Separate command script for OIDC and non-OIDC
if (!!args.federatedToken) {
command += `Connect-AzAccount -ServicePrincipal -ApplicationId '${args.servicePrincipalId}' -Tenant '${tenantId}' -FederatedToken '${args.federatedToken}' \
-Environment '${args.environment}' | out-null;`;
}
else {
command += `Connect-AzAccount -ServicePrincipal -Tenant '${tenantId}' -Credential \ command += `Connect-AzAccount -ServicePrincipal -Tenant '${tenantId}' -Credential \
(New-Object System.Management.Automation.PSCredential('${args.servicePrincipalId}',(ConvertTo-SecureString '${args.servicePrincipalKey.replace("'", "''")}' -AsPlainText -Force))) \ (New-Object System.Management.Automation.PSCredential('${args.servicePrincipalId}',(ConvertTo-SecureString '${args.servicePrincipalKey.replace("'", "''")}' -AsPlainText -Force))) \
-Environment '${args.environment}' | out-null;`; -Environment '${args.environment}' | out-null;`;
if (args.scopeLevel === Constants.Subscription) { }
// command to set the subscription
if (args.scopeLevel === Constants.Subscription && !args.allowNoSubscriptionsLogin) {
command += `Set-AzContext -SubscriptionId '${args.subscriptionId}' -TenantId '${tenantId}' | out-null;`; command += `Set-AzContext -SubscriptionId '${args.subscriptionId}' -TenantId '${tenantId}' | out-null;`;
} }
} }
this.script += `try { this.script += `try {
$ErrorActionPreference = "Stop" $ErrorActionPreference = "Stop"
$WarningPreference = "SilentlyContinue" $WarningPreference = "SilentlyContinue"
@@ -27,6 +41,7 @@ export default class ScriptBuilder {
$output['${Constants.Error}'] = $_.exception.Message $output['${Constants.Error}'] = $_.exception.Message
} }
return ConvertTo-Json $output`; return ConvertTo-Json $output`;
core.debug(`Azure PowerShell Login Script: ${this.script}`); core.debug(`Azure PowerShell Login Script: ${this.script}`);
return this.script; return this.script;
} }
@@ -48,4 +63,5 @@ export default class ScriptBuilder {
core.debug(`GetLatestModuleScript: ${this.script}`); core.debug(`GetLatestModuleScript: ${this.script}`);
return this.script; return this.script;
} }
} }

93
src/common/LoginConfig.ts Normal file
View File

@@ -0,0 +1,93 @@
import * as core from '@actions/core';
import { FormatType, SecretParser } from 'actions-secret-parser';
export class LoginConfig {
static readonly azureSupportedCloudName = new Set([
"azureusgovernment",
"azurechinacloud",
"azuregermancloud",
"azurecloud",
"azurestack"]);
servicePrincipalId: string;
servicePrincipalKey: string;
tenantId: string;
subscriptionId: string;
resourceManagerEndpointUrl: string;
allowNoSubscriptionsLogin: boolean;
enableOIDC: boolean;
environment: string;
enableAzPSSession: boolean;
audience: string;
federatedToken: string;
constructor() {
this.enableOIDC = true;
}
async initialize() {
this.environment = core.getInput("environment").toLowerCase();
this.enableAzPSSession = core.getInput('enable-AzPSSession').toLowerCase() === "true";
this.allowNoSubscriptionsLogin = core.getInput('allow-no-subscriptions').toLowerCase() === "true";
this.servicePrincipalId = core.getInput('client-id', { required: false });
this.servicePrincipalKey = null;
this.tenantId = core.getInput('tenant-id', { required: false });
this.subscriptionId = core.getInput('subscription-id', { required: false });
this.audience = core.getInput('audience', { required: false });
this.federatedToken = null;
let creds = core.getInput('creds', { required: false });
let secrets = creds ? new SecretParser(creds, FormatType.JSON) : null;
if (creds) {
core.debug('using creds JSON...');
this.enableOIDC = false;
this.servicePrincipalId = secrets.getSecret("$.clientId", true);
this.servicePrincipalKey = secrets.getSecret("$.clientSecret", true);
this.tenantId = secrets.getSecret("$.tenantId", true);
this.subscriptionId = secrets.getSecret("$.subscriptionId", true);
this.resourceManagerEndpointUrl = secrets.getSecret("$.resourceManagerEndpointUrl", false);
}
this.getFederatedTokenIfNecessary();
}
async getFederatedTokenIfNecessary() {
if (!this.enableOIDC) {
return;
}
try {
this.federatedToken = await core.getIDToken(this.audience);
}
catch (error) {
core.error(`Please make sure to give write permissions to id-token in the workflow.`);
throw error;
}
if (!!this.federatedToken) {
let [issuer, subjectClaim] = await jwtParser(this.federatedToken);
console.log("Federated token details: \n issuer - " + issuer + " \n subject claim - " + subjectClaim);
}
else {
throw new Error("Failed to fetch federated token.");
}
}
async validate() {
if (!this.servicePrincipalId || !this.tenantId || !(this.servicePrincipalKey || this.enableOIDC)) {
throw new Error("Not all values are present in the credentials. Ensure clientId, clientSecret and tenantId are supplied.");
}
if (!this.subscriptionId && !this.allowNoSubscriptionsLogin) {
throw new Error("Not all values are present in the credentials. Ensure subscriptionId is supplied.");
}
if (!LoginConfig.azureSupportedCloudName.has(this.environment)) {
throw new Error("Unsupported value for environment is passed.The list of supported values for environment are azureusgovernment', azurechinacloud, azuregermancloud, azurecloud or azurestack");
}
}
}
async function jwtParser(federatedToken: string) {
let tokenPayload = federatedToken.split('.')[1];
let bufferObj = Buffer.from(tokenPayload, "base64");
let decodedPayload = JSON.parse(bufferObj.toString("utf8"));
return [decodedPayload['iss'], decodedPayload['sub']];
}

View File

@@ -1,72 +1,54 @@
import * as core from '@actions/core'; 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';
import { ServicePrincipalLogin } from './PowerShell/ServicePrincipalLogin'; import { ServicePrincipalLogin } from './PowerShell/ServicePrincipalLogin';
import { LoginConfig } from './common/LoginConfig';
import { AzureCliLogin } from './Cli/AzureCliLogin';
var azPath: string;
var prefix = !!process.env.AZURE_HTTP_USER_AGENT ? `${process.env.AZURE_HTTP_USER_AGENT}` : ""; 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}` : ""; var azPSHostEnv = !!process.env.AZUREPS_HOST_ENVIRONMENT ? `${process.env.AZUREPS_HOST_ENVIRONMENT}` : "";
async function main() { async function main() {
try {
// Set user agent variable
var isAzCLISuccess = false; var isAzCLISuccess = false;
let usrAgentRepo = crypto.createHash('sha256').update(`${process.env.GITHUB_REPOSITORY}`).digest('hex'); try {
let usrAgentRepo = `${process.env.GITHUB_REPOSITORY}`;
let actionName = 'AzureLogin'; let actionName = 'AzureLogin';
let userAgentString = (!!prefix ? `${prefix}+` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`; let userAgentString = (!!prefix ? `${prefix}+` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`;
let azurePSHostEnv = (!!azPSHostEnv ? `${azPSHostEnv}+` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`; let azurePSHostEnv = (!!azPSHostEnv ? `${azPSHostEnv}+` : '') + `GITHUBACTIONS/${actionName}@v1_${usrAgentRepo}`;
core.exportVariable('AZURE_HTTP_USER_AGENT', userAgentString); core.exportVariable('AZURE_HTTP_USER_AGENT', userAgentString);
core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azurePSHostEnv); core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azurePSHostEnv);
azPath = await io.which("az", true); // perpare the login configuration
await executeAzCliCommand("--version"); var loginConfig = new LoginConfig();
await loginConfig.initialize();
await loginConfig.validate();
let creds = core.getInput('creds', { required: true }); // login to Azure Cli
let secrets = new SecretParser(creds, FormatType.JSON); var cliLogin = new AzureCliLogin(loginConfig);
let servicePrincipalId = secrets.getSecret("$.clientId", false); await cliLogin.login();
let servicePrincipalKey = secrets.getSecret("$.clientSecret", true);
let tenantId = secrets.getSecret("$.tenantId", false);
let subscriptionId = secrets.getSecret("$.subscriptionId", false);
const enableAzPSSession = core.getInput('enable-AzPSSession').toLowerCase() === "true";
if (!servicePrincipalId || !servicePrincipalKey || !tenantId || !subscriptionId) {
throw new Error("Not all values are present in the creds object. Ensure clientId, clientSecret, tenantId and subscriptionId are supplied.");
}
// Attempting Az cli login
await executeAzCliCommand(`login --service-principal -u "${servicePrincipalId}" -p "${servicePrincipalKey}" --tenant "${tenantId}"`, true);
await executeAzCliCommand(`account set --subscription "${subscriptionId}"`, true);
isAzCLISuccess = true; isAzCLISuccess = true;
if (enableAzPSSession) {
// Attempting Az PS login //login to Azure PowerShell
if (loginConfig.enableAzPSSession) {
console.log(`Running Azure PS Login`); console.log(`Running Azure PS Login`);
const spnlogin: ServicePrincipalLogin = new ServicePrincipalLogin(servicePrincipalId, servicePrincipalKey, tenantId, subscriptionId); var spnlogin: ServicePrincipalLogin = new ServicePrincipalLogin(loginConfig);
await spnlogin.initialize(); await spnlogin.initialize();
await spnlogin.login(); await spnlogin.login();
} }
console.log("Login successful."); 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); catch (error) {
} finally { if (!isAzCLISuccess) {
core.setFailed(`Az CLI Login failed with ${error}. Please check the credentials and make sure az is installed on the runner. For more information refer https://aka.ms/create-secrets-for-GitHub-workflows`);
}
else {
core.setFailed(`Azure PowerShell Login failed with ${error}. Please check the credentials and make sure az is installed on the runner. For more information refer https://aka.ms/create-secrets-for-GitHub-workflows`);
}
}
finally {
// Reset AZURE_HTTP_USER_AGENT // Reset AZURE_HTTP_USER_AGENT
core.exportVariable('AZURE_HTTP_USER_AGENT', prefix); core.exportVariable('AZURE_HTTP_USER_AGENT', prefix);
core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azPSHostEnv); core.exportVariable('AZUREPS_HOST_ENVIRONMENT', azPSHostEnv);
} }
} }
async function executeAzCliCommand(command: string, silent?: boolean) {
try {
await exec.exec(`"${azPath}" ${command}`, [], {silent: !!silent});
}
catch(error) {
throw new Error(error);
}
}
main(); main();