Skip to content

Commit 013b9a9

Browse files
committed
keep old code as legacy
1 parent 6dbba1c commit 013b9a9

File tree

4 files changed

+139
-37
lines changed

4 files changed

+139
-37
lines changed

lib/utils.js

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const core_1 = require("@octokit/core");
4646
const github = __importStar(require("@actions/github"));
4747
const zlib_1 = require("zlib");
4848
const util_1 = require("util");
49+
const legacyOidc_1 = require("./legacyOidc");
4950
class Utils {
5051
/**
5152
* Retrieves server credentials for accessing JFrog's server
@@ -57,11 +58,28 @@ class Utils {
5758
return __awaiter(this, void 0, void 0, function* () {
5859
const jfrogCredentials = this.collectJfrogCredentialsFromEnvVars();
5960
if (jfrogCredentials.oidcProviderName) {
60-
return yield this.setOidcTokenID(jfrogCredentials);
61+
if (this.isCliSupportsOidc()) {
62+
return yield this.setOidcTokenID(jfrogCredentials);
63+
}
64+
else {
65+
// Fallback to legacy OIDC flow
66+
return yield legacyOidc_1.LegacyOidc.handleLegacyOidcFlow(jfrogCredentials);
67+
}
6168
}
6269
return jfrogCredentials;
6370
});
6471
}
72+
/**
73+
* Determine if the currently configured CLI version supports native OIDC token injection.
74+
*/
75+
static isCliSupportsOidc() {
76+
var _a;
77+
const version = (_a = core.getInput(this.CLI_VERSION_ARG)) === null || _a === void 0 ? void 0 : _a.toLowerCase();
78+
if (version === 'latest') {
79+
return true;
80+
}
81+
return !(0, semver_1.lt)(version, Utils.MIN_OIDC_SUPPORTED_VERSION);
82+
}
6583
/**
6684
* @param jfrogCredentials - The existing JFrog credentials
6785
* @returns The updated JfrogCredentials with the OIDC tokenID
@@ -112,14 +130,15 @@ class Utils {
112130
if (jfrogCredentials.password) {
113131
core.setSecret(jfrogCredentials.password);
114132
}
115-
Utils.validateOidcSupported(jfrogCredentials);
133+
Utils.validateOidcNotWithRepositorySettings(jfrogCredentials);
116134
return jfrogCredentials;
117135
}
118136
/**
119137
* Validates OIDC auth method is supported by the JFrog CLI version
138+
* // TODO rename or change
120139
* @param jfrogCredentials
121140
*/
122-
static validateOidcSupported(jfrogCredentials) {
141+
static validateOidcNotWithRepositorySettings(jfrogCredentials) {
123142
const version = core.getInput(Utils.CLI_VERSION_ARG);
124143
if (!!version && version.toLowerCase() === 'latest') {
125144
return;
@@ -129,12 +148,6 @@ class Utils {
129148
if (!!downloadRepository && !jfrogCredentials.oidcProviderName) {
130149
throw new Error(`Download repository feature is not supported while using OIDC.`);
131150
}
132-
if (!!version) {
133-
if (jfrogCredentials.oidcProviderName && (0, semver_1.lt)(version, Utils.MIN_OIDC_SUPPORTED_VERSION)) {
134-
throw new Error(`JFrog CLI version ${version} does not support OIDC (requires >= ${Utils.MIN_OIDC_SUPPORTED_VERSION}).\n` +
135-
`Either upgrade your CLI or downgrade the setup-jfrog-cli action to v4.5.6.`);
136-
}
137-
}
138151
}
139152
static getAndAddCliToPath(jfrogCredentials) {
140153
return __awaiter(this, void 0, void 0, function* () {

src/legacyOidc.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import * as core from '@actions/core';
2+
import { HttpClient, HttpClientResponse } from '@actions/http-client';
3+
import { JfrogCredentials } from './utils';
4+
import { load } from 'js-yaml';
5+
import * as fs from 'fs';
6+
import * as path from 'path';
7+
8+
type ApplicationConfig = {
9+
application?: {
10+
key?: string;
11+
};
12+
};
13+
14+
export interface TokenExchangeResponseData {
15+
access_token: string;
16+
errors: string;
17+
}
18+
19+
type TokenExchangeRequest = {
20+
grant_type: string;
21+
subject_token_type: string;
22+
subject_token: string;
23+
provider_name: string;
24+
project_key: string;
25+
gh_job_id: string;
26+
gh_run_id: string;
27+
gh_repo: string;
28+
application_key: string;
29+
};
30+
31+
export class LegacyOidc {
32+
public static async handleLegacyOidcFlow(jfrogCredentials: JfrogCredentials): Promise<JfrogCredentials> {
33+
core.info('Obtaining an access token through OpenID Connect (legacy fallback)...');
34+
35+
const audience: string = core.getInput('oidc-audience');
36+
let jsonWebToken: string;
37+
try {
38+
core.debug('Fetching JSON web token (legacy)');
39+
jsonWebToken = await core.getIDToken(audience);
40+
} catch (error: any) {
41+
throw new Error(`Getting OpenID Connect JSON web token failed: ${error.message}`);
42+
}
43+
44+
const applicationKey: string = await this.getApplicationKey();
45+
return await this.exchangeToken(jfrogCredentials, jsonWebToken, applicationKey);
46+
}
47+
48+
private static async exchangeToken(jfrogCredentials: JfrogCredentials, jsonWebToken: string, applicationKey: string): Promise<JfrogCredentials> {
49+
const oidcProviderName: string = jfrogCredentials.oidcProviderName!;
50+
const exchangeUrl: string = `${jfrogCredentials.jfrogUrl!.replace(/\/$/, '')}/access/api/v1/oidc/token`;
51+
52+
const data: TokenExchangeRequest = {
53+
grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',
54+
subject_token_type: 'urn:ietf:params:oauth:token-type:id_token',
55+
subject_token: jsonWebToken,
56+
provider_name: oidcProviderName,
57+
project_key: process.env.JF_PROJECT || '',
58+
gh_job_id: process.env.GITHUB_WORKFLOW || '',
59+
gh_run_id: process.env.GITHUB_RUN_ID || '',
60+
gh_repo: process.env.GITHUB_REPOSITORY || '',
61+
application_key: applicationKey,
62+
};
63+
64+
const httpClient: HttpClient = new HttpClient();
65+
const response: HttpClientResponse = await httpClient.post(exchangeUrl, JSON.stringify(data), {
66+
'Content-Type': 'application/json',
67+
});
68+
const responseBody: string = await response.readBody();
69+
const responseJson: TokenExchangeResponseData = JSON.parse(responseBody);
70+
71+
if (responseJson.errors) {
72+
throw new Error(`OIDC token exchange failed: ${JSON.stringify(responseJson.errors)}`);
73+
}
74+
75+
core.exportVariable('JFROG_CLI_USAGE_CONFIG_OIDC', 'TRUE');
76+
core.exportVariable('JFROG_CLI_USAGE_OIDC_USED', 'TRUE');
77+
78+
jfrogCredentials.accessToken = responseJson.access_token;
79+
return jfrogCredentials;
80+
}
81+
82+
private static async getApplicationKey(): Promise<string> {
83+
const configFilePath: string = path.join('.jfrog', 'config.yaml');
84+
85+
if (!fs.existsSync(configFilePath)) {
86+
core.debug('JFrog config file not found');
87+
return '';
88+
}
89+
90+
const configContent: string = await fs.promises.readFile(configFilePath, 'utf-8');
91+
const configObj: ApplicationConfig = load(configContent) as ApplicationConfig;
92+
return configObj?.application?.key ?? '';
93+
}
94+
}

src/utils.ts

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { OctokitResponse } from '@octokit/types/dist-types/OctokitResponse';
1313
import * as github from '@actions/github';
1414
import { gzip } from 'zlib';
1515
import { promisify } from 'util';
16+
import { LegacyOidc } from './legacyOidc';
1617

1718
export class Utils {
1819
// eslint-disable-next-line @typescript-eslint/no-var-requires
@@ -111,11 +112,27 @@ export class Utils {
111112
const jfrogCredentials: JfrogCredentials = this.collectJfrogCredentialsFromEnvVars();
112113

113114
if (jfrogCredentials.oidcProviderName) {
114-
return await this.setOidcTokenID(jfrogCredentials);
115+
if (this.isCliSupportsOidc()) {
116+
return await this.setOidcTokenID(jfrogCredentials);
117+
} else {
118+
// Fallback to legacy OIDC flow
119+
return await LegacyOidc.handleLegacyOidcFlow(jfrogCredentials);
120+
}
115121
}
116122
return jfrogCredentials;
117123
}
118124

125+
/**
126+
* Determine if the currently configured CLI version supports native OIDC token injection.
127+
*/
128+
private static isCliSupportsOidc(): boolean {
129+
const version: string = core.getInput(this.CLI_VERSION_ARG)?.toLowerCase();
130+
if (version === 'latest') {
131+
return true;
132+
}
133+
return !lt(version, Utils.MIN_OIDC_SUPPORTED_VERSION);
134+
}
135+
119136
/**
120137
* @param jfrogCredentials - The existing JFrog credentials
121138
* @returns The updated JfrogCredentials with the OIDC tokenID
@@ -166,16 +183,17 @@ export class Utils {
166183
core.setSecret(jfrogCredentials.password);
167184
}
168185

169-
Utils.validateOidcSupported(jfrogCredentials);
186+
Utils.validateOidcNotWithRepositorySettings(jfrogCredentials);
170187

171188
return jfrogCredentials;
172189
}
173190

174191
/**
175192
* Validates OIDC auth method is supported by the JFrog CLI version
193+
* // TODO rename or change
176194
* @param jfrogCredentials
177195
*/
178-
public static validateOidcSupported(jfrogCredentials: JfrogCredentials) {
196+
public static validateOidcNotWithRepositorySettings(jfrogCredentials: JfrogCredentials) {
179197
const version: string = core.getInput(Utils.CLI_VERSION_ARG);
180198
if (!!version && version.toLowerCase() === 'latest') {
181199
return;
@@ -186,14 +204,6 @@ export class Utils {
186204
if (!!downloadRepository && !jfrogCredentials.oidcProviderName) {
187205
throw new Error(`Download repository feature is not supported while using OIDC.`);
188206
}
189-
if (!!version) {
190-
if (jfrogCredentials.oidcProviderName && lt(version, Utils.MIN_OIDC_SUPPORTED_VERSION)) {
191-
throw new Error(
192-
`JFrog CLI version ${version} does not support OIDC (requires >= ${Utils.MIN_OIDC_SUPPORTED_VERSION}).\n` +
193-
`Either upgrade your CLI or downgrade the setup-jfrog-cli action to v4.5.6.`,
194-
);
195-
}
196-
}
197207
}
198208

199209
public static async getAndAddCliToPath(jfrogCredentials: JfrogCredentials) {
@@ -881,18 +891,3 @@ export interface JfrogCredentials {
881891
oidcAudience: string | undefined;
882892
oidcTokenId: string | undefined;
883893
}
884-
885-
export interface TokenExchangeResponseData {
886-
access_token: string;
887-
errors: string;
888-
}
889-
890-
export interface JWTTokenData {
891-
sub: string;
892-
scp: string;
893-
aud: string;
894-
iss: string;
895-
exp: bigint;
896-
iat: bigint;
897-
jti: string;
898-
}

test/main.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,11 +514,11 @@ describe('Utils.validateOidcSupported', () => {
514514

515515
if (shouldThrow) {
516516
expect(() => {
517-
Utils.validateOidcSupported(jfrogCredentials);
517+
Utils.validateOidcNotWithRepositorySettings(jfrogCredentials);
518518
}).toThrow(errorMessage);
519519
} else {
520520
expect(() => {
521-
Utils.validateOidcSupported(jfrogCredentials);
521+
Utils.validateOidcNotWithRepositorySettings(jfrogCredentials);
522522
}).not.toThrow();
523523
}
524524
};

0 commit comments

Comments
 (0)