Skip to content

Commit

Permalink
Updating all libraries to Java 11 and image to 3.70.0-java11-ubi
Browse files Browse the repository at this point in the history
  • Loading branch information
a-langer committed Jul 17, 2024
1 parent 2ed467f commit a37e9bc
Show file tree
Hide file tree
Showing 16 changed files with 511 additions and 76 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ LOGGING_MAX_SIZE="${LOGGING_MAX_SIZE:-10M}"
LOGGING_COUNT_FILES="${LOGGING_COUNT_FILES:-10}"

## Nexus
NEXUS_IMAGE="${NEXUS_IMAGE:-ghcr.io/a-langer/nexus-sso:3.70.0}"
NEXUS_IMAGE="${NEXUS_IMAGE:-ghcr.io/a-langer/nexus-sso:3.70.0-java11-ubi}"
NEXUS_USER="${NEXUS_USER:-nexus}"
NEXUS_GROUP="${NEXUS_GROUP:-nexus}"
NEXUS_DATA="${NEXUS_DATA:-./nexus_data}"
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# docker rmi $(docker images -f "dangling=true" -q)
# docker run --user=0:0 --rm -it -p 8081:8081/tcp sonatype/nexus3:3.37.3 /bin/bash

ARG NEXUS_BASE_IMAGE="sonatype/nexus3:3.70.0"
ARG NEXUS_BASE_IMAGE="sonatype/nexus3:3.70.0-java11-ubi"
FROM $NEXUS_BASE_IMAGE
USER root

Expand Down
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![license](https://img.shields.io/badge/license-EPL1-brightgreen.svg)](https://github.com/a-langer/nexus-sso/blob/main/LICENSE "License of source code")
[![image](https://ghcr-badge.deta.dev/a-langer/nexus-sso/latest_tag?trim=major&label=latest)][0]
[![image-size](https://ghcr-badge.deta.dev/a-langer/nexus-sso/size?tag=3.70.0)][0]
[![image-size](https://ghcr-badge.deta.dev/a-langer/nexus-sso/size?tag=3.70.0-java11-ubi)][0]
[![JitPack](https://jitpack.io/v/a-langer/nexus-sso.svg)][1]

Patch for [Nexus OSS][2] with authorization via [SSO][9] and [tokens][10]. By default this features available only in PRO version ([see comparison][5]), but this patch provides them an alternative implementation without violating the license.
Expand All @@ -23,14 +23,16 @@ Solution implement as Docker [container][0] (based on [official image][3] with S

## Supported features and examples of usage

> **Note**: Since version `3.61.0` for SSO and User Tokens, it is enough to have following [realms][8.1] in the order listed:
>
> 1. "**Local Authenticating Realm**" - built-in realm used by default.
> 2. "**SSO Pac4j Realm**" - single sign-on realm uses an external Identity Provider (IdP).
> 3. "**SSO Token Realm**" - realm allows you to use user tokens instead of a password.
> 4. "**Docker Bearer Token Realm**" - required to access Docker repositories through a Docker client (must be below the "**SSO Token Realm**").
>
> Other realms are not required and may lead to conflicts.
> **Note**: Since version `3.70.0-java11-ubi` image and all libraries have been updated to Java 11. See [release notes](https://help.sonatype.com/en/sonatype-nexus-repository-3-70-0-release-notes.html) for more information.
Since version `3.61.0` for using SSO and User Tokens, it is enough to have following [realms][8.1] in the order listed:

1. "**Local Authenticating Realm**" - built-in realm used by default.
2. "**SSO Pac4j Realm**" - single sign-on realm uses an external Identity Provider (IdP).
3. "**SSO Token Realm**" - realm allows you to use user tokens instead of a password.
4. "**Docker Bearer Token Realm**" - required to access Docker repositories through a Docker client (must be below the "**SSO Token Realm**").

Other realms are not required and may lead to conflicts.

List of features this patch adds:

Expand Down
12 changes: 6 additions & 6 deletions etc/logback/logback.xml
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,9 @@
<!-- <logger name="com.github.alanger.nexus.bootstrap.QuotaFilter" level="TRACE" /> -->

<!-- SAML debug -->
<!-- <logger name="io.buji.pac4j.filter.SecurityFilter" level="TRACE" /> -->
<!-- <logger name="io.buji.pac4j.filter.CallbackFilter" level="TRACE" /> -->
<!-- <logger name="com.github.alanger.nexus.plugin.Pac4jCallbackLogic" level="TRACE" /> -->
<!-- <logger name="org.pac4j.jee.filter.SecurityFilter" level="TRACE" /> -->
<!-- <logger name="org.pac4j.jee.filter.CallbackFilter" level="TRACE" /> -->
<!-- <logger name="org.pac4j.saml.client" level="DEBUG" /> -->
<!-- <logger name="org.pac4j.core.client" level="TRACE" /> -->
<!-- <logger name="org.pac4j.saml.crypto" level="TRACE" /> -->
Expand All @@ -176,17 +177,16 @@
<!-- <logger name="org.sonatype.nexus.security" level="TRACE" /> -->

<!-- User Token debug -->
<!-- <logger name="org.pac4j.saml" level="TRACE" /> -->
<!-- <logger name="org.sonatype.nexus.siesta.internal.UnexpectedExceptionMapper" level="TRACE" /> -->
<!-- <logger name="org.sonatype.nexus.extdirect.internal.ExtDirectExceptionHandler" level="OFF" /> -->
<!-- <logger name="org.sonatype.nexus.repository.docker.internal.security.DockerTokenRealm" level="TRACE" /> -->
<!-- <logger name="com.sonatype.nexus.repository.nuget.internal.rest.NugetApiKeyResource" level="TRACE" /> -->
<!-- <logger name="com.github.alanger.nexus.plugin.rest.NugetApiKeyResource" level="TRACE" /> -->
<!-- <logger name="org.sonatype.nexus.internal.security.apikey.ApiKeyStoreImpl" level="TRACE" /> -->
<!-- <logger name="org.sonatype.nexus.internal.security.apikey.OrientApiKeyEntityAdapter" level="TRACE" /> -->
<!-- <logger name="org.sonatype.nexus.internal.security.apikey.orient.OrientApiKeyStore" level="TRACE" /> -->
<!-- <logger name="com.sonatype.nexus.repository.nuget" level="TRACE" /> -->
<!-- <logger name="com.github.alanger.nexus.plugin.rest.NugetApiKeyResource" level="TRACE" /> -->
<!-- <logger name="org.sonatype.nexus.security.authc.FirstSuccessfulModularRealmAuthenticator" level="TRACE" /> -->
<!-- <logger name="org.sonatype.nexus.security.token.BearerTokenRealm" level="TRACE" /> -->
<!-- <logger name="org.sonatype.nexus.repository.docker.internal.security.DockerTokenRealm" level="TRACE" /> -->

<!-- Startup progress log -->
<logger name="org.sonatype.nexus.bootstrap" level="INFO" />
Expand Down
23 changes: 19 additions & 4 deletions nexus-docker/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
<packaging>pom</packaging>

<properties>
<nexus.base.image>sonatype/nexus3:${nexus.base.version}</nexus.base.image>
<docker.image>ghcr.io/a-langer/nexus-sso:${project.version}</docker.image>
<nexus.base.image>sonatype/nexus3:${nexus.base.version}-java11-ubi</nexus.base.image>
<docker.image>ghcr.io/a-langer/nexus-sso:${project.version}-java11-ubi</docker.image>
<ansiblegalaxy.version>0.3.2-fixed</ansiblegalaxy.version>
</properties>

Expand Down Expand Up @@ -88,10 +88,12 @@
match="ARG NEXUS_PLUGIN_VERSION=(.*)"
replace='ARG NEXUS_PLUGIN_VERSION="${nexus.plugin.version}"' />

<echo>Set size?tag=${project.version} to README.md</echo>
<taskdef resource="net/sf/antcontrib/antcontrib.properties" />
<propertyregex property="image.tag" input="${docker.image}" regexp="^.*\:(.*)$" select="\1" />
<echo>Set size?tag=${image.tag} to README.md</echo>
<replaceregexp file="${maven.multiModuleProjectDirectory}/README.md" byline="true"
match=".*/a-langer/nexus-sso/size\?tag=(.*)"
replace='[![image-size](https://ghcr-badge.deta.dev/a-langer/nexus-sso/size?tag=${project.version})][0]' />
replace='[![image-size](https://ghcr-badge.deta.dev/a-langer/nexus-sso/size?tag=${image.tag})][0]' />

<echo>Set ANSIBLEGALAXY_VERSION="${ansiblegalaxy.version}" to Dockerfile</echo>
<replaceregexp file="${maven.multiModuleProjectDirectory}/Dockerfile" byline="true"
Expand All @@ -101,6 +103,19 @@
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>ant-contrib</groupId>
<artifactId>ant-contrib</artifactId>
<version>1.0b3</version>
<exclusions>
<exclusion>
<groupId>ant</groupId>
<artifactId>ant</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
Expand Down
35 changes: 29 additions & 6 deletions nexus-pac4j-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,35 +36,45 @@
</exclusion>
</exclusions>
</dependency>
<!-- Newer version requires JDK 11, Nexus 3 supports only JDK 8 -->
<!-- Newer version requires JDK 17, Nexus 3.70.X with OrientDB supports max JDK 11 -->
<dependency>
<groupId>io.buji</groupId>
<artifactId>buji-pac4j</artifactId>
<version>4.1.1</version>
<version>8.0.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.shiro</groupId>
<artifactId>*</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Fix NoClassDefFoundError: org/pac4j/core/redirect/RedirectActionBuilder -->
<!-- Since buji-pac4j:8.0.0 -->
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>javaee-pac4j</artifactId>
<version>7.1.0</version>
</dependency>
<!-- Newer version requires JDK 17, Nexus 3.70.X with OrientDB supports max JDK 11 -->
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>pac4j-core</artifactId>
<version>3.9.0</version>
<version>5.6.0</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Newer version requires JDK 11, Nexus 3 supports only JDK 8 -->
<!-- Newer version requires JDK 17, Nexus 3.70.X with OrientDB supports max JDK 11 -->
<dependency>
<groupId>org.pac4j</groupId>
<artifactId>pac4j-saml</artifactId>
<version>3.9.0</version>
<version>5.6.0</version>
<exclusions>
<!-- Shared libraries will be loaded from OSGI bundles -->
<exclusion>
Expand Down Expand Up @@ -158,6 +168,19 @@
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
</exclusion>
<!-- Not required since buji-pac4j:8.0.0 -->
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<!-- Fix FactoryConfigurationError: Provider org.apache.xerces.jaxp.DocumentBuilderFactoryImpl not found -->
<exclusion>
<groupId>xalan</groupId>
Expand Down
18 changes: 14 additions & 4 deletions nexus-pac4j-plugin/src/main/config/shiro.ini
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Authenticate_Modal_Dialog_Message = <div>Accessing API Key requires validation o
# pac4jRealm = com.github.alanger.nexus.plugin.realm.NexusPac4jRealm

## SAML buji-pac4j https://github.com/bujiio/buji-pac4j/blob/master/src/main/resources/buji-pac4j-default.ini
## SAML buji-pac4j-demo https://github.com/pac4j/buji-pac4j-demo/blob/master/src/main/resources/shiro.ini
authorizationGenerator = org.pac4j.core.authorization.generator.FromAttributesAuthorizationGenerator
authorizationGenerator.roleAttributes = ${PAC4J_ROLE_ATTRS:-roles}
authorizationGenerator.permissionAttributes = ${PAC4J_PERMISSION_ATTRS:-permission}
Expand Down Expand Up @@ -88,18 +89,27 @@ tokenRealm.authenticationCachingEnabled = true
; securityManager.realms = $iniRealm, $pac4jRealm, $tokenRealm

## Pac4j filters
callbackFilter = io.buji.pac4j.filter.CallbackFilter
callbackFilter = org.pac4j.jee.filter.CallbackFilter
callbackFilter.config = $config
callbackFilter.defaultUrl = /${NEXUS_CONTEXT:-}
callbackFilter.defaultClient = SAML2Client
callbackFilter.renewSession = false
# Required since buji-pac4j:8.0.0 (or use pac4jToShiroBridge)
; callbackLogic = com.github.alanger.nexus.plugin.Pac4jCallbackLogic
; config.callbackLogic = $callbackLogic
; callbackFilter.callbackLogic = $callbackLogic

saml2SecurityFilter = io.buji.pac4j.filter.SecurityFilter
# Required since buji-pac4j:8.0.0 (or use callbackLogic)
pac4jToShiroBridge = io.buji.pac4j.bridge.Pac4jShiroBridge
pac4jToShiroBridge.config = $config

saml2SecurityFilter = org.pac4j.jee.filter.SecurityFilter
saml2SecurityFilter.config = $config
saml2SecurityFilter.clients = SAML2Client

pac4jLogout = io.buji.pac4j.filter.LogoutFilter
pac4jLogout = org.pac4j.jee.filter.LogoutFilter
pac4jLogout.config = $config
; pac4jCentralLogout = io.buji.pac4j.filter.LogoutFilter
; pac4jCentralLogout = org.pac4j.jee.filter.LogoutFilter
; pac4jCentralLogout.config = $config
; pac4jCentralLogout.localLogout = false
; pac4jCentralLogout.centralLogout = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import com.github.alanger.shiroext.http.MockHttpServletRequest;
import com.github.alanger.shiroext.http.MockHttpServletResponse;
import com.github.alanger.shiroext.realm.jdbc.JdbcRealmName;
import com.github.alanger.shiroext.realm.pac4j.Pac4jRealmName;
import com.github.alanger.nexus.plugin.realm.NexusPac4jRealm;

/**
* Main object of script initialization.
Expand Down Expand Up @@ -221,7 +221,7 @@ public void initObjects() {
objects.put("echoRealm", echoRealm);

// Realm for authorization by SAML/SSO
Pac4jRealmName pac4jRealm = (Pac4jRealmName) objects.getOrDefault("pac4jRealm", DI.getInstance().pac4jRealm);
NexusPac4jRealm pac4jRealm = (NexusPac4jRealm) objects.getOrDefault("pac4jRealm", DI.getInstance().pac4jRealm);
pac4jRealm.setName("pac4jRealm");
objects.put("pac4jRealm", pac4jRealm);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.subject.support.WebDelegatingSubject;

import com.github.alanger.shiroext.realm.pac4j.Pac4jPrincipalName;
import com.github.alanger.shiroext.realm.pac4j.Pac4jRealmName;
import com.github.alanger.nexus.plugin.realm.Pac4jPrincipalName;
import com.github.alanger.nexus.plugin.realm.Pac4jRealmName;
import com.github.alanger.shiroext.realm.RealmUtils;
import com.github.alanger.shiroext.realm.ICommonRole;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import io.buji.pac4j.filter.SecurityFilter;
import org.pac4j.jee.filter.SecurityFilter;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,53 @@

import org.pac4j.core.config.Config;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.context.session.SessionStore;
import org.pac4j.core.engine.DefaultCallbackLogic;
import org.pac4j.core.http.adapter.HttpActionAdapter;
import io.buji.pac4j.engine.ShiroCallbackLogic;
import io.buji.pac4j.profile.ShiroProfileManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Debug only.
* Required since buji-pac4j:8.0.0, add to in shiro.ini:
*
* <pre>
* callbackLogic = com.github.alanger.nexus.plugin.Pac4jCallbackLogic
* config.callbackLogic = $callbackLogic
* callbackFilter.callbackLogic = $callbackLogic
* </pre>
*
* Or use {@link io.buji.pac4j.bridge.Pac4jShiroBridge}:
* <pre>
* pac4jToShiroBridge = io.buji.pac4j.bridge.Pac4jShiroBridge
* pac4jToShiroBridge.config = $config
* </pre>
*
* @see https://github.com/bujiio/buji-pac4j/blob/8.0.x/src/main/resources/buji-pac4j-default.ini
* @see https://github.com/pac4j/buji-pac4j-demo/blob/8.0.x/src/main/resources/shiro.ini
*/
public class Pac4jCallbackLogic<R, C extends WebContext> extends ShiroCallbackLogic<R, C> {
public class Pac4jCallbackLogic extends DefaultCallbackLogic {

private static final Logger logger = LoggerFactory.getLogger(Pac4jCallbackLogic.class);

public Pac4jCallbackLogic() {
super();
this.setProfileManagerFactory(ShiroProfileManager::new);
}

@Override
public R perform(C context, Config config, HttpActionAdapter<R, C> httpActionAdapter, String inputDefaultUrl,
Boolean inputSaveInSession, Boolean inputMultiProfile, Boolean inputRenewSession, String client) {
public Object perform(WebContext webContext, SessionStore sessionStore, Config config,
HttpActionAdapter httpActionAdapter, String inputDefaultUrl, Boolean inputRenewSession,
String defaultClient) {
try {
return super.perform(context, config, httpActionAdapter, inputDefaultUrl, inputSaveInSession, inputMultiProfile,
inputRenewSession, client);
return super.perform(webContext, sessionStore, config, httpActionAdapter, inputDefaultUrl,
inputRenewSession, defaultClient);
} catch (final Exception e) {
// Verbose error from org.opensaml.xmlsec.signature.support.SignatureValidator
logger.trace("Callback perform error:", e);
throw e;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
import org.slf4j.LoggerFactory;
import org.sonatype.nexus.security.NexusSimpleAuthenticationInfo;
import org.sonatype.nexus.security.RealmCaseMapping;
import com.github.alanger.shiroext.realm.pac4j.Pac4jPrincipalName;
import com.github.alanger.shiroext.realm.pac4j.Pac4jRealmName;
import io.buji.pac4j.token.Pac4jToken;

/**
Expand Down
Loading

0 comments on commit a37e9bc

Please sign in to comment.