Skip to content

Commit

Permalink
upstream: b=main,r=3d02b1bc4d2c108074576905aed211b76b877d8c,t=2024-04…
Browse files Browse the repository at this point in the history
…-19-1242-47895
  • Loading branch information
sonatype-zion committed Apr 19, 2024
1 parent 9a59ea3 commit 641f5f5
Show file tree
Hide file tree
Showing 36 changed files with 864 additions and 351 deletions.
11 changes: 10 additions & 1 deletion buildsupport/testing/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@
<testcontainers.version>1.19.1</testcontainers.version>
<iq.version>1.168.0</iq.version>


<jupiter.version>5.10.2</jupiter.version>

<gatling.version>3.9.5</gatling.version>
</properties>

<dependencyManagement>
Expand Down Expand Up @@ -297,7 +300,7 @@
<dependency>
<groupId>io.gatling.highcharts</groupId>
<artifactId>gatling-charts-highcharts</artifactId>
<version>3.0.3</version>
<version>${gatling.version}</version>
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
Expand All @@ -306,6 +309,12 @@
</exclusions>
</dependency>

<dependency>
<groupId>io.gatling</groupId>
<artifactId>gatling-http-java</artifactId>
<version>${gatling.version}</version>
</dependency>

<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-admin-client</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ public interface FeatureFlags
*/
String REPOSITORY_SIZE_ENABLED = "nexus.repository.size";

String REPOSITORY_SIZE_ENABLED_NAMED = "${nexus.repository.size:-false}";
String REPOSITORY_SIZE_ENABLED_NAMED = "${nexus.repository.size:-true}";

String CONTENT_USAGE_ENABLED_NAMED = "${nexus.contentUsageMetrics.enabled:-true}";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,11 @@ public interface ApiKeyDAO
* @param domain the domain, e.g. npm keys, nuget keys
*/
void deleteApiKeysByDomain(@Param("domain") String domain);

/**
* Remove all expired API Keys
*
* @param expiration the date of expiration
*/
void deleteApiKeyByExpirationDate(@Param("expiration") OffsetDateTime expiration);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
Expand Down Expand Up @@ -66,10 +65,11 @@ public class ApiKeyStoreImpl
private final DefaultApiKeyFactory defaultApiKeyFactory;

@Inject
public ApiKeyStoreImpl(final DataSessionSupplier sessionSupplier,
final UserPrincipalsHelper principalsHelper,
final Map<String, ApiKeyFactory> apiKeyFactories,
final DefaultApiKeyFactory defaultApiKeyFactory)
public ApiKeyStoreImpl(
final DataSessionSupplier sessionSupplier,
final UserPrincipalsHelper principalsHelper,
final Map<String, ApiKeyFactory> apiKeyFactories,
final DefaultApiKeyFactory defaultApiKeyFactory)
{
super(sessionSupplier);

Expand Down Expand Up @@ -148,7 +148,7 @@ public void deleteApiKeys() {
public void purgeApiKeys() {
checkCancellation();
List<PrincipalCollection> candidates = newArrayList(doBrowsePrincipals());
for (Iterator<PrincipalCollection> itr = candidates.iterator(); itr.hasNext();) {
for (Iterator<PrincipalCollection> itr = candidates.iterator(); itr.hasNext(); ) {
checkCancellation();
if (userExists(itr.next())) {
itr.remove(); // don't purge keys belonging to existing users
Expand Down Expand Up @@ -212,6 +212,12 @@ public void deleteApiKeys(final String domain) {
dao().deleteApiKeysByDomain(domain);
}

@Transactional
@Override
public void deleteApiKeys(final OffsetDateTime expiration) {
dao().deleteApiKeyByExpirationDate(expiration);
}

/*
* Finds ApiKey records for the provided username, and ensures the realm is the same
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ public class OrientApiKeyEntityAdapter

private static final String P_CREATED = "created";

private static final String P_EXPIRED_TIME = "expired";

private static final String I_APIKEY = new OIndexNameBuilder()
.type(DB_CLASS)
.property(P_DOMAIN)
Expand All @@ -100,6 +102,10 @@ public class OrientApiKeyEntityAdapter
private static final String COUNT_DOMAIN_QUERY_STRING =
format("SELECT count(*) as count FROM %s WHERE %s = :domain", DB_CLASS, P_DOMAIN);

private static final String
EXPIRED_QUERY_STRING = format(
"SELECT FROM %s WHERE %s < :expired", DB_CLASS, P_CREATED);

private final DeleteEntitiesAction deleteAll = new DeleteEntitiesAction(this);

private final ReadEntityByPropertyAction<OrientApiKey> findByApiKey =
Expand Down Expand Up @@ -270,4 +276,13 @@ public OrientApiKey findByApiKey(final ODatabaseDocumentTx db, final String doma
checkNotNull(apiKey);
return findByApiKey.execute(db, domain, String.valueOf(apiKey));
}

public Iterable<OrientApiKey> browseByExpiration(
final ODatabaseDocumentTx db,
final OffsetDateTime expiration)
{
Map<String, Object> params = ImmutableMap.of(P_EXPIRED_TIME, expiration.toInstant().toEpochMilli());

return query(db, EXPIRED_QUERY_STRING, params);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import javax.annotation.Priority;
import javax.inject.Inject;
import javax.inject.Named;
Expand Down Expand Up @@ -231,8 +230,9 @@ public void on(final UserPrincipalsExpired event) {
}
}

private Iterable<OrientApiKey> findByPrimaryPrincipal(final ODatabaseDocumentTx db,
final PrincipalCollection principals)
private Iterable<OrientApiKey> findByPrimaryPrincipal(
final ODatabaseDocumentTx db,
final PrincipalCollection principals)
{
final String primaryPrincipal = checkNotNull(principals).getPrimaryPrincipal().toString();
return entityAdapter.browseByPrimaryPrincipal(db, primaryPrincipal);
Expand Down Expand Up @@ -264,7 +264,6 @@ public Collection<ApiKey> browseByCreatedDate(final String domain, final OffsetD
return convert(keys);
}


@Override
public int count(final String domain) {
return inTx(databaseInstance)
Expand All @@ -282,14 +281,24 @@ public void deleteApiKeys(final String domain) {
});
}

@Override
public void deleteApiKeys(final OffsetDateTime expiration) {
inTxRetry(databaseInstance).run(db -> {
for (OrientApiKey entity : entityAdapter.browseByExpiration(db, expiration)) {
checkCancellation();
entityAdapter.deleteEntity(db, entity);
}
});
}

private static Collection<ApiKey> convert(final Iterable<OrientApiKey> keys) {
return StreamSupport.stream(keys.spliterator(), false)
.map(ApiKey.class::cast)
.collect(Collectors.toList());
}

private boolean principalsEqual(final PrincipalCollection a, final PrincipalCollection b) {
return Objects.equals(a.getPrimaryPrincipal(), b.getPrimaryPrincipal()) &&
Objects.equals(a.getRealmNames(), b.getRealmNames());
return Objects.equals(a.getPrimaryPrincipal(), b.getPrimaryPrincipal()) &&
Objects.equals(a.getRealmNames(), b.getRealmNames());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import javax.cache.Cache;
import javax.cache.expiry.CreatedExpiryPolicy;
import javax.cache.expiry.Duration;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

import org.sonatype.goodies.common.Time;
import org.sonatype.nexus.cache.CacheHelper;
import org.sonatype.nexus.common.app.ManagedLifecycle;
import org.sonatype.nexus.common.entity.EntityId;
import org.sonatype.nexus.common.event.EventAware;
Expand Down Expand Up @@ -66,6 +70,7 @@
import com.google.common.eventbus.AllowConcurrentEvents;
import com.google.common.eventbus.Subscribe;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.subject.Subject;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.stream.Collectors.toList;
Expand All @@ -87,25 +92,38 @@ public class SelectorManagerImpl
extends StateGuardLifecycleSupport
implements SelectorManager, EventAware
{

private static final SoftReference<List<SelectorConfiguration>> EMPTY_CACHE = new SoftReference<>(null);

private static final String USER_CACHE_KEY = "SelectorManager";

private final SelectorConfigurationStore store;

private final SecuritySystem securitySystem;

private final LoadingCache<SelectorConfiguration, Selector> selectorCache;

private final CacheHelper cacheHelper;

private final Duration userCacheTimeout;

private volatile SoftReference<List<SelectorConfiguration>> cachedBrowseResult = EMPTY_CACHE;

private Map<String, Role> rolesCache = Collections.emptyMap();

private Cache<String, User> userCache;

@Inject
public SelectorManagerImpl(final SelectorConfigurationStore store,
final SecuritySystem securitySystem,
final SelectorFactory selectorFactory)
final SelectorFactory selectorFactory,
final CacheHelper cacheHelper,
@Named("${nexus.shiro.cache.defaultTimeToLive:-2m}") final Time userCacheTimeout)
{
this.store = checkNotNull(store);
this.securitySystem = checkNotNull(securitySystem);
this.cacheHelper = cacheHelper;
this.userCacheTimeout = new Duration(userCacheTimeout.getUnit(), userCacheTimeout.getValue());

checkNotNull(selectorFactory);
selectorCache = CacheBuilder.newBuilder().softValues().build(CacheLoader.from(config -> {
Expand Down Expand Up @@ -292,7 +310,7 @@ public List<SelectorConfiguration> browseActive(

try {
authorizationManager = securitySystem.getAuthorizationManager(DEFAULT_SOURCE);
currentUser = securitySystem.currentUser();
currentUser = getCurrentUser();
}
catch (NoSuchAuthorizationManagerException | UserNotFoundException e) {
log.warn("Unable to load active content selectors", e);
Expand Down Expand Up @@ -340,6 +358,30 @@ public SelectorConfiguration newSelectorConfiguration(
return selectorConfiguration;
}

private User getCurrentUser() throws UserNotFoundException {
Subject subject = securitySystem.getSubject();
if (subject.isAuthenticated()) {
Cache<String, User> cache = getUserCache();
String userKey = subject.getPrincipal().toString() + subject.getPrincipals().getRealmNames().toString();
User currentUser = cache.get(userKey);
if (currentUser == null) {
currentUser = securitySystem.currentUser();
if (currentUser != null) {
cache.put(userKey, currentUser);
}
}
return currentUser;
}
return null;
}

private Cache<String, User> getUserCache() {
if (userCache == null) {
userCache = cacheHelper.maybeCreateCache(USER_CACHE_KEY, CreatedExpiryPolicy.factoryOf(userCacheTimeout));
}
return userCache;
}

private boolean matchesFormatOrRepository(final Collection<String> repositoryNames,
final Collection<String> formats,
final Privilege privilege)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,15 @@
FROM api_key
WHERE domain = #{domain};
</select>

<delete id="deleteApiKeysByDomain">
DELETE FROM api_key
WHERE domain = #{domain};
</delete>

<delete id="deleteApiKeyByExpirationDate">
DELETE FROM api_key
WHERE created &lt; #{expiration};
</delete>

</mapper>
Loading

0 comments on commit 641f5f5

Please sign in to comment.