Sign inSign up

jdenly/nexus-proxy

By jdenly

•Updated over 6 years ago

Nexus repository proxy server with additional JAVA_OPTS environment variable.

Image
0

1.0K

jdenly/nexus-proxy repository overview

⁠nexus-proxy

Build Status Docker Repository on Quay

A proxy for Nexus Repository Manager that allows for optional authentication against external identity providers.

Read the design document⁠ for a more detailed explanation of why and how.

⁠Before proceeding

ATTENTION: This software does not manage or enforce authorization. It's therefore required that users, roles and permissions are to be configured through Nexus administrative UI before start using Nexus.

ATTENTION: If GCP IAM authentication is enabled, every user account must be created with their organization email address as the username. A password needs to be set but it will only be important if GCP IAM authentication is disabled. Also it is necessary to grant the "Organization Viewer" role at organization-level⁠ (i.e., in the "IAM & Admin" section of the organization in the GCP UI) to every user.

ATTENTION:: If GCP IAM authentication is enabled, it is necessary to enable the Nexus "Rut Auth" capability⁠. Otherwise, authentication succeeds but Nexus can't initiate user sessions.

ATTENTION: The Nexus-specific credentials mentioned above are valid for one year and for as long as the user is a member of the GCP organization.

ATTENTION: If the ENFORCE_HTTPS flag is set to true it is assumed that one has configured nexus-proxy or any load-balancers in front of it to serve HTTPS on host NEXUS_HTTP_HOST and port 443 with a valid TLS certificate.

ATTENTION:: Setting the JWT_REQUIRES_MEMBERSHIP_VERIFICATION environment variable to false inherently makes nexus-proxy less secure. In this scenario, a user containing a valid JWT token will be able to make requests using CLI tools like Maven or Docker without having to go through the OAuth2 consent screen. For example, if a user leaves the organization while keeping a valid JWT token, and this environment variable is set to false, they will still be able to make requests to Nexus.

⁠Introduction

While deploying Nexus Repository Manager on GKE, we identified a couple issues:

  1. GCLB backend health-checks weren't working when reaching Nexus directly.
  2. Couldn't expose Docker private registry with the same set-up used to expose the other artifact repositories.

We also knew beforehand that we would need to authenticate Nexus against Google Cloud Identity & Access Management⁠.

While the aforementioned issues were easily fixed with Nginx⁠, the authentication part proved much more complicated. For all of those reasons, we decided to implement our own proxy software that would deliver everything we needed.

Also, authentication is disabled by default so it can be used in simpler scenarios.

When GCP IAM authentication is enabled, every user attempting to access Nexus is asked to authenticate against GCP with their GCP organization credentials. If authentication succeeds, an encrypted token will be generated by the proxy and sent to the client ,e.g. browser, so it knows how to authenticate itself. After being logged-in, and only when authentication is enabled, the user must request Nexus-specific credentials for using with tools like Maven, Gradle, sbt, Python (pip) and Docker.

⁠Pre-requisites

For building the project:

  • JDK 8.

For basic proxying:

  • A domain name configured with an A and a CNAME records pointing to the proxy.
    • For local testing one may create two entries on /etc/hosts pointing to 127.0.0.1.
  • A running and properly configured instance of Nexus.
    • One may use the default 8081 port for the HTTP connector and 5003 for the Docker registry, for example.

For opt-in authentication against Google Cloud IAM:

  • All of the above.
  • A GCP organization.
  • A GCP project with the Cloud Resources Manager API enabled.
  • A set of credentials of type OAuth Client ID obtained from GCP > API Manager > Credentials.
  • Proper configuration of the resulting client's "Redirect URL".

⁠Generating the Keystore

A Java keystore is needed in order for the proxy to sign user tokens (JWT). Here's how to generate the keystore:

$ keytool -genkey \
          -keystore keystore.jceks \
          -storetype jceks \
          -keyalg RSA \
          -keysize 2048 \
          -alias RS256 \
          -sigalg SHA256withRSA \
          -dname "CN=,OU=,O=,L=,ST=,C=" \
          -validity 3651

One will be prompted for two passwords. One must make sure the passwords match.

Also, one is free to change the value of the dname, keystore and validity parameters.

⁠Building the code

The following command will build the project and generate a runnable jar:

$ ./gradlew build

⁠Running the proxy

The following command will run the proxy on port 8080 with no authentication and pointing to a local Nexus instance:

$ ALLOWED_USER_AGENTS_ON_ROOT_REGEX="GoogleHC" \
  BIND_PORT="8080" \
  NEXUS_DOCKER_HOST="containers.example.com" \
  NEXUS_HTTP_HOST="nexus.example.com" \
  NEXUS_RUT_HEADER="X-Forwarded-User" \
  TLS_ENABLED="false" \
  UPSTREAM_DOCKER_PORT="5000" \
  UPSTREAM_HTTP_PORT="8081" \
  UPSTREAM_HOST="localhost" \
  java -jar ./build/libs/nexus-proxy-2.3.0.jar

⁠Running the proxy with GCP IAM authentication enabled

The following command will run the proxy on port 8080 with GCP IAM authentication enabled and pointing to a local Nexus instance:

$ ALLOWED_USER_AGENTS_ON_ROOT_REGEX="GoogleHC" \
  AUTH_CACHE_TTL="60000" \
  BIND_PORT="8080" \
  CLOUD_IAM_AUTH_ENABLED="true" \
  CLIENT_ID="my-client-id" \
  CLIENT_SECRET="my-client-secret" \
  KEYSTORE_PATH="./.secrets/keystore.jceks" \
  KEYSTORE_PASS="my-keystore-password" \
  NEXUS_DOCKER_HOST="containers.example.com" \
  NEXUS_HTTP_HOST="nexus.example.com" \
  NEXUS_RUT_HEADER="X-Forwarded-User" \
  ORGANIZATION_ID="123412341234" \
  REDIRECT_URL="https://nexus.example.com/oauth/callback" \
  SESSION_TTL="1440000" \
  TLS_ENABLED="false" \
  UPSTREAM_DOCKER_PORT="5000" \
  UPSTREAM_HTTP_PORT="8081" \
  UPSTREAM_HOST="localhost" \
  java -jar ./build/libs/nexus-proxy-2.3.0.jar

⁠Environment Variables

NameDescription
ALLOWED_USER_AGENTS_ON_ROOT_REGEXA regex against which to match the User-Agent of requests to GET / so that they can be answered with 200 OK.
AUTH_CACHE_TTLThe amount of time (in milliseconds) during which to cache the fact that a given user is authorized to make requests.
BIND_HOSTThe interface on which to listen for incoming requests. Defaults to 0.0.0.0.
BIND_PORTThe port on which to listen for incoming requests.
CLIENT_IDThe application's client ID in GCP / API Manager / Credentials.
CLIENT_SECRETThe abovementioned application's client secret.
CLOUD_IAM_AUTH_ENABLEDWhether to enable authentication against Google Cloud IAM.
ENFORCE_HTTPSWhether to enforce access by HTTPS only. If set to true Nexus will only be accessible via HTTPS.
JAVA_OPTSJVM options to provide, for example -XX:MaxDirectMemorySize=1024M.
JWT_REQUIRES_MEMBERSHIP_VERIFICATIONWhether users presenting valid JWT tokens must still be verified for membership within the organization.
KEYSTORE_PATHThe path to the keystore containing the key with which to sign JWTs.
KEYSTORE_PASSThe password of the abovementioned keystore.
LOG_LEVELThe desired log level (i.e., trace, debug, info, warn or error). Defaults to info.
NEXUS_DOCKER_HOSTThe host used to access the Nexus Docker registry.
NEXUS_HTTP_HOSTThe host used to access the Nexus UI and Maven repositories.
NEXUS_RUT_HEADERThe name of the header which will convey auth info to Nexus.
ORGANIZATION_IDThe ID of the organization against which to validate users' membership.
REDIRECT_URLThe URL where to redirect users after the OAuth2 consent screen.
SESSION_TTLThe TTL (in milliseconds) of a user's session.
TLS_CERT_PK12_PATHThe path to the PK12 file to use when enabling TLS.
TLS_CERT_PK12_PASSThe password of the PK12 file to use when enabling TLS.
TLS_ENABLEDWhether to enable TLS.
UPSTREAM_DOCKER_PORTThe port where the proxied Nexus Docker registry listens.
UPSTREAM_HTTP_PORTThe port where the proxied Nexus instance listens.
UPSTREAM_HOSTThe host where the proxied Nexus instance listens.

Tag summary

Content type

Image

Digest

Size

67.2 MB

Last updated

over 6 years ago

docker pull jdenly/nexus-proxy