Giter VIP home page Giter VIP logo

nexus-proxy's Introduction

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

Name Description
ALLOWED_USER_AGENTS_ON_ROOT_REGEX A regex against which to match the User-Agent of requests to GET / so that they can be answered with 200 OK.
AUTH_CACHE_TTL The amount of time (in milliseconds) during which to cache the fact that a given user is authorized to make requests.
BIND_HOST The interface on which to listen for incoming requests. Defaults to 0.0.0.0.
BIND_PORT The port on which to listen for incoming requests.
CLIENT_ID The application's client ID in GCP / API Manager / Credentials.
CLIENT_SECRET The abovementioned application's client secret.
CLOUD_IAM_AUTH_ENABLED Whether to enable authentication against Google Cloud IAM.
ENFORCE_HTTPS Whether to enforce access by HTTPS only. If set to true Nexus will only be accessible via HTTPS.
JAVA_TOOL_OPTIONS JVM options to provide, for example -XX:MaxDirectMemorySize=1024M.
JWT_REQUIRES_MEMBERSHIP_VERIFICATION Whether users presenting valid JWT tokens must still be verified for membership within the organization.
KEYSTORE_PATH The path to the keystore containing the key with which to sign JWTs.
KEYSTORE_PASS The password of the abovementioned keystore.
LOG_LEVEL The desired log level (i.e., trace, debug, info, warn or error). Defaults to info.
NEXUS_DOCKER_HOST The host used to access the Nexus Docker registry.
NEXUS_HTTP_HOST The host used to access the Nexus UI and Maven repositories.
NEXUS_RUT_HEADER The name of the header which will convey auth info to Nexus.
ORGANIZATION_ID The ID of the organization against which to validate users' membership.
REDIRECT_URL The URL where to redirect users after the OAuth2 consent screen.
SESSION_TTL The TTL (in milliseconds) of a user's session.
TLS_CERT_PK12_PATH The path to the PK12 file to use when enabling TLS.
TLS_CERT_PK12_PASS The password of the PK12 file to use when enabling TLS.
TLS_ENABLED Whether to enable TLS.
UPSTREAM_DOCKER_PORT The port where the proxied Nexus Docker registry listens.
UPSTREAM_HTTP_PORT The port where the proxied Nexus instance listens.
UPSTREAM_HOST The host where the proxied Nexus instance listens.

nexus-proxy's People

Contributors

cmoroianu1 avatar jdenly avatar pires avatar tbcardoso avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

nexus-proxy's Issues

How to disable nexus proxy ?

First of all, reading this can help understanding that i'm not the only one having this need : helm/charts#5385

I found a nexus chart for Goole Kubernetes Engine here : https://github.com/helm/charts/tree/master/stable/sonatype-nexus

By default, the type service created is NodePort , so I update the values.yml from NodePort to LoadBalancer

dockerPort: 5003
nexusPort: 8081
  service:
    # type: NodePort
    type: LoadBalancer

Then I installed the chart using this command :

helm install --name gara-nexus sonatype-nexus/

GKE generates an external IP adress for the service, running on the port 8080. When I try to got this IP, I got the error :

Invalid host. To browse Nexus, click here/. To use the Docker registry, point your client at < nil >.

I logs the nexus-proxy deployment and have this error :

[io.netty.util.internal.MacAddressUtil] Failed to find a usable hardware address from the network interfaces; using random bytes: 63:86:20:76:be:a5:7e:7f 2019-12-30 21:43:28,182 [INFO ] [vert.x-eventloop-thread-0] [com.travelaudience.nexus.proxy.BaseNexusProxyVerticle] Listening at 0.0.0.0:8080.

Here: Run nexus in kubernetes cluster using helm there is an answer saying that the workaround is to change:

nexusProxy:
  imageName: quay.io/travelaudience/docker-nexus-proxy
  imageTag: 2.3.0
  imagePullPolicy: IfNotPresent
  port: 8080
  env:
    nexusDockerHost: 
    nexusHttpHost: 
    enforceHttps: false
    cloudIamAuthEnabled: false

with

nexusProxy:
  imageName: quay.io/travelaudience/docker-nexus-proxy
  imageTag: 2.3.0
  imagePullPolicy: IfNotPresent
  port: 8080
  env:
    nexusDockerHost: 127.0.0.1
    nexusHttpHost: 127.0.0.1
    enforceHttps: false
    cloudIamAuthEnabled: false

I changed it, but result is the same.
I generated a static ip from my gcp console, but still can't acess to the dashboard.

Please how could I correctly configure it and access to the nexus UI? I don't want to use docker-proxy. I don't have a dns for the moment.
I spent one week without success.

Thanks in advance

Authentication tokens survive restarts

This issue is a feature request.

Right now, the authentication tokens are stored in-memory only, meaning that every time the nexus-proxy is started, an empty cache is initialized and any previously assigned authentication tokens are revoked and users need to authenticate again, get new tokens and reconfigure their tools.

We should add persistent backend for mitigating this issue.

One suggestion is to create a pluggable mechanism that will allow for anyone to implement their own storage backends. By default, it would be in-memory only.

GCP IAM Auth Organization Viewer

Hi!

I was curious about the choice to only allow access through gcp iam auth with the organization viewer role.

In our organization this leads to some issues with out IT team. we don't necessarily want every user with nexus access to have access to view all of the projects in our organization.

Could this be linked to the project level instead? Is this in the works?

If not what is the reasoning behind choosing organization viewer as the permission to access nexus.

Thanks!

Exception on request and no response

Hi All,

I'm running with the following values.yaml using the latest nexus helm chart:

nexusProxy:
  env:
    nexusDockerHost: docker.portdynamics.com
    nexusHttpHost: nexus.portdynamics.com

ingress:
  enabled: true
  annotations:
    kubernetes.io/ingress.class: nginx
#    kubernetes.io/tls-acme: true
  tls: false

persistence:
  storageClass: standard
  storageSize: 1024Gi

On attempting to reach the proxy it throws an exception:

2018-05-11 14:26:36,180 [INFO ] [vert.x-eventloop-thread-0] [com.travelaudience.nexus.proxy.BaseNexusProxyVerticle] Listening at 0.0.0.0:8080.
2018-05-11 14:43:04,471 [ERROR] [vert.x-eventloop-thread-0] [io.vertx.ext.web.impl.RoutingContextImplBase] Unexpected exception in route
java.lang.NullPointerException: null
	at com.travelaudience.nexus.proxy.BaseNexusProxyVerticle.lambda$start$5(BaseNexusProxyVerticle.java:129)
	at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:217)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:78)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:118)
	at io.vertx.ext.web.handler.impl.VirtualHostHandlerImpl.handle(VirtualHostHandlerImpl.java:54)
	at io.vertx.ext.web.handler.impl.VirtualHostHandlerImpl.handle(VirtualHostHandlerImpl.java:27)
	at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:217)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:78)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:118)
	at io.vertx.ext.web.handler.impl.VirtualHostHandlerImpl.handle(VirtualHostHandlerImpl.java:54)
	at io.vertx.ext.web.handler.impl.VirtualHostHandlerImpl.handle(VirtualHostHandlerImpl.java:27)
	at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:217)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:78)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:118)
	at io.vertx.ext.web.handler.impl.VirtualHostHandlerImpl.handle(VirtualHostHandlerImpl.java:54)
	at io.vertx.ext.web.handler.impl.VirtualHostHandlerImpl.handle(VirtualHostHandlerImpl.java:27)
	at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:217)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:78)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:118)
	at com.travelaudience.nexus.proxy.BaseNexusProxyVerticle.lambda$start$0(BaseNexusProxyVerticle.java:80)
	at io.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:217)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:78)
	at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:118)
	at io.vertx.ext.web.impl.RouterImpl.accept(RouterImpl.java:79)
	at io.vertx.core.http.impl.ServerConnection.handleRequest(ServerConnection.java:285)
	at io.vertx.core.http.impl.ServerConnection.processMessage(ServerConnection.java:429)
	at io.vertx.core.http.impl.ServerConnection.handleMessage(ServerConnection.java:131)
	at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.lambda$createConnAndHandle$1(HttpServerImpl.java:770)
	at io.vertx.core.impl.ContextImpl.lambda$wrapTask$2(ContextImpl.java:335)
	at io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:193)
	at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.createConnAndHandle(HttpServerImpl.java:764)
	at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.doMessageReceived(HttpServerImpl.java:628)
	at io.vertx.core.http.impl.HttpServerImpl$ServerHandler.doMessageReceived(HttpServerImpl.java:580)
	at io.vertx.core.http.impl.VertxHttpHandler.channelRead(VertxHttpHandler.java:76)
	at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:122)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:349)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:341)
	at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
	at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:349)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:341)
	at io.vertx.core.http.impl.Http1xOrH2CHandler.end(Http1xOrH2CHandler.java:49)
	at io.vertx.core.http.impl.Http1xOrH2CHandler.channelRead(Http1xOrH2CHandler.java:27)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:349)
	at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:341)
	at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1334)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:363)
	at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:349)
	at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:926)
	at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:129)
	at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:642)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:565)
	at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:479)
	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:441)
	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
	at java.lang.Thread.run(Thread.java:748)

Any ideas?

npm error HPE_UNEXPECTED_CONTENT_LENGTH

Hello,

I deployed Nexus OSS with nexus-proxy on a k8s cluster through the helm chart. I don't use GCP IAM authentication.
I followed the documentation to configure the npm repositories.

When I try to download a package, I got the error HPE_UNEXPECTED_CONTENT_LENGTH.

The full error stack is the following:

[vmuser@Centos tmp]$ npm --registry http://www.exemple.com/repository/npm-group/ install generator-exemple-flak-api --loglevel verbose
npm info it worked if it ends with ok
npm verb cli [
npm verb cli '/usr/bin/node',
npm verb cli '/usr/bin/npm',
npm verb cli '--registry',
npm verb cli 'http://www.exemple.com/repository/npm-group/',
npm verb cli 'install',
npm verb cli 'generator-exemple-flak-api',
npm verb cli '--loglevel',
npm verb cli 'verbose'
npm verb cli ]
npm info using [email protected]
npm info using [email protected]
npm verb npm-session 86bac6cdd6426873
npm timing stage:rollbackFailedOptional Completed in 1ms
npm timing stage:runTopLevelLifecycles Completed in 131ms
npm verb type system
npm verb stack FetchError: request to http://www.exemple.com/repository/npm-group/generator-exemple-flak-api failed, reason: Parse Error: Content-Length can't be present with chunked encoding
npm verb stack at ClientRequest. (/usr/lib/node_modules/npm/node_modules/node-fetch-npm/src/index.js:68:14)
npm verb stack at ClientRequest.emit (events.js:203:13)
npm verb stack at Socket.socketOnData (_http_client.js:456:9)
npm verb stack at Socket.emit (events.js:203:13)
npm verb stack at addChunk (_stream_readable.js:295:12)
npm verb stack at readableAddChunk (_stream_readable.js:276:11)
npm verb stack at Socket.Readable.push (_stream_readable.js:210:10)
npm verb stack at TCP.onStreamRead (internal/stream_base_commons.js:166:17)
npm verb cwd /tmp
npm verb Linux 3.10.0-957.27.2.el7.x86_64
npm verb argv "/usr/bin/node" "/usr/bin/npm" "--registry" "http://www.exemple.com/repository/npm-group/" "install" "generator-exemple-flak-api" "--loglevel" "verbose"
npm verb node v12.8.1
npm verb npm v6.10.2
npm ERR! code HPE_UNEXPECTED_CONTENT_LENGTH
npm ERR! errno HPE_UNEXPECTED_CONTENT_LENGTH
npm ERR! request to http://www.exemple.com/repository/npm-group/generator-exemple-flak-api failed, reason: Parse Error: Content-Length can't be present with chunked encoding
npm verb exit [ 1, true ]
npm timing npm Completed in 387ms

npm ERR! A complete log of this run can be found in:
npm ERR! /home/vmuser/.npm/_logs/2019-08-30T14_56_28_661Z-debug.log

2019-08-30T14_56_28_661Z-debug.log

The error seems comming from the nexus-proxy because when I disable the nexus-proxy and directly access the nexus I don't get the error.

Is there a configuration parameter to avoid this error?

Thanks for your help.
Reagrds,
Renaud

Using Nexus npm proxy results in invalid http responses

I tried using nexus-proxy in the context of the oteemo helm chart (https://github.com/Oteemo/charts/tree/master/charts/sonatype-nexus)
and it resulted in the issue that during npm installs I get invalid http responses:
ERROR  request to https://nexus.company.com/repository/npm-public/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz failed, reason: Parse Error: Content-Length can't be present with chunked encoding

My helm chart values to reproduce:

...
ingress:
  enabled: true
  path: /*
  annotations:
    kubernetes.io/ingress.class: gce
    kubernetes.io/ingress.global-static-ip-name: my-static-ip
  tls:
    enabled: true
    secretName: wildcard-cert
nexusProxy:
  env:
    nexusHttpHost: nexus.company.com
    nexusDockerHost: containers.company.com
    enforceHttps: true
...

Other proxy repos like maven are working fine though and also the webinterface of Nexus is working as expected, therefore I think it has to be something specific to the npm proxy repository.

Automate releases

Right now, releases are done manually. It would be cool if we had an automated way of releasing new versions of this software. Extra points if it's triggered by a CI job and made available in a public Maven repository.

How to use nexus proxy with machine users

I have a few questions regarding the usage of nexus-proxy with machine users like maven etc.

  1. When using nexus proxy with GCP IAM authentication enabled. Do we have to first create users in nexus that are going to be authenticated via GCP?
  2. You have this line in the introduction:
    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.
    Can you explain please what do you mean by the user must request Nexus-specific credentials. What I don't understand is how and from whome the user is going to request credentials.
  3. I'm currently using keycloak proxy to do nexus authentication. From web ui authentication works fine. But when I try to upload a maven artifact it does not authenticate it. So currently my setup authenticates the user from browser but does not authenticate the machine users. I wonder how this is handled in nexus proxy?

CLI credentials' JWT returns 403 after server restart and before OAuth flow triggered

Problem

After nexus-proxy is restarted all JWTs obtained from /cli/credentials result in 403 responses, and the server logs claim it's because the principal "is not an organization member. Denying". Once a user has renewed their session by navigating to the browser and completing the OAuth flow, then the cli credential JWT authorizes successfully.

This is related to #3, which was closed but I found it to still be a problem.

Reason

The principal is extracted from the JWT and then a credential store of previously authenticated OAuth tokens is checked for a matching principal. If no match is found then the principal is not considered an organization member. The JWT is stored by clients and the credential store is stored on the server, but currently that store is in memory only.

The credential store is wiped out when the server restarts because it lives in memory only. Therefore there is no matching token for the principal contained in the JWT provided by the client. Sessions are lost too, so when users navigate to the nexus-proxy they are forced to go through the OAuth flow again. When that happens, a new token is put into the credential store and subsequent calls with the previous JWT now have principal matches.

Since this proxy is primarily used in Kubernetes deployments, this loss of JWT validity becomes a problem every time there is an update of the Nexus pod or a pod gets rescheduled for planned and unplanned reasons.

OutOfDirectMemoryError when downloading huge files

nexus-proxy version : quay.io/travelaudience/docker-nexus-proxy:2.5.0

hello, I set up nexus using the stable/sonatype helm chart , I tried to download a file size of 700M but failed , here's the log of nexus-proxy :

2020-03-20 14:28:52,118 [ERROR] [vert.x-eventloop-thread-0] [io.vertx.core.net.impl.ConnectionBase] io.netty.util.internal.OutOfDirectMemoryError: failed to allocate 16777216 byte(s) of direct memory (used: 117440551, max: 129761280)

the nexus log at the same time is like

2020-03-20 14:28:52,119+0000 WARN  [qtp1894943996-12704]  *UNKNOWN org.sonatype.nexus.repository.httpbridge.internal.ViewServlet - Failure servicing: GET /repository/pypi-all/files.pythonhosted.org/https/packages/bc/47/5b7c4f832b600779eed76cac86efbd5054f124bc919930aced51de2ccbb1/torch-1.4.0-cp38-cp38-manylinux1_x86_64.whl
org.eclipse.jetty.io.EofException: null
	at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:284)
	at org.eclipse.jetty.io.WriteFlusher.flush(WriteFlusher.java:393)
	at org.eclipse.jetty.io.WriteFlusher.write(WriteFlusher.java:277)
	at org.eclipse.jetty.io.AbstractEndPoint.write(AbstractEndPoint.java:380)
	at org.eclipse.jetty.server.HttpConnection$SendCallback.process(HttpConnection.java:826)
	at org.eclipse.jetty.util.IteratingCallback.processing(IteratingCallback.java:241)
	at org.eclipse.jetty.util.IteratingCallback.iterate(IteratingCallback.java:224)
	at org.eclipse.jetty.server.HttpConnection.send(HttpConnection.java:550)
	at org.eclipse.jetty.server.HttpChannel.sendResponse(HttpChannel.java:850)
	at org.eclipse.jetty.server.HttpChannel.write(HttpChannel.java:921)
	at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:249)
	at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:225)
	at org.eclipse.jetty.server.HttpOutput.write(HttpOutput.java:524)
	at com.google.common.io.ByteStreams.copy(ByteStreams.java:113)
	at org.sonatype.nexus.repository.view.Payload.copy(Payload.java:61)
	at org.sonatype.nexus.repository.view.Content.copy(Content.java:116)
	at org.sonatype.nexus.repository.httpbridge.internal.DefaultHttpResponseSender.send(DefaultHttpResponseSender.java:81)
	at org.sonatype.nexus.repository.httpbridge.internal.ViewServlet.dispatchAndSend(ViewServlet.java:228)
	at org.sonatype.nexus.repository.httpbridge.internal.ViewServlet.doService(ViewServlet.java:174)
	at org.sonatype.nexus.repository.httpbridge.internal.ViewServlet.service(ViewServlet.java:126)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at com.google.inject.servlet.ServletDefinition.doServiceImpl(ServletDefinition.java:286)
	at com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:276)
	at com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:181)
	at com.google.inject.servlet.DynamicServletPipeline.service(DynamicServletPipeline.java:71)
	at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:85)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:112)
	at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:61)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AdviceFilter.executeChain(AdviceFilter.java:108)
	at org.apache.shiro.web.servlet.AdviceFilter.doFilterInternal(AdviceFilter.java:137)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at org.apache.shiro.web.servlet.ProxiedFilterChain.doFilter(ProxiedFilterChain.java:66)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
	at org.sonatype.nexus.security.SecurityFilter.executeChain(SecurityFilter.java:85)
	at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
	at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
	at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
	at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
	at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
	at org.sonatype.nexus.security.SecurityFilter.doFilterInternal(SecurityFilter.java:101)
	at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
	at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
	at org.sonatype.nexus.repository.httpbridge.internal.ExhaustRequestFilter.doFilter(ExhaustRequestFilter.java:80)
	at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
	at com.sonatype.nexus.licensing.internal.LicensingRedirectFilter.doFilter(LicensingRedirectFilter.java:114)
	at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
	at com.codahale.metrics.servlet.AbstractInstrumentedFilter.doFilter(AbstractInstrumentedFilter.java:112)
	at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
	at org.sonatype.nexus.internal.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:79)
	at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
	at org.sonatype.nexus.internal.web.EnvironmentFilter.doFilter(EnvironmentFilter.java:101)
	at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
	at org.sonatype.nexus.internal.web.HeaderPatternFilter.doFilter(HeaderPatternFilter.java:98)
	at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:82)
	at com.google.inject.servlet.DynamicFilterPipeline.dispatch(DynamicFilterPipeline.java:104)
	at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:135)
	at org.sonatype.nexus.bootstrap.osgi.DelegatingFilter.doFilter(DelegatingFilter.java:73)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1602)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:540)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1700)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1345)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:480)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1667)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1247)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at com.codahale.metrics.jetty9.InstrumentedHandler.handle(InstrumentedHandler.java:239)
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:152)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
	at org.eclipse.jetty.server.Server.handle(Server.java:505)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:370)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:267)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:698)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:804)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: Connection reset by peer
	at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
	at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
	at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
	at sun.nio.ch.IOUtil.write(IOUtil.java:51)
	at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:468)
	at org.eclipse.jetty.io.ChannelEndPoint.flush(ChannelEndPoint.java:262)
	... 102 common frames omitted

How to configure different docker ports in one nexus-proxy

How to configure different docker ports in one nexus-proxy?
Usually we defined 3 docker repository in one nexus, one for group, one for proxy, one for hosted. And we need the hosted port to push the image, we need the group port to pull the image. Then how to do that in nexus proxy?

EOF on Docker Login with stable/sonatype Helm chart

Getting this EOF error upon docker login:

$ docker login -u admin -p admin123 kmaster:30313
Error response from daemon: Get https://kmaster:30313/v2/: EOF

I'm not fully understanding the solution between the documentation for the proxy, registry and the docker client and the interactions between. I'm seeking ideas on what might cause this problem.

Nexus on Kubernetes Setup

Kmaster host is a local and healthy K8s cluster, version 1.13.1 setup with Kubeadm with a master and worker node (Mac w/ Parallels). The stable/sonatype Helm chart, version sonatype-nexus-1.15.0, was applied with this command:

helm install stable/sonatype-nexus --namespace nexus --name nexus -f nexus-values.yaml

The values file is below. Nexus and its UI runs fine and is healthy.

Through the UI a "docker (hosted)" repository was added and configured with:

Name: containers
Format: docker
Type: hosted
URL: http://kmaster:30313/repository/containers/
Online: checked
HTTP: 30313
HTTPS: unchecked
Force basic authentication: checked
Enable Docker V1 API: checked

The helm chart values applied in nexus-values.yaml reads as:

statefulset:
  enabled: false

replicaCount: 1
deploymentStrategy: {}

nexus:
  imageName: quay.io/travelaudience/docker-nexus
  imageTag: 3.14.0
  imagePullPolicy: IfNotPresent
  env:
    - name: install4jAddVmParams
      value: "-Xms1200M -Xmx1200M -XX:MaxDirectMemorySize=2G -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap"
  resources: {}
  dockerPort: 5003
  nexusPort: 8081
  service:
    type: NodePort
  podAnnotations: {}
  livenessProbe:
    initialDelaySeconds: 30
    periodSeconds: 30
    failureThreshold: 6
    path: /
  readinessProbe:
    initialDelaySeconds: 30
    periodSeconds: 30
    failureThreshold: 6
    path: /
  hostAliases: []

nexusProxy:
  enabled: true
  imageName: quay.io/travelaudience/docker-nexus-proxy
  imageTag: 2.4.0
  imagePullPolicy: IfNotPresent
  port: 8080
  targetPort: 8080
  env:
    nexusDockerHost: kmaster
    nexusHttpHost: kmaster
    enforceHttps: false
    cloudIamAuthEnabled: false
  resources: {}

persistence:
  enabled: false

nexusBackup:
  enabled: false

ingress:
  enabled: false

tolerations: []

config:
  enabled: false

deployment:
  annotations: {}
  initContainers:
  postStart:
    command:    # '["/bin/sh", "-c", "ls"]'
  additionalContainers:
  additionalVolumes:

secret:
  enabled: false

service:
  enabled: false

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.