Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix authentication flows #122

Merged
merged 3 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/oidc-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
"name": "oidc-test-identity-mapping",
"priority": "1",
"claims": {
"sub": "repo:jfrog/setup-jfrog-cli:ref:refs/heads/main",
"sub": "repo:${{ github.repository_owner }}/setup-jfrog-cli:ref:${{ github.ref }}",
"iss": "https://token.actions.githubusercontent.com"
},
"token_spec": {
Expand All @@ -72,7 +72,7 @@ jobs:

- name: Test JFrog CLI
run: |
jf rt ping
jf rt s "some-repo/"

# Removing the OIDC integration will remove the Identity Mapping as well
- name: Delete OIDC integration
Expand Down
37 changes: 17 additions & 20 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,11 @@ class Utils {
static getJfrogCredentials() {
return __awaiter(this, void 0, void 0, function* () {
let jfrogCredentials = this.collectJfrogCredentialsFromEnvVars();
if (!jfrogCredentials.jfrogUrl) {
return jfrogCredentials;
}
// If the required credentials, such as the access token or a combination of username and password, are available, the process terminates without triggering the OIDC flow
if (jfrogCredentials.accessToken || (jfrogCredentials.username && jfrogCredentials.password)) {
if (!jfrogCredentials.jfrogUrl || jfrogCredentials.password || jfrogCredentials.accessToken || !process.env.ACTIONS_ID_TOKEN_REQUEST_URL) {
yahavi marked this conversation as resolved.
Show resolved Hide resolved
// Use JF_ENV or the credentials found in the environment variables
return jfrogCredentials;
}
core.info("JF_ACCESS_TOKEN and JF_USER + JF_PASSWORD weren't found. Getting access token using OpenID Connect");
core.info('The JFrog platform credentials were not configured. Obtaining an access token through OpenID Connect.');
const audience = core.getInput(Utils.OIDC_AUDIENCE_ARG);
let jsonWebToken;
try {
Expand All @@ -79,23 +76,20 @@ class Utils {
/**
* Gathers JFrog's credentials from environment variables and delivers them in a JfrogCredentials structure
* @returns JfrogCredentials struct with all credentials found in environment variables
* @throws Error if a password provided without a username
*/
static collectJfrogCredentialsFromEnvVars() {
let jfrogCredentials = {};
core.debug('Searching for JF_URL');
if (process.env.JF_URL) {
core.debug('JF_URL found');
jfrogCredentials.jfrogUrl = process.env.JF_URL;
let jfrogCredentials = {
jfrogUrl: process.env.JF_URL,
accessToken: process.env.JF_ACCESS_TOKEN,
username: process.env.JF_USER,
password: process.env.JF_PASSWORD,
};
if (jfrogCredentials.password && !jfrogCredentials.username) {
throw new Error('JF_PASSWORD is configured, but the JF_USER environment variable was not set.');
yahavi marked this conversation as resolved.
Show resolved Hide resolved
}
core.debug('Searching for JF_ACCESS_TOKEN, JF_USER and JF_PASSWORD');
if (process.env.JF_ACCESS_TOKEN) {
core.debug('JF_ACCESS_TOKEN found');
jfrogCredentials.accessToken = process.env.JF_ACCESS_TOKEN;
}
if (process.env.JF_USER && process.env.JF_PASSWORD) {
core.debug('JF_USER and JF_PASSWORD found');
jfrogCredentials.username = process.env.JF_USER;
jfrogCredentials.password = process.env.JF_PASSWORD;
if (jfrogCredentials.username && !jfrogCredentials.accessToken && !jfrogCredentials.password) {
throw new Error('JF_USER is configured, but the JF_PASSWORD or JF_ACCESS_TOKEN environment variables were not set.');
}
return jfrogCredentials;
}
Expand Down Expand Up @@ -125,6 +119,9 @@ class Utils {
const responseString = yield response.readBody();
const responseJson = JSON.parse(responseString);
jfrogCredentials.accessToken = responseJson.access_token;
if (jfrogCredentials.accessToken) {
core.setSecret(jfrogCredentials.accessToken);
}
return jfrogCredentials;
});
}
Expand Down
41 changes: 18 additions & 23 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,12 @@ export class Utils {
*/
public static async getJfrogCredentials(): Promise<JfrogCredentials> {
let jfrogCredentials: JfrogCredentials = this.collectJfrogCredentialsFromEnvVars();
if (!jfrogCredentials.jfrogUrl) {
if (!jfrogCredentials.jfrogUrl || jfrogCredentials.password || jfrogCredentials.accessToken || !process.env.ACTIONS_ID_TOKEN_REQUEST_URL) {
yahavi marked this conversation as resolved.
Show resolved Hide resolved
// Use JF_ENV or the credentials found in the environment variables
return jfrogCredentials;
}

// If the required credentials, such as the access token or a combination of username and password, are available, the process terminates without triggering the OIDC flow
if (jfrogCredentials.accessToken || (jfrogCredentials.username && jfrogCredentials.password)) {
return jfrogCredentials;
}

core.info("JF_ACCESS_TOKEN and JF_USER + JF_PASSWORD weren't found. Getting access token using OpenID Connect");
core.info('The JFrog platform credentials were not configured. Obtaining an access token through OpenID Connect.');
const audience: string = core.getInput(Utils.OIDC_AUDIENCE_ARG);
let jsonWebToken: string | undefined;
try {
Expand All @@ -79,25 +75,21 @@ export class Utils {
/**
* Gathers JFrog's credentials from environment variables and delivers them in a JfrogCredentials structure
* @returns JfrogCredentials struct with all credentials found in environment variables
* @throws Error if a password provided without a username
*/
public static collectJfrogCredentialsFromEnvVars(): JfrogCredentials {
let jfrogCredentials: JfrogCredentials = {} as JfrogCredentials;
core.debug('Searching for JF_URL');
if (process.env.JF_URL) {
core.debug('JF_URL found');
jfrogCredentials.jfrogUrl = process.env.JF_URL;
let jfrogCredentials: JfrogCredentials = {
jfrogUrl: process.env.JF_URL,
accessToken: process.env.JF_ACCESS_TOKEN,
username: process.env.JF_USER,
password: process.env.JF_PASSWORD,
} as JfrogCredentials;

if (jfrogCredentials.password && !jfrogCredentials.username) {
throw new Error('JF_PASSWORD is configured, but the JF_USER environment variable was not set.');
}

core.debug('Searching for JF_ACCESS_TOKEN, JF_USER and JF_PASSWORD');
if (process.env.JF_ACCESS_TOKEN) {
core.debug('JF_ACCESS_TOKEN found');
jfrogCredentials.accessToken = process.env.JF_ACCESS_TOKEN;
}

if (process.env.JF_USER && process.env.JF_PASSWORD) {
core.debug('JF_USER and JF_PASSWORD found');
jfrogCredentials.username = process.env.JF_USER;
jfrogCredentials.password = process.env.JF_PASSWORD;
if (jfrogCredentials.username && !jfrogCredentials.accessToken && !jfrogCredentials.password) {
throw new Error('JF_USER is configured, but the JF_PASSWORD or JF_ACCESS_TOKEN environment variables were not set.');
}
return jfrogCredentials;
}
Expand Down Expand Up @@ -130,6 +122,9 @@ export class Utils {
const responseString: string = await response.readBody();
const responseJson: TokenExchangeResponseData = JSON.parse(responseString);
jfrogCredentials.accessToken = responseJson.access_token;
if (jfrogCredentials.accessToken) {
core.setSecret(jfrogCredentials.accessToken);
}
return jfrogCredentials;
}

Expand Down
46 changes: 18 additions & 28 deletions test/main.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ describe('Collect credentials from environment variables test', () => {
];

test.each(cases)(
'Checking Jfrog credentials struct for url: %s, access token %s, username: %s, password: %s',
'Checking JFrog credentials struct for url: %s, access token %s, username: %s, password: %s',
(jfrogUrl, accessToken, username, password) => {
process.env['JF_URL'] = jfrogUrl;
process.env['JF_ACCESS_TOKEN'] = accessToken;
Expand All @@ -93,53 +93,43 @@ describe('Collect credentials from environment variables test', () => {
if (jfrogUrl) {
expect(jfrogCredentials.jfrogUrl).toEqual(jfrogUrl);
} else {
expect(jfrogCredentials.jfrogUrl).toBeUndefined();
expect(jfrogCredentials.jfrogUrl).toBeFalsy();
}

if (accessToken) {
expect(jfrogCredentials.accessToken).toEqual(accessToken);
} else {
expect(jfrogCredentials.accessToken).toBeUndefined();
expect(jfrogCredentials.accessToken).toBeFalsy();
}

if (username) {
expect(jfrogCredentials.username).toEqual(username);
} else {
expect(jfrogCredentials.username).toBeUndefined();
expect(jfrogCredentials.username).toBeFalsy();
}

if (password) {
expect(jfrogCredentials.password).toEqual(password);
} else {
expect(jfrogCredentials.password).toBeUndefined();
expect(jfrogCredentials.password).toBeFalsy();
}
},
);
});

test('Collect JFrog Credentials from env vars', async () => {
process.env['JF_URL'] = '';
let jfrogCredentials: JfrogCredentials = Utils.collectJfrogCredentialsFromEnvVars();
expect(jfrogCredentials.jfrogUrl).toBeUndefined();
expect(jfrogCredentials.username).toBeUndefined();
expect(jfrogCredentials.password).toBeUndefined();
expect(jfrogCredentials.accessToken).toBeUndefined();

process.env['JF_URL'] = 'https://my-server.io';
process.env['JF_ACCESS_TOKEN'] = 'my-access-token';
jfrogCredentials = Utils.collectJfrogCredentialsFromEnvVars();
expect(jfrogCredentials.jfrogUrl).toEqual('https://my-server.io');
expect(jfrogCredentials.username).toBeUndefined();
expect(jfrogCredentials.password).toBeUndefined();
expect(jfrogCredentials.accessToken).toEqual('my-access-token');

process.env['JF_USER'] = 'user';
process.env['JF_PASSWORD'] = 'password';
jfrogCredentials = Utils.collectJfrogCredentialsFromEnvVars();
expect(jfrogCredentials.jfrogUrl).toEqual('https://my-server.io');
expect(jfrogCredentials.username).toEqual('user');
expect(jfrogCredentials.password).toEqual('password');
expect(jfrogCredentials.accessToken).toEqual('my-access-token');
describe('Collect JFrog Credentials from env vars exceptions', () => {
let cases: string[][] = [
// [JF_USER, JF_PASSWORD, EXCEPTION]
['', 'password', 'JF_PASSWORD is configured, but the JF_USER environment variable was not set.'],
['user', '', 'JF_USER is configured, but the JF_PASSWORD or JF_ACCESS_TOKEN environment variables were not set.'],
];

test.each(cases)('Checking JFrog credentials struct for username: %s, password: %s', (username, password, exception) => {
process.env['JF_ACCESS_TOKEN'] = '';
process.env['JF_USER'] = username;
process.env['JF_PASSWORD'] = password;
expect(() => Utils.collectJfrogCredentialsFromEnvVars()).toThrow(new Error(exception));
});
});

test('Get separate env config', async () => {
Expand Down
Loading