-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Proposal for identity aware proxy authentication mode
Adds a proposal for identity aware proxy authentication mode in Harbor.
- Loading branch information
Sheng Jiang
committed
Oct 4, 2023
1 parent
016139a
commit 7cee938
Showing
5 changed files
with
230 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
Harbor Proposal: Identity Aware proxy authentication mode | ||
|
||
Author: Sheng Jiang/shengjiang3, Eric Liu/ Date: Oct 3, 2023 | ||
|
||
## Abstract | ||
|
||
Proposes an approach to delegate Authentication decisions to external | ||
authentication authority in Harbor. | ||
|
||
## Background | ||
|
||
Currently, Harbor supports the OIDC protocol, however this means that Harbor | ||
cannot be seamlessly integrated into Single Sign-On (SSO) within an organization | ||
because Harbor must perform the code exchange for an identity token. | ||
|
||
## Proposal | ||
|
||
Add another authentication option, letting the identity provider authenticate | ||
and issue an identity token while Harbor assumes the role of an application that | ||
consumes the identity token. Harbor would act as an OIDC token verifier. The | ||
goal is to allow Harbor to plug in to any upstream OIDC identity provider | ||
allowing an SSO credential to authenticate with Harbor. | ||
|
||
### Key terms | ||
|
||
Identity Aware proxy (IAP) - A reverse proxy that provides authentication. Also | ||
known as auth proxy. Identity token (ID token) - Artifact that proves that the | ||
user has been authenticated (source). | ||
|
||
### High Level design | ||
|
||
![high-level-design](../images/identity-aware-proxy/high_level_design.png) | ||
|
||
The new authentication option allows Harbor to trust the identity tokens issued | ||
by an identity aware proxy (such as Dex). The identity aware proxy is OIDC | ||
compatible. As such, Harbor is to be configured to fetch the JWKS from the | ||
identity aware proxy and to use the JWKS to verify the ID tokens issued by the | ||
identity aware proxy. Once the token is verified and validated, Harbor can use | ||
the identity inside the ID token as the user identity. | ||
|
||
This is a slight deviation from the existing OIDC authentication mode where | ||
Harbor is directly configured to authenticate with the identity provider. | ||
|
||
### Configuration | ||
|
||
Since the new authentication mode in Harbor plays the role as an OIDC verifier, | ||
the following OIDC attributes are needed: | ||
|
||
- Name: The name of the OIDC provider. | ||
- Issuer URL: The identity provider's URL. This is used to locate the OIDC | ||
discovery document typically found at /.well-known/openid-configuration. | ||
- Expected Audiences (optional): A comma separated list of identifiers that | ||
Harbor is recognized by. The audience claim in the JWT should contain one of | ||
the audiences configured in the list. | ||
- User claim: The claim in the JWT to use as the user name. The default is the | ||
`sub` claim in the OIDC specification. | ||
- Groups claim: The claim in the JWT to locate the user’s groups. | ||
- Certificate authority data: base64 encoded PEM encoded certificate for the | ||
identity proxy. | ||
- Header name: HTTP header to get the ID token. | ||
|
||
The identity aware proxy should be able to be configured using the portal and/or | ||
the API. | ||
|
||
### Validating a token | ||
|
||
![token-validation](../images/identity-aware-proxy/token_validation.png) | ||
|
||
In the Identity Aware Proxy authentication mode, Harbor will look for the ID | ||
token in the Authorization header (Authorization: Bearer <JWT>). | ||
|
||
- The token will be a JWT Bearer token. | ||
- The token will be issued by the IAP after the user has authenticated through | ||
the IAP. | ||
- The token will be signed using the private key corresponding to the public | ||
keys available in the JWKS endpoint. | ||
|
||
The user contained in the ID token should only be used after verifying and | ||
validating the ID token: | ||
|
||
1. Verify the signature of the JWT using the JWKS. | ||
1. Harbor can periodically refresh the JWKS. | ||
1. Fetch the JWKS if a JWT with an unknown key ID is received. | ||
- Back off if the JWKS was fetched recently to prevent too many requests | ||
to the proxy. | ||
1. Ensure that alg cannot be none. | ||
1. Validate that the token is not expired or not valid yet. | ||
- Check the exp and nbf claims. | ||
1. Validate that the token is intended for Harbor. | ||
- Check the aud claim for any of the expected audiences. | ||
1. The validated token can be used for authorization enforcement and user | ||
identification. | ||
|
||
The ID token is a short lived token so each token should be verified and | ||
validated independently. The ID token cannot be refreshed by Harbor to get a new | ||
token. | ||
|
||
### Obtaining identity from the token | ||
|
||
The identity is obtained from the token by looking for the user and groups claim | ||
specified in the Identity Aware Proxy configuration. | ||
|
||
The user claim specifies the claim in the JWT to obtain the user name from. The | ||
value in this claim is to be used to identify the user within Harbor (for | ||
example authorization policies). The user name in the user claim needs to be | ||
unique across the IAP. | ||
|
||
The groups claim specifies the claim in the JWT to obtain the groups from. The | ||
groups claim value is in the form of a list. | ||
|
||
### User access from a browser | ||
|
||
![browser-flow](../images/identity-aware-proxy/browser_flow.png) | ||
|
||
The first time Harbor sees a token for a given user claim, Harbor can on-board | ||
the user into the Harbor database (is this necessary?). The user name in the | ||
user claim is the username to onboard with. | ||
|
||
If the request has a valid bearer token, then the user should not be shown the | ||
Harbor login page and instead should be taken directly to the portal. | ||
|
||
### User access from the CLI (docker) | ||
|
||
![cli-flow](../images/identity-aware-proxy/cli_flow.png) | ||
|
||
The user flow for CLI can follow the same flow as OIDC CLI flow. The user gets | ||
the CLI secret from the UI and uses the CLI secret in the docker CLI which means | ||
that the OIDC CLI flow should also support IAP. | ||
|
||
The IAP issues ID tokens after authenticating the user credentials. The | ||
limitation is that the user must refresh the ID token in Harbor in order for the | ||
secret to remain valid since the IAP does not send the refresh token. | ||
|
||
Once the user is authenticated and accessing the UI, the user can obtain the CLI | ||
secret and use the CLI secret. | ||
|
||
## Non-Goals | ||
|
||
- Support for non-OIDC protocols such as SAML or LDAP. | ||
|
||
- Support for authorization by the identity provider. | ||
|
||
- Using access tokens from the OIDC provider. | ||
|
||
## Rationale | ||
|
||
### Alternatives | ||
|
||
#### Authentication with Kubernetes TokenReview | ||
|
||
Harbor auth proxy (link) uses Kubernetes token review to validate the token. | ||
However, Harbor auth proxy also relies on an endpoint that isn’t well | ||
documented. Since Harbor auth proxy already makes use of Kubernetes TokenReview | ||
to authenticate a token, an alternative to the Identity Aware Proxy would be | ||
support authentication via Kubernetes TokenReview as a first order option. | ||
Kubernetes TokenReview would operate as a webhook that Harbor can delegate | ||
authentication decisions to. | ||
|
||
Required configurations: | ||
|
||
- Host name: This is the Kubernetes API server evaluating the TokenReview. | ||
- Certificate: Certificate establishing the TLS connection. | ||
- Audiences (recommended): The audiences for tokens intended for Harbor. | ||
|
||
#### UI: | ||
|
||
- The token to authenticate is sent in the Authorization header as a bearer | ||
token. | ||
- The TokenReview ensures that the token is intended for Harbor by checking the | ||
audience in the token if it is provided. | ||
- The username and groups are provided in the TokenReview status upon successful | ||
authentication. | ||
- Automatically onboard the user using the username if this is the first time | ||
the user has signed in. | ||
- Skip the sign in page if the user is authenticated. | ||
|
||
#### CLI: | ||
|
||
- The docker CLI sends the token to the Token Service in the authorization basic | ||
header. | ||
- The username in the Authorization basic header is a filler string. The secret | ||
contains the token. | ||
- AWS uses a filler string for the user name: | ||
https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html | ||
- Azure also uses a filler string for the user name: | ||
https://learn.microsoft.com/en-us/azure/container-registry/container-registry-authentication?tabs=azure-cli#az-acr-login-with---expose-token | ||
|
||
### Auth Proxy using trusted headers for identification | ||
|
||
Harbor lives behind an auth proxy that authenticates access to Harbor. The | ||
mechanism authenticating access through the auth proxy is not important. | ||
However, after authenticating access, the auth proxy passes the identity of the | ||
user as a string in a configurable header (e.g- X-AuthProxy-UserName). | ||
|
||
Harbor would trust and use the user name passed in from the configurable header | ||
as the user name within Harbor. When Harbor gets a username that it has not seen | ||
before, Harbor should auto-onboard the user into the user database. | ||
|
||
Configuration options: | ||
|
||
- Header name (Required): This is the header where the username can be found. | ||
- Allowed sources (Optional): List of hosts or IPs the auth proxy requests can | ||
be forwarded from. | ||
|
||
## Trade-offs | ||
|
||
Pros of IAP: | ||
|
||
- Delegates authentication to an external identity authority. The external | ||
identity authority can manage the authentication logic so that Harbor only | ||
needs to verify and use the credentials. | ||
- Harbor explicitly verifies the identity token against the published public | ||
keys. | ||
|
||
Disadvantages of IAP: | ||
|
||
- The Harbor issued access token depends on the ID token. Short lived ID token | ||
means that the user has to authenticate often. | ||
|
||
# Compatibility | ||
|
||
This adds a new authentication method that doesn’t conflict with any existing | ||
ones. | ||
|
||
# Implementation | ||
|
||
1. Create configuration items for auth proxy configuration, and update UI to | ||
enable the configuration via Portal. | ||
1. Create a table (separate from the OIDC table) for sub, username, CLI secret. | ||
1. Add security context to handle the id token. |