Skip to content
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
a9ee69b
add logs
EyalDelarea Apr 29, 2025
799aeb9
add logs
EyalDelarea Apr 29, 2025
a3ecdb4
Default audience
EyalDelarea Apr 29, 2025
a765ad8
dont pass audience to exchange command
EyalDelarea Apr 29, 2025
cc0efe9
Change audience default value
EyalDelarea Apr 30, 2025
119f08f
Test
EyalDelarea Apr 30, 2025
5f4b8e1
Test
EyalDelarea Apr 30, 2025
44c0113
Test
EyalDelarea May 4, 2025
c5a21ca
Test
EyalDelarea May 4, 2025
bbafc02
Test
EyalDelarea May 4, 2025
c49d377
Test
EyalDelarea May 4, 2025
7640918
Extract audience values
EyalDelarea May 4, 2025
abe4d6d
Extract audience values
EyalDelarea May 4, 2025
f48402a
test
EyalDelarea May 4, 2025
7cf343a
test
EyalDelarea May 4, 2025
308692b
test
EyalDelarea May 4, 2025
e6c5b6f
Update test workflow
EyalDelarea May 4, 2025
394b82e
Update workflow
EyalDelarea May 4, 2025
10390a3
Update description
EyalDelarea May 4, 2025
0969cbd
Run local tests
EyalDelarea May 4, 2025
74a5010
Run local tests
EyalDelarea May 4, 2025
ae3fcd9
Test
EyalDelarea May 4, 2025
1b779a5
Test
EyalDelarea May 4, 2025
9173db9
Ready to merge
EyalDelarea May 4, 2025
ca3e7a8
CR
EyalDelarea May 4, 2025
84750a1
CR
EyalDelarea May 4, 2025
e9c6e84
Fix matrix
EyalDelarea May 4, 2025
8a0f100
Fix matrix
EyalDelarea May 4, 2025
e58752c
Remove unneeded step
EyalDelarea May 4, 2025
4e87fea
Test change default
EyalDelarea May 4, 2025
8a6cf1c
Test change default
EyalDelarea May 4, 2025
6b1493b
Test
EyalDelarea May 4, 2025
41b1c2d
Test
EyalDelarea May 4, 2025
b7bf892
Test
EyalDelarea May 4, 2025
e3d8977
Test
EyalDelarea May 4, 2025
7ee09c3
Test
EyalDelarea May 4, 2025
a8703c2
local test
EyalDelarea May 4, 2025
8341c09
case sensitive default github
EyalDelarea May 4, 2025
c123c18
Test all cases locally
EyalDelarea May 4, 2025
b634528
Fix image name
EyalDelarea May 4, 2025
0f899df
Prepare workflow for merge
EyalDelarea May 4, 2025
8d6dd55
test locally
EyalDelarea May 4, 2025
6175f37
Edit comments
EyalDelarea May 5, 2025
99d04f2
Test renames
EyalDelarea May 5, 2025
48afeaa
Prepare action for merge
EyalDelarea May 5, 2025
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
76 changes: 43 additions & 33 deletions .github/workflows/oidc-integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ name: OIDC Integration Test
on:
push:
branches:
- master
#- master
- "**"
# Triggers the workflow on labeled PRs only.
pull_request_target:
types: [ labeled ]
Expand All @@ -23,30 +24,17 @@ permissions:
contents: read

jobs:
oidc-test:
generate-platform-oidc-integration:
strategy:
fail-fast: false
matrix:
os: [ ubuntu, macos, windows ]
cli-version: [ '2.74.1', '2.75.0','latest' ]
runs-on: ${{ matrix.os }}-latest
name: OIDC Test - ${{ matrix.cli-version }} on ${{ matrix.os }}
env:
JFROG_CLI_LOG_LEVEL: DEBUG

# Test with a default and provided audience value
audience_value: ['', 'test-audience']
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}

# Setup OIDC platform integration
- name: Generate unique OIDC provider name
id: gen-oidc
shell: bash
run: |
cli_version="${{ matrix.cli-version }}" && cli_version="${cli_version//./-}"
echo "oidc_provider_name=oidc-integration-${cli_version}-${{ matrix.os }}-$(date +%s)" >> "$GITHUB_OUTPUT"
run: echo "oidc_provider_name=oidc-integration-${{ matrix.audience_value }}-${{ github.run_id }}" >> "$GITHUB_OUTPUT"

- name: Create OpenID Connect integration
shell: bash
Expand All @@ -55,46 +43,62 @@ jobs:
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${{ secrets.JFROG_PLATFORM_RT_TOKEN }}" \
-d '{
"name": "${{ steps.gen-oidc.outputs.oidc_provider_name }}",
"name": "oidc-integration-${{ matrix.audience_value }}-${{ github.run_id }}",
"issuer_url": "https://token.actions.githubusercontent.com",
"provider_type": "GitHub",
"enable_permissive_configuration": "true",
"description": "Test configuration for CLI version ${{ matrix.cli-version }}"
"audience": "${{ matrix.audience_value }}",
"enable_permissive_configuration": true,
"description": "Temp integration for testing OIDC with audience: ${{ matrix.audience_value }}"
}'

- name: Create OIDC Identity Mapping
shell: bash
run: |
curl -X POST "${{ secrets.JFROG_PLATFORM_URL }}/access/api/v1/oidc/${{ steps.gen-oidc.outputs.oidc_provider_name }}/identity_mappings" \
-H 'Content-Type: application/json' \
curl -X POST "${{ secrets.JFROG_PLATFORM_URL }}/access/api/v1/oidc/oidc-integration-${{ matrix.audience_value }}-${{ github.run_id }}/identity_mappings" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${{ secrets.JFROG_PLATFORM_RT_TOKEN }}" \
-d '{
"name": "oidc-test-mapping",
"priority": "1",
"priority": 1,
"claims": {
"repository": "${{ github.repository_owner }}/setup-jfrog-cli"
},
"token_spec": {
"scope": "applied-permissions/groups:readers",
"expires_in": 30
"expires_in": 10
}
}'

# Setup
oidc-test:
needs: generate-platform-oidc-integration
strategy:
fail-fast: false
matrix:
os: [ubuntu, macos, windows]
cli-version: ['2.74.1', '2.75.0', 'latest']
audience_value: ['', 'test-audience']
runs-on: ${{ matrix.os }}-latest
env:
JFROG_CLI_LOG_LEVEL: DEBUG
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}

- name: Setup JFrog CLI
id: setup-jfrog-cli
uses: ./
env:
JF_URL: ${{ secrets.JFROG_PLATFORM_URL }}
with:
version: ${{ matrix.cli-version }}
oidc-provider-name: ${{ steps.gen-oidc.outputs.oidc_provider_name }}
oidc-provider-name: oidc-integration-${{ matrix.audience_value }}-${{ github.run_id }}
oidc-audience: ${{ matrix.audience_value }}

# validate successful OIDC configuration
- name: Test JFrog CLI connectivity
run: jf rt ping

# Validate step outputs
- name: Validate user output
shell: bash
run: test -n "${{ steps.setup-jfrog-cli.outputs.oidc-user }}"
Expand All @@ -103,10 +107,16 @@ jobs:
shell: bash
run: test -n "${{ steps.setup-jfrog-cli.outputs.oidc-token }}"

# Cleanup
cleanup-oidc-integration:
needs: oidc-test
if: always()
strategy:
matrix:
audience_value: ['', 'test-audience']
runs-on: ubuntu-latest
steps:
- name: Delete OIDC integration
shell: bash
if: always()
run: |
curl -X DELETE "${{ secrets.JFROG_PLATFORM_URL }}/access/api/v1/oidc/${{ steps.gen-oidc.outputs.oidc_provider_name }}" \
curl -X DELETE "${{ secrets.JFROG_PLATFORM_URL }}/access/api/v1/oidc/oidc-integration-${{ matrix.audience_value }}-${{ github.run_id }}" \
-H "Authorization: Bearer ${{ secrets.JFROG_PLATFORM_RT_TOKEN }}"
8 changes: 6 additions & 2 deletions lib/oidc-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class OidcUtils {
throw new Error(`JF_URL must be provided when oidc-provider-name is specified`);
}
// Get OIDC token ID from GitHub
jfrogCredentials.oidcTokenId = yield this.getIdToken(jfrogCredentials.oidcAudience || '');
jfrogCredentials.oidcTokenId = yield this.getIdToken(jfrogCredentials.oidcAudience);
// Version should be more than min version
// If CLI_REMOTE_ARG specified, we have to fetch token before we can download the CLI.
if (this.isCLIVersionOidcSupported() && !core.getInput(utils_1.Utils.CLI_REMOTE_ARG)) {
Expand All @@ -90,7 +90,11 @@ class OidcUtils {
if (creds.oidcProviderName === undefined || creds.oidcTokenId === undefined || creds.jfrogUrl === undefined) {
throw new Error('Missing one or more required fields: OIDC provider name, token ID, or JFrog Platform URL.');
}
output = yield utils_1.Utils.runCliAndGetOutput(['eot', creds.oidcProviderName, creds.oidcTokenId, '--url', creds.jfrogUrl, '--oidc-audience', creds.oidcAudience || 'jfrog-github'], { silent: true });
const args = ['eot', creds.oidcProviderName, creds.oidcTokenId, '--url', creds.jfrogUrl];
if (creds.oidcAudience !== "") {
args.push('--oidc-audience', creds.oidcAudience);
}
output = yield utils_1.Utils.runCliAndGetOutput(args, { silent: true });
const { accessToken, username } = this.extractValuesFromOIDCToken(output);
this.setOidcStepOutputs(username, accessToken);
return accessToken;
Expand Down
4 changes: 1 addition & 3 deletions lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class Utils {
username: process.env.JF_USER,
password: process.env.JF_PASSWORD,
oidcProviderName: core.getInput(Utils.OIDC_INTEGRATION_PROVIDER_NAME),
oidcAudience: core.getInput(Utils.OIDC_AUDIENCE_ARG) || Utils.DEFAULT_OIDC_AUDIENCE,
oidcAudience: core.getInput(Utils.OIDC_AUDIENCE_ARG) || '',
oidcTokenId: '',
};
if (jfrogCredentials.password && !jfrogCredentials.username) {
Expand Down Expand Up @@ -184,7 +184,6 @@ class Utils {
* @name password - JFrog Platform basic authentication
* @name accessToken - Jfrog Platform access token
* @name oidcProviderName - OpenID Connect provider name defined in the JFrog Platform
* @name oidcAudience - JFrog Platform OpenID Connect audience
*/
let url = jfrogCredentials.jfrogUrl;
let user = jfrogCredentials.username;
Expand Down Expand Up @@ -474,4 +473,3 @@ Utils.JOB_SUMMARY_DISABLE = 'disable-job-summary';
Utils.AUTO_BUILD_PUBLISH_DISABLE = 'disable-auto-build-publish';
// Custom server ID input
Utils.CUSTOM_SERVER_ID = 'custom-server-id';
Utils.DEFAULT_OIDC_AUDIENCE = 'jfrog-github';
11 changes: 6 additions & 5 deletions src/oidc-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class OidcUtils {
throw new Error(`JF_URL must be provided when oidc-provider-name is specified`);
}
// Get OIDC token ID from GitHub
jfrogCredentials.oidcTokenId = await this.getIdToken(jfrogCredentials.oidcAudience || '');
jfrogCredentials.oidcTokenId = await this.getIdToken(jfrogCredentials. oidcAudience);

// Version should be more than min version
// If CLI_REMOTE_ARG specified, we have to fetch token before we can download the CLI.
Expand Down Expand Up @@ -69,10 +69,11 @@ export class OidcUtils {
throw new Error('Missing one or more required fields: OIDC provider name, token ID, or JFrog Platform URL.');
}

output = await Utils.runCliAndGetOutput(
['eot', creds.oidcProviderName, creds.oidcTokenId, '--url', creds.jfrogUrl, '--oidc-audience', creds.oidcAudience || 'jfrog-github'],
{ silent: true },
);
const args = ['eot', creds.oidcProviderName, creds.oidcTokenId, '--url', creds.jfrogUrl];
if (creds.oidcAudience !== "") {
args.push('--oidc-audience', creds.oidcAudience);
}
output = await Utils.runCliAndGetOutput(args, { silent: true });

const { accessToken, username }: CliExchangeTokenResponse = this.extractValuesFromOIDCToken(output);
this.setOidcStepOutputs(username, accessToken);
Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface JfrogCredentials {
accessToken?: string;
oidcProviderName?: string;
oidcTokenId?: string;
oidcAudience?: string;
oidcAudience : string;
}

/**
Expand Down
4 changes: 1 addition & 3 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ export class Utils {
public static readonly AUTO_BUILD_PUBLISH_DISABLE: string = 'disable-auto-build-publish';
// Custom server ID input
private static readonly CUSTOM_SERVER_ID: string = 'custom-server-id';
private static DEFAULT_OIDC_AUDIENCE: string = 'jfrog-github';

/**
* Gathers JFrog's credentials from environment variables and delivers them in a JfrogCredentials structure
Expand All @@ -66,7 +65,7 @@ export class Utils {
username: process.env.JF_USER,
password: process.env.JF_PASSWORD,
oidcProviderName: core.getInput(Utils.OIDC_INTEGRATION_PROVIDER_NAME),
oidcAudience: core.getInput(Utils.OIDC_AUDIENCE_ARG) || Utils.DEFAULT_OIDC_AUDIENCE,
oidcAudience: core.getInput(Utils.OIDC_AUDIENCE_ARG) || '',
oidcTokenId: '',
} as JfrogCredentials;

Expand Down Expand Up @@ -204,7 +203,6 @@ export class Utils {
* @name password - JFrog Platform basic authentication
* @name accessToken - Jfrog Platform access token
* @name oidcProviderName - OpenID Connect provider name defined in the JFrog Platform
* @name oidcAudience - JFrog Platform OpenID Connect audience
*/
let url: string | undefined = jfrogCredentials.jfrogUrl;
let user: string | undefined = jfrogCredentials.username;
Expand Down
18 changes: 18 additions & 0 deletions test/main.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,24 @@ describe('Collect JFrog Credentials from env vars exceptions', () => {
process.env['JF_PASSWORD'] = password;
expect(() => Utils.collectJfrogCredentialsFromEnvVars()).toThrow(new Error(exception));
});

test('collectJfrogCredentialsFromEnvVars should return default values when no environment variables are set', () => {
// Ensure no relevant environment variables are set
delete process.env['JF_URL'];
delete process.env['JF_ACCESS_TOKEN'];
delete process.env['JF_USER'];
delete process.env['JF_PASSWORD'];

// Call the function
const jfrogCredentials: JfrogCredentials = Utils.collectJfrogCredentialsFromEnvVars();

// Verify default values
expect(jfrogCredentials.jfrogUrl).toBeUndefined();
expect(jfrogCredentials.accessToken).toBeUndefined();
expect(jfrogCredentials.username).toBeUndefined();
expect(jfrogCredentials.password).toBeUndefined();
expect(jfrogCredentials.oidcAudience).toEqual("")
});
});

async function testConfigCommand(expectedServerId: string) {
Expand Down
1 change: 1 addition & 0 deletions test/oidc-utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ describe('OidcUtils', (): void => {
it('should throw if creds are missing required fields', async (): Promise<void> => {
const incompleteCreds: JfrogCredentials = {
jfrogUrl: 'https://example.jfrog.io',
oidcAudience: ''
// missing provider and token ID
};

Expand Down
Loading