Skip to content

Commit

Permalink
Enable auth with OpenID Connect (#117)
Browse files Browse the repository at this point in the history
  • Loading branch information
eranturgeman authored Jan 17, 2024
1 parent ea63b04 commit 391668d
Show file tree
Hide file tree
Showing 199 changed files with 31,347 additions and 501 deletions.
82 changes: 82 additions & 0 deletions .github/workflows/oidc-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# This action is an integration test for OIDC workflow
name: OpenID Connect Test
on:
push:
branches:
- '**'
tags-ignore:
- '**'
# Triggers the workflow on labeled PRs only.
pull_request_target:
types: [ labeled ]
# Ensures that only the latest commit is running for each PR at a time.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}-${{ github.ref }}
cancel-in-progress: true

permissions:
id-token: write

jobs:
OIDC-Test:
if: contains(github.event.pull_request.labels.*.name, 'safe to test') || github.event_name == 'push'
name: OIDC-Access integration test (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [ ubuntu, windows, macos ]
runs-on: ${{ matrix.os }}-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4

# Generating a unique name for the Integration Configuration that will be created in the following step
- name: Generate unique OIDC config name
shell: bash
run: echo "OIDC_CONFIG_NAME=oidc-integration-test-config-$(date +%Y%m%d%H%M%S)" >> $GITHUB_ENV

- name: Create OpenID Connect integration
shell: bash
run: |
curl -X POST "${{ secrets.JFROG_PLATFORM_URL }}/access/api/v1/oidc" -H "Content-Type: application/json" -H "Authorization: Bearer ${{ secrets.JFROG_PLATFORM_RT_TOKEN }}" -d '{
"name": "${{ env.OIDC_CONFIG_NAME }}",
"issuer_url": "https://token.actions.githubusercontent.com/",
"provider_type": "GitHub",
"description": "This is a test configuration created for OIDC-Access integration test" }'
- name: Create OIDC integration Identity Mapping
shell: bash
run: |
curl -X POST ${{ secrets.JFROG_PLATFORM_URL }}/access/api/v1/oidc/${{ env.OIDC_CONFIG_NAME }}/identity_mappings \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer ${{ secrets.JFROG_PLATFORM_RT_TOKEN }}' \
-d '{
"name": "oidc-test-identity-mapping",
"priority": "1",
"claims": {
"sub": "repo:jfrog/setup-jfrog-cli:ref:refs/heads/main",
"iss": "https://token.actions.githubusercontent.com"
},
"token_spec": {
"scope": "applied-permissions/admin",
"expires_in": 60
}
}'
- name: Setup JFrog CLI
uses: ./
env:
JF_URL: ${{ secrets.JFROG_PLATFORM_URL }}
with:
oidc-provider-name: ${{ env.OIDC_CONFIG_NAME }}

- name: Test JFrog CLI
run: |
jf rt ping
# Removing the OIDC integration will remove the Identity Mapping as well
- name: Delete OIDC integration
shell: bash
if: always()
run: |
curl -X DELETE ${{ secrets.JFROG_PLATFORM_URL }}/access/api/v1/oidc/${{ env.OIDC_CONFIG_NAME }} -H 'Authorization: Bearer ${{ secrets.JFROG_PLATFORM_RT_TOKEN }}'
57 changes: 55 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

This GitHub Action downloads, installs and configures JFrog CLI, so that it can be used as part of the workflow.

In addition, the Action includes the following features, when using JFrog CLI to work with JFrog Platform.
* The connection details of the JFrog platform used by JFrog CLI can be stored as secrets. Read more about it [here](#Storing-JFrog-Connection-Details-as-Secrets).
Additionally, the Action incorporates the following features when utilizing JFrog CLI to interact with the JFrog Platform:
* Two distinct methods are available for authenticating with the JFrog Platform. Explore more details [here](#authorization)
* There's no need to add the *build name* and *build number* options and arguments to commands which accept them.
All build related operations will be automatically recorded with the *Workflow Name* as build name and *Run Number* as build number.

Expand All @@ -23,6 +23,12 @@ All build related operations will be automatically recorded with the *Workflow N
- uses: jfrog/setup-jfrog-cli@v3
- run: jf --version
```
# Authorization
JFrog CLI operates in conjunction with the JFrog Platform. In order to facilitate this connection, certain connection details of the JFrog Platform must be provided.
There exist two methods to provide these details, and you only need to choose **one** method:
* The connection details of the JFrog platform can be stored as secrets. Read more about it [here](#storing-jfrog-connection-details-as-secrets).
* The connection details of the JFrog platform can be auto-generated using OpenID Connect protocol. Read more about it [here](#connect-using-openid-connect).
## Storing JFrog connection details as secrets
The connection details of the JFrog platform used by JFrog CLI can be stored as secrets.
Expand Down Expand Up @@ -95,6 +101,53 @@ If you have multiple Config Tokens as secrets, you can use all of them in the wo
| Important: When exposing more than one JFrog configuration to the Action, you should always add the ```jf c use``` command to specify the server to use. |
|----------------------------------------------------------------------------------------------------------------------------------------------------------|

## Connect using OpenID Connect
The sensitive connection details, such as the access token used by JFrog CLI on the JFrog platform, can be automatically generated by the action instead of storing it as a secret in GitHub.
This is made possible by leveraging the OpenID-Connect (OIDC) protocol. This protocol can authenticate the workflow issuer and supply a valid access token, requiring only the JF_URL environment variable.
To utilize the OIDC protocol, follow these steps:
### Platform configuration (To be performed once):
1. **[Configure an OIDC Integration](https://jfrog.com/help/r/jfrog-platform-administration-documentation/configure-an-oidc-integration)**: This phase sets an integration between the Action to the JFrog platform.

| NOTE: |
|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| The value specified as the 'Provider Name' should be used as the oidc-provider-name input in [Workflow configuration step 2](#workflowstep2) below. |
| The 'Audience' field does not represent the 'aud' claim for insertion into the identity-mapping in [Platform configuration step 2](#platformstep2) below. Only the claims included in the Claims Json created during step 2 will be validated. |

<div id="platformstep2"/>

2. **[Configure an identity mapping](https://jfrog.com/help/r/jfrog-platform-administration-documentation/configure-identity-mappings)**: This phase generates a reference token for authenticating against the JFrog platform. It involves defining the necessary details to enable server authentication of the action issuer and granting the issuer an appropriate access token.
You have the flexibility to define any valid list of claims required for request authentication. You can check a list of the possible claims [here](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#understanding-the-oidc-token).
Example Claims JSON:
```yml
{
"sub": "repo:my-user-name/project1:ref:refs/heads/main",
"aud": "https://github.com/my-user-name",
"ref": "refs/heads/main",
"repository": "my-user-name/project1",
"iss": "https://token.actions.githubusercontent.com"
}
```
### Workflow configuration (To be performed per workflow):
1. **Set required permissions**: In the course of the protocol's execution, it's imperative to acquire a JSON Web Token (JWT) from GitHub's OIDC provider. To request this token, it's essential to configure the specified permission in the workflow file:
```yml
permissions:
id-token: write
```
<div id="workflowstep2"/>

2. **Pass the 'oidc-provider-name' input to the Action (Required)**: The 'oidc-provider-name' parameter designates the OIDC configuration whose one of its identity mapping should align with the generated JWT claims. This input needs to align with the 'Provider Name' value established within the OIDC configuration.
3. **Pass the 'oidc-audience' input to the Action (Optional)**: The 'oidc-audience' input defines the intended recipients of an ID token (JWT), ensuring access is restricted to authorized recipients for the cloud (Artifactory). By default, it contains the URL of the repository owner.
This value, if transmitted, will be used as an argument in core.getIDToken(), which generates the JWT. It enforces a condition, allowing only workflows within the designated repository/organization to access the cloud role. Read more about it [here](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect#customizing-the-audience-value).
```yml
- name: Install JFrog CLI
uses: jfrog/setup-jfrog-cli@v3
env:
JF_URL: ${{ secrets.JF_URL }}
with:
oidc-provider-name: <Provider Name value given in step 1>
oidc-audience: <URL to the intended audience>
```

## Setting the build name and build number when publishing build-info to Artifactory
The Action automatically sets the following environment variables:
*JFROG_CLI_BUILD_NAME* and *JFROG_CLI_BUILD_NUMBER* with the workflow name and run number respectively.
Expand Down
7 changes: 7 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ inputs:
download-repository:
description: "Remote repository in Artifactory pointing to 'https://releases.jfrog.io/artifactory/jfrog-cli'. Use this parameter in case you don't have an Internet access."
required: false
oidc-audience:
description: "Recipient for which the JWT is intended. By default it contains the URL to the repository owner."
required: false
oidc-provider-name:
description: "Provider Name's value that was set in OpenId Connect integration."
required: false

runs:
using: "node16"
main: "lib/main.js"
Expand Down
2 changes: 1 addition & 1 deletion lib/cleanup.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function cleanup() {
return __awaiter(this, void 0, void 0, function* () {
try {
core.startGroup('Cleanup JFrog CLI servers configuration');
yield utils_1.Utils.addCliToPath();
yield utils_1.Utils.getAndAddCliToPath({});
yield utils_1.Utils.removeJFrogServers();
}
catch (error) {
Expand Down
5 changes: 3 additions & 2 deletions lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ function main() {
try {
core.startGroup('Setup JFrog CLI');
utils_1.Utils.setCliEnv();
yield utils_1.Utils.addCliToPath();
yield utils_1.Utils.configJFrogServers();
let jfrogCredentials = yield utils_1.Utils.getJfrogCredentials();
yield utils_1.Utils.getAndAddCliToPath(jfrogCredentials);
yield utils_1.Utils.configJFrogServers(jfrogCredentials);
}
catch (error) {
core.setFailed(error.message);
Expand Down
Loading

0 comments on commit 391668d

Please sign in to comment.