-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for authenticating using an API key (#189)
* Add support for authenticating using an API key This commit adds support for the App Store Connect API key authentication method, which is the new recommended method by fastlane. It passes new options through to the --api_key_path option of fastlane. The options are: apiKeyId, apiKeyIssuerId, apiKeyContent, apiKeyInHouse (cherry picked from commit f3c49eb) * App App Store Connect API Key support to ServiceEndpoint This commits adds the ability to use the Service Endpoint to provide API Key credentials. The "token auth" scheme was chosen because it seems to be the closest match to what the App Store Connect API Key is. (cherry picked from commit 9a6c3b6) * Use base64-encoded private App Store Connect API Key Azure DevOps doesn't support multi-line string values in input fields which caused problems with the Private Key for the App Store Connect p8 private key. Base64-encoding the private key (which is supported by fastlane) solves this. (cherry picked from commit a98d239) * Merge branch 'master' into app_store_connect_api_key_support (cherry picked from commit 1a51081) * Merge branch 'master' into app_store_connect_api_key_support (cherry picked from commit 594948c) * Bump version number to 180.0 (cherry picked from commit e2f5124) * Merge branch 'master' into app_store_connect_api_key_support (cherry picked from commit 991b03e) * Resolved merging conflicts * Change scheme value from ms.vss-endpoint.endpoint-auth-scheme-token to Token As noted by @PeterStaev, the value should be "Token". * Use API Key ID in filename and delete API Key file in a clean up step To avoid any conflicts, we now use the API Key ID to construct the name of the API Key JSON file, and we save it inside of `Agent.BuildDirectory` or `Agent.TempDirectory`. By default, the API Key JSON file will be deleted after its use. That should be much safer. Using the `DEBUG_API_KEY_FILE` environment variable keeps it from being deleted. We use that env var for testing so we can verify that the file has been created with the correct content. * fix tests failing on windows * fix deprecated mocha types * Change 'apiKeyContent' to 'apitoken' to avoid duplicate field in ADO UI When using a service endpoint auth type with the new API key, the ADO UI adds an unused "API Token" field alongside our "API Key Content" field. As suggested by @PeterStaev, it's better to reuse the "apitoken" field name with our task-specific labels instead of adding our own field. That reuses the "apitoken" field that ADO adds anyway, but displays it with our labels. * fix invalid precheck for in app purchases * add message about precheck for in app purchases * Ensure API Key tests clean up api_key.json test files reliably Since we were cleaning up at the end of the tests, the clean up didn't happen when an assertion before it failed. That left an api_key.json file on disk. Now we read the file first and clean up right away. * apply deliver precheck fix for AppStoreRelease too * fix service endpoint values for better secret masking Agent's secret masker assumes that every service endpoint parameter is a secret, so if 'true' and 'false' are used as endpoint values, every 'true' and 'false' string in the logs of the job will be replaced with '***' * Change `apiKeyFileName` to `apiKeyFilePath` and prefer Agent.TempDirectory As per @egor-bryzgalov's code review, I've changed the name of the variable holding the path to the API Key file to make it clearer that it's not just the file *name*. Also change where the file is saved on disk: Prefer Agent.TempDirectory to Agent.BuildDirectory. This required some changes to the tests, since the system also writes a `.taskkey` file into the temp dir, which we need to clean up in order to delete the temp directory we had to create for testing. Co-authored-by: Egor Bryzgalov <v-egbryz@microsoft.com> Co-authored-by: DaniilShmelev <daniil.shmelev@akvelon.com>
- Loading branch information
1 parent
f364c3e
commit d47166e
Showing
16 changed files
with
1,002 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
'use strict'; | ||
|
||
import ma = require('azure-pipelines-task-lib/mock-answer'); | ||
import tmrm = require('azure-pipelines-task-lib/mock-run'); | ||
import path = require('path'); | ||
import os = require('os'); | ||
|
||
let taskPath = path.join(__dirname, '..', 'app-store-promote.js'); | ||
let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); | ||
|
||
tmr.setInput('authType', 'ApiKey'); | ||
tmr.setInput('apiKeyId', 'D383SF739'); | ||
tmr.setInput('apiKeyIssuerId', '6053b7fe-68a8-4acb-89be-165aa6465141'); | ||
tmr.setInput('apitoken', 'LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR1RBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJIa25saGRsWWRMdQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tLS0tLUVORCBQUklWQVRFIEtFWS0tLS0t'); | ||
tmr.setInput('appIdentifier', 'com.microsoft.test.appId'); | ||
tmr.setInput('chooseBuild', 'latest'); | ||
tmr.setInput('shouldAutoRelease', 'true'); | ||
tmr.setInput('installFastlane', 'true'); | ||
tmr.setInput('fastlaneToolsVersion', 'LatestVersion'); | ||
|
||
process.env['AGENT_TEMPDIRECTORY'] = 'test_temp_path'; | ||
// Keeps the API key file from being deleted, so we can inspect it in our test | ||
process.env['DEBUG_API_KEY_FILE'] = 'true'; | ||
process.env['MOCK_NORMALIZE_SLASHES'] = 'true'; | ||
process.env['HOME'] = '/usr/bin'; | ||
let gemCache: string = '/usr/bin/.gem-cache'; | ||
|
||
//construct a string that is JSON, call JSON.parse(string), send that to ma.TaskLibAnswers | ||
let myAnswers: string = `{ | ||
"which": { | ||
"ruby": "/usr/bin/ruby", | ||
"gem": "/usr/bin/gem", | ||
"fastlane": "/usr/bin/fastlane" | ||
}, | ||
"checkPath" : { | ||
"/usr/bin/ruby": true, | ||
"/usr/bin/gem": true, | ||
"/usr/bin/fastlane": true | ||
}, | ||
"exec": { | ||
"/usr/bin/gem install fastlane": { | ||
"code": 0, | ||
"stdout": "1 gem installed" | ||
}, | ||
"/usr/bin/gem update fastlane -i ${gemCache}": { | ||
"code": 0, | ||
"stdout": "1 gem installed" | ||
}, | ||
"fastlane deliver submit_build --precheck_include_in_app_purchases false --api_key_path test_temp_path/api_keyD383SF739.json -a com.microsoft.test.appId --skip_binary_upload true --skip_metadata true --skip_screenshots true --automatic_release --force": { | ||
"code": 0, | ||
"stdout": "consider it delivered!" | ||
} | ||
} | ||
}`; | ||
let json: any = JSON.parse(myAnswers); | ||
// Cast the json blob into a TaskLibAnswers | ||
tmr.setAnswers(<ma.TaskLibAnswers>json); | ||
|
||
// This is how you can mock NPM packages... | ||
os.platform = () => { | ||
return 'darwin'; | ||
}; | ||
tmr.registerMock('os', os); | ||
|
||
tmr.run(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
'use strict'; | ||
|
||
import ma = require('azure-pipelines-task-lib/mock-answer'); | ||
import tmrm = require('azure-pipelines-task-lib/mock-run'); | ||
import path = require('path'); | ||
import os = require('os'); | ||
|
||
let taskPath = path.join(__dirname, '..', 'app-store-promote.js'); | ||
let tmr: tmrm.TaskMockRunner = new tmrm.TaskMockRunner(taskPath); | ||
|
||
process.env['ENDPOINT_AUTH_MyServiceEndpoint'] = '{ "parameters": {"apiKeyId": "D383SF739", "apiKeyIssuerId": "6053b7fe-68a8-4acb-89be-165aa6465141", "apitoken": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JR1RBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJIa25saGRsWWRMdQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0t" }, "scheme": "Token" }'; | ||
|
||
tmr.setInput('authType', 'ServiceEndpoint'); | ||
tmr.setInput('serviceEndpoint', 'MyServiceEndpoint'); | ||
tmr.setInput('chooseBuild', 'Latest'); | ||
tmr.setInput('appIdentifier', 'com.microsoft.test.appId'); | ||
|
||
process.env['MOCK_NORMALIZE_SLASHES'] = 'true'; | ||
process.env['HOME'] = '/usr/bin'; | ||
process.env['AGENT_TEMPDIRECTORY'] = 'test_temp_path'; | ||
// Keeps the API key file from being deleted, so we can inspect it in our test | ||
process.env['DEBUG_API_KEY_FILE'] = 'true'; | ||
|
||
//construct a string that is JSON, call JSON.parse(string), send that to ma.TaskLibAnswers | ||
let myAnswers: string = `{ | ||
"which": { | ||
"ruby": "/usr/bin/ruby", | ||
"gem": "/usr/bin/gem", | ||
"fastlane": "/usr/bin/fastlane" | ||
}, | ||
"checkPath" : { | ||
"/usr/bin/ruby": true, | ||
"/usr/bin/gem": true, | ||
"/usr/bin/fastlane": true | ||
}, | ||
"exec": { | ||
"fastlane deliver submit_build --precheck_include_in_app_purchases false --api_key_path test_temp_path/api_keyD383SF739.json -a com.microsoft.test.appId --skip_binary_upload true --skip_metadata true --skip_screenshots true --force": { | ||
"code": 0, | ||
"stdout": "consider it uploaded!" | ||
} | ||
} | ||
}`; | ||
let json: any = JSON.parse(myAnswers); | ||
// Cast the json blob into a TaskLibAnswers | ||
tmr.setAnswers(<ma.TaskLibAnswers>json); | ||
|
||
// This is how you can mock NPM packages... | ||
os.platform = () => { | ||
return 'darwin'; | ||
}; | ||
tmr.registerMock('os', os); | ||
|
||
tmr.run(); |
Oops, something went wrong.