Skip to content

Commit f817edb

Browse files
authored
Cargo AuthenticateV0 Service Connection (#17572)
* Cargo AuthenticateV0 Service Connection * Added username/password (PAT) * Refactoring to support crates.io auth token * Remove node16 * Remove node16 * node10 commit
1 parent d2a7c8f commit f817edb

File tree

9 files changed

+104
-996
lines changed

9 files changed

+104
-996
lines changed

Tasks/CargoAuthenticateV0/Strings/resources.resjson/en-US/resources.resjson

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
"loc.instanceNameFormat": "cargo Authenticate $(configFile)",
66
"loc.input.label.configFile": "config.toml file to authenticate",
77
"loc.input.help.configFile": "Path to the config.toml file that specifies the registries you want to work with. Select the file, not the folder e.g. \"/.cargo/config.toml\".",
8+
"loc.input.label.cargoServiceConnections": "Credentials for registries outside this organization/collection",
9+
"loc.input.help.cargoServiceConnections": "Credentials to use for external registries located in the project's config.toml. For registries in this organization/collection, leave this blank; the build’s credentials are used automatically.",
810
"loc.messages.FailedToAddAuthentication": "Failed to add authentication.",
911
"loc.messages.ConfigTomlNotToml": "The file you selected to authenticate (%s) is not a valid .toml file.",
1012
"loc.messages.ConfigTomlDoesNotExist": "The config.toml file you selected at %s does not currently exist.",
1113
"loc.messages.ConfigTomlMissingRegistry": "The config.toml file you selected must contain registries table",
1214
"loc.messages.AuthenticatingThisConfigToml": "Adding authentication for registry listed in this config.toml file at %s",
13-
"loc.messages.AddingAuthRegistry": "Adding auth for registry: %s with token name: %s"
15+
"loc.messages.AddingAuthRegistry": "Adding auth for registry: %s with token name: %s",
16+
"loc.messages.AddingAuthExternalRegistry": "Adding auth for external registry: %s with token name: %s"
1417
}

Tasks/CargoAuthenticateV0/Tests/package-lock.json

Lines changed: 1 addition & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
{
2-
"name": "cargo-authenticate-tests",
3-
"version": "1.0.0",
4-
"description": "Azure Pipelines Cargo Authenticate V0 Task Tests",
5-
"main": "L0.js",
6-
"scripts": {
7-
"test": "echo \"Error: no test specified\" && exit 1"
8-
},
9-
"repository": {
10-
"type": "git",
11-
"url": "git+ssh://[email protected]/Microsoft/azure-pipelines-tasks.git"
12-
},
13-
"author": "Microsoft Corporation",
14-
"license": "MIT",
15-
"bugs": {
16-
"url": "https://github.com/Microsoft/azure-pipelines-tasks/issues"
17-
},
18-
"homepage": "https://github.com/Microsoft/azure-pipelines-tasks#readme"
19-
}
20-
2+
"name": "cargo-authenticate-tests",
3+
"version": "1.0.0",
4+
"description": "Azure Pipelines Cargo Authenticate V0 Task Tests",
5+
"main": "L0.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1"
8+
},
9+
"repository": {
10+
"type": "git",
11+
"url": "git+ssh://[email protected]/Microsoft/azure-pipelines-tasks.git"
12+
},
13+
"author": "Microsoft Corporation",
14+
"license": "MIT",
15+
"bugs": {
16+
"url": "https://github.com/Microsoft/azure-pipelines-tasks/issues"
17+
},
18+
"homepage": "https://github.com/Microsoft/azure-pipelines-tasks#readme"
19+
}

Tasks/CargoAuthenticateV0/cargoauthenticatemain.ts

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import * as constants from './constants';
66
import * as util from 'azure-pipelines-tasks-packaging-common/util';
77
import * as pkgLocationUtils from 'azure-pipelines-tasks-packaging-common/locationUtilities';
88
import * as url from 'url';
9+
import * as base64 from 'base-64';
10+
import * as utf8 from 'utf8';
11+
import { ServiceConnection, getPackagingServiceConnections, ServiceConnectionAuthType, UsernamePasswordServiceConnection, TokenServiceConnection } from "azure-pipelines-tasks-artifacts-common/serviceConnectionUtils";
912

1013
async function main(): Promise<void> {
1114
tl.setResourcePath(path.join(__dirname, 'task.json'));
@@ -49,16 +52,48 @@ async function main(): Promise<void> {
4952
});
5053

5154
const localAccesstoken = `Bearer ${tl.getVariable('System.AccessToken')}`;
55+
const serviceConnections = getPackagingServiceConnections('cargoServiceConnections');
56+
let externalServiceConnections: ServiceConnection[] = [];
57+
58+
for (let serviceConnection of serviceConnections) {
59+
switch (serviceConnection.authType) {
60+
case (ServiceConnectionAuthType.UsernamePassword):
61+
externalServiceConnections.push(serviceConnection);
62+
break;
63+
case (ServiceConnectionAuthType.Token):
64+
// We only support crates.io
65+
if (url.parse(serviceConnection.packageSource.uri).host !== "crates.io") throw Error(tl.loc('Error_InvalidServiceConnection', serviceConnection.packageSource.uri));
66+
67+
const tokenAuthInfo = serviceConnection as TokenServiceConnection;
68+
tl.debug(`Detected token credentials for '${serviceConnection.packageSource.uri}'`);
69+
tl.setVariable("CARGO_REGISTRY_TOKEN", tokenAuthInfo.token)
70+
break;
71+
default:
72+
throw Error(tl.loc('Error_InvalidServiceConnection', serviceConnection.packageSource.uri));
73+
}
74+
}
75+
5276
for (let registry of Object.keys(result.registries)) {
5377
const registryUrl = url.parse(result.registries[registry].index);
54-
if(registryUrl && registryUrl.host && collectionHosts.indexOf(registryUrl.host.toLowerCase()) >= 0) {
55-
const tokenName = `CARGO_REGISTRIES_${registry.toLocaleUpperCase().replace("-", "_")}_TOKEN`;
56-
tl.debug(tl.loc('AddingAuthRegistry', registry, tokenName));
57-
tl.setVariable(tokenName, localAccesstoken);
78+
let tokenName = `CARGO_REGISTRIES_${registry.toLocaleUpperCase().replace("-", "_")}_TOKEN`;
79+
if (registryUrl && registryUrl.host && collectionHosts.indexOf(registryUrl.host.toLowerCase()) >= 0) {
80+
let currentRegistry : string;
81+
for (let serviceConnection of externalServiceConnections) {
82+
if (url.parse(serviceConnection.packageSource.uri).href === url.parse(result.registries[registry].index.replace("sparse+", "")).href) {
83+
const usernamePasswordAuthInfo = serviceConnection as UsernamePasswordServiceConnection;
84+
currentRegistry = registry;
85+
tl.debug(`Detected username/password or PAT credentials for '${serviceConnection.packageSource.uri}'`);
86+
tl.debug(tl.loc('AddingAuthExternalRegistry', registry, tokenName));
87+
tl.setVariable(tokenName, `Basic ${base64.encode(utf8.encode(`${usernamePasswordAuthInfo.username}:${usernamePasswordAuthInfo.password}`))}`);
88+
}
89+
}
90+
// Default to internal registry if no token has been set yet
91+
if (!currentRegistry) {
92+
tl.debug(tl.loc('AddingAuthRegistry', registry, tokenName));
93+
tl.setVariable(tokenName, localAccesstoken);
94+
}
5895
}
59-
}
60-
61-
//External endpoints
96+
}
6297
}
6398

6499
catch(error) {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export class CargoAuthenticateTaskInput {
22
public static ConfigFile: string = 'configFile';
3+
public static cargoServiceConnections: string = 'cargoServiceConnections';
34
}

0 commit comments

Comments
 (0)