Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ISPN-12868 Configure ACL cache #9165

Merged
merged 1 commit into from
Mar 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ public interface RestSecurityClient {
CompletionStage<RestResponse> grant(String principal, List<String> roles);

CompletionStage<RestResponse> deny(String principal, List<String> roles);

CompletionStage<RestResponse> flushCache();
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.infinispan.client.rest.impl.okhttp;

import static org.infinispan.client.rest.impl.okhttp.RestClientOkHttp.EMPTY_BODY;

import java.util.List;
import java.util.concurrent.CompletionStage;

Expand Down Expand Up @@ -48,4 +50,11 @@ private CompletionStage<RestResponse> modifyAcl(String principal, List<String> r
builder.url(sb.toString()).put(Util.EMPTY_REQUEST);
return client.execute(builder);
}

@Override
public CompletionStage<RestResponse> flushCache() {
Request.Builder builder = new Request.Builder();
builder.post(EMPTY_BODY).url(baseSecurityURL + "cache?action=flush");
return client.execute(builder);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
public class GlobalAuthorizationConfiguration implements ConfigurationInfo {
private static final Map<String, Role> DEFAULT_ROLES;
public static final AttributeDefinition<Boolean> ENABLED = AttributeDefinition.builder("enabled", false).immutable().build();
public static final AttributeDefinition<Long> CACHE_SIZE = AttributeDefinition.builder("cacheSize", 1_000l).immutable().build();
public static final AttributeDefinition<AuditLogger> AUDIT_LOGGER = AttributeDefinition.builder("auditLogger", (AuditLogger) new NullAuditLogger()).copier(IdentityAttributeCopier.INSTANCE).serializer(ClassAttributeSerializer.INSTANCE).immutable().build();
public static final AttributeDefinition<Map<String, Role>> ROLES = AttributeDefinition.<Map<String, Role>>builder("roles", new HashMap<>())
.serializer(new AttributeSerializer<Map<String, Role>, GlobalAuthorizationConfiguration, ConfigurationBuilderInfo>() {
Expand All @@ -50,10 +49,9 @@ public Map<String, Role> initialize() {
return DEFAULT_ROLES;
}
}).build();
private final Attribute<Long> cacheSize;

static AttributeSet attributeDefinitionSet() {
return new AttributeSet(GlobalAuthorizationConfiguration.class, ENABLED, CACHE_SIZE, AUDIT_LOGGER, ROLES);
return new AttributeSet(GlobalAuthorizationConfiguration.class, ENABLED, AUDIT_LOGGER, ROLES);
}

static {
Expand Down Expand Up @@ -104,7 +102,6 @@ static AttributeSet attributeDefinitionSet() {
public GlobalAuthorizationConfiguration(AttributeSet attributes, PrincipalRoleMapperConfiguration roleMapperConfiguration) {
this.attributes = attributes.checkProtection();
this.enabled = attributes.attribute(ENABLED);
this.cacheSize = attributes.attribute(CACHE_SIZE);
this.auditLogger = attributes.attribute(AUDIT_LOGGER);
this.roles = attributes.attribute(ROLES);
this.roleMapperConfiguration = roleMapperConfiguration;
Expand All @@ -125,9 +122,7 @@ public boolean enabled() {
return enabled.get();
}

public long cacheSize() {
return cacheSize.get();
}


public AuditLogger auditLogger() {
return auditLogger.get();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.infinispan.configuration.global;

import static org.infinispan.configuration.global.GlobalAuthorizationConfiguration.AUDIT_LOGGER;
import static org.infinispan.configuration.global.GlobalAuthorizationConfiguration.CACHE_SIZE;
import static org.infinispan.configuration.global.GlobalAuthorizationConfiguration.ENABLED;
import static org.infinispan.configuration.global.GlobalAuthorizationConfiguration.ROLES;
import static org.infinispan.util.logging.Log.CONFIG;
Expand Down Expand Up @@ -54,11 +53,6 @@ public boolean isEnabled() {
return attributes.attribute(ENABLED).get();
}

public GlobalAuthorizationConfigurationBuilder cacheSize(long cacheSize) {
attributes.attribute(CACHE_SIZE).set(cacheSize);
return this;
}

/**
* The instance of an {@link AuditLogger} to be used to track operations performed on caches and cachemanagers. The default logger is
* the {@link NullAuditLogger}. You can also use the {@link LoggingAuditLogger} which will send audit messages to the log.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import org.infinispan.commons.configuration.ConfigurationInfo;
import org.infinispan.commons.configuration.attributes.AttributeDefinition;
import org.infinispan.commons.configuration.attributes.AttributeSet;
import org.infinispan.commons.configuration.elements.DefaultElementDefinition;
import org.infinispan.commons.configuration.elements.ElementDefinition;
import org.infinispan.configuration.parsing.Element;
Expand All @@ -16,14 +20,21 @@
*/
public class GlobalSecurityConfiguration implements ConfigurationInfo {
private final GlobalAuthorizationConfiguration authorization;
private final long securityCacheTimeout;
public static final AttributeDefinition<Integer> CACHE_SIZE = AttributeDefinition.builder("securityCacheSize", 1000).build();
public static final AttributeDefinition<Long> CACHE_TIMEOUT = AttributeDefinition.builder("securityCacheTimeout", TimeUnit.MINUTES.toMillis(5)).build();


static AttributeSet attributeDefinitionSet() {
return new AttributeSet(GlobalSecurityConfiguration.class, CACHE_SIZE, CACHE_TIMEOUT);
}

private static ElementDefinition ELEMENT_DEFINITION = new DefaultElementDefinition(Element.SECURITY.getLocalName());
private final List<ConfigurationInfo> subElements;
private final AttributeSet attributes;

GlobalSecurityConfiguration(GlobalAuthorizationConfiguration authorization, long securityCacheTimeout) {
public GlobalSecurityConfiguration(GlobalAuthorizationConfiguration authorization, AttributeSet attributes) {
this.authorization = authorization;
this.securityCacheTimeout = securityCacheTimeout;
this.attributes = attributes;
this.subElements = Collections.singletonList(authorization);
}

Expand All @@ -41,14 +52,37 @@ public GlobalAuthorizationConfiguration authorization() {
return authorization;
}

public long securityCacheSize() {
return attributes.attribute(CACHE_SIZE).get();
}

public long securityCacheTimeout() {
return securityCacheTimeout;
return attributes.attribute(CACHE_TIMEOUT).get();
}

@Override
public String toString() {
return "GlobalSecurityConfiguration [authorization=" + authorization
+ ", securityCacheTimeout=" + securityCacheTimeout + "]";
public AttributeSet attributes() {
return attributes;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GlobalSecurityConfiguration that = (GlobalSecurityConfiguration) o;
return Objects.equals(authorization, that.authorization) && Objects.equals(attributes, that.attributes);
}

@Override
public int hashCode() {
return Objects.hash(authorization, attributes);
}

@Override
public String toString() {
return "GlobalSecurityConfiguration{" +
"authorization=" + authorization +
", attributes=" + attributes +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package org.infinispan.configuration.global;

import static org.infinispan.configuration.global.GlobalSecurityConfiguration.CACHE_SIZE;
import static org.infinispan.configuration.global.GlobalSecurityConfiguration.CACHE_TIMEOUT;

import java.util.concurrent.TimeUnit;

import org.infinispan.commons.configuration.Builder;
import org.infinispan.commons.configuration.attributes.AttributeSet;

/**
* GlobalSecurityConfigurationBuilder.
Expand All @@ -12,21 +16,28 @@
*/
public class GlobalSecurityConfigurationBuilder extends AbstractGlobalConfigurationBuilder implements GlobalSecurityConfigurationChildBuilder, Builder<GlobalSecurityConfiguration> {
private final GlobalAuthorizationConfigurationBuilder authorizationBuilder;
private long securityCacheTimeout = 30000;
private final AttributeSet attributes;

public GlobalSecurityConfigurationBuilder(GlobalConfigurationBuilder builder) {
super(builder);
authorizationBuilder = new GlobalAuthorizationConfigurationBuilder(this);
this.authorizationBuilder = new GlobalAuthorizationConfigurationBuilder(this);
this.attributes = GlobalSecurityConfiguration.attributeDefinitionSet();
}

@Override
public GlobalAuthorizationConfigurationBuilder authorization() {
return authorizationBuilder;
}

@Override
public GlobalSecurityConfigurationBuilder securityCacheSize(int securityCacheSize) {
attributes.attribute(CACHE_SIZE).set(securityCacheSize);
return this;
}

@Override
public GlobalSecurityConfigurationBuilder securityCacheTimeout(long securityCacheTimeout, TimeUnit unit) {
this.securityCacheTimeout = unit.toMillis(securityCacheTimeout);
attributes.attribute(CACHE_TIMEOUT).set(unit.toMillis(securityCacheTimeout));
return this;
}

Expand All @@ -37,14 +48,13 @@ public void validate() {

@Override
public GlobalSecurityConfiguration create() {
return new GlobalSecurityConfiguration(authorizationBuilder.create(), securityCacheTimeout);
return new GlobalSecurityConfiguration(authorizationBuilder.create(), attributes.protect());
}

@Override
public GlobalSecurityConfigurationBuilder read(GlobalSecurityConfiguration template) {
this.authorizationBuilder.read(template.authorization());
this.attributes.read(template.attributes());
return this;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ public interface GlobalSecurityConfigurationChildBuilder extends GlobalConfigura
*/
GlobalAuthorizationConfigurationBuilder authorization();

/**
* Defines the size for the access role cache. The default value is 1000.
* @param securityCacheSize the number of access roles to cache
*/
GlobalSecurityConfigurationBuilder securityCacheSize(int securityCacheSize);

/**
* Defines the timeout for which to cache user access roles. A value of -1 means the entries
* never expire. A value of 0 will disable the cache.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public enum Attribute {
BIAS_LIFESPAN,
BLOCKING_EXECUTOR,
CACHE_SIZE,
CACHE_TIMEOUT,
CALIBRATE_BY_DELETES,
CAPACITY_FACTOR("capacity"),
CHUNK_SIZE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.infinispan.configuration.global.GlobalAuthorizationConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.configuration.global.GlobalRoleConfigurationBuilder;
import org.infinispan.configuration.global.GlobalSecurityConfigurationBuilder;
import org.infinispan.configuration.global.GlobalStateConfigurationBuilder;
import org.infinispan.configuration.global.SerializationConfigurationBuilder;
import org.infinispan.configuration.global.ShutdownHookBehavior;
Expand Down Expand Up @@ -763,7 +764,25 @@ private void parseContainer(ConfigurationReader reader, ConfigurationBuilderHold
}

private void parseGlobalSecurity(ConfigurationReader reader, ConfigurationBuilderHolder holder) {
ParseUtils.requireNoAttributes(reader);
GlobalSecurityConfigurationBuilder security = holder.getGlobalConfigurationBuilder().security();
for (int i = 0; i < reader.getAttributeCount(); i++) {
String value = reader.getAttributeValue(i);
Attribute attribute = Attribute.forName(reader.getAttributeName(i));
switch (attribute) {
case CACHE_SIZE: {
security.securityCacheSize(Integer.parseInt(value));
break;
}
case CACHE_TIMEOUT: {
security.securityCacheTimeout(Long.parseLong(value), TimeUnit.MILLISECONDS);
break;
}
default: {
throw ParseUtils.unexpectedAttribute(reader, i);
}
}
}

while (reader.inTag()) {
Element element = Element.forName(reader.getLocalName());
switch (element) {
Expand All @@ -788,10 +807,6 @@ private void parseGlobalAuthorization(ConfigurationReader reader, ConfigurationB
builder.auditLogger(Util.getInstance(value, holder.getClassLoader()));
break;
}
case CACHE_SIZE: {
builder.cacheSize(Long.parseLong(value));
break;
}
default: {
throw ParseUtils.unexpectedAttribute(reader, i);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ public DefaultCacheManager(GlobalConfiguration globalConfiguration, Configuratio
InternalCacheRegistry internalCacheRegistry = globalComponentRegistry.getComponent(InternalCacheRegistry.class);
this.globalComponentRegistry.registerComponent(cacheDependencyGraph, CACHE_DEPENDENCY_GRAPH, false);

this.authorizer = new Authorizer(globalConfiguration.security(), AuditContext.CACHEMANAGER, globalConfiguration.cacheManagerName());
this.authorizer = new Authorizer(globalConfiguration.security(), AuditContext.CACHEMANAGER, globalConfiguration.cacheManagerName(), null);
this.globalComponentRegistry.registerComponent(authorizer, Authorizer.class);

this.stats = new CacheContainerStatsImpl(this);
Expand Down Expand Up @@ -385,7 +385,7 @@ public DefaultCacheManager(ConfigurationBuilderHolder holder, boolean start) {
cacheManagerInfo = new CacheManagerInfo(this, getConfigurationManager(), internalCacheRegistry);
globalComponentRegistry.registerComponent(new HealthJMXExposerImpl(health), HealthJMXExposer.class);

authorizer = new Authorizer(globalConfiguration.security(), AuditContext.CACHEMANAGER, globalConfiguration.cacheManagerName());
authorizer = new Authorizer(globalConfiguration.security(), AuditContext.CACHEMANAGER, globalConfiguration.cacheManagerName(), null);
globalComponentRegistry.registerComponent(authorizer, Authorizer.class);

cacheManagerAdmin = new DefaultCacheManagerAdmin(this, authorizer, EnumSet.noneOf(CacheContainerAdmin.AdminFlag.class),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.infinispan.security;

import org.infinispan.Cache;
import java.util.Map;
import java.util.concurrent.CompletionStage;

import org.infinispan.factories.scopes.Scope;
import org.infinispan.factories.scopes.Scopes;

Expand All @@ -16,11 +18,12 @@ public interface GlobalSecurityManager {
/**
* Returns the global ACL cache
*/
Cache<?, ?> globalACLCache();
<K, V> Map<K, V> globalACLCache();

/**
* Flushes the ACL cache for this node
* @return
*/
void flushGlobalACLCache();
CompletionStage<Void> flushGlobalACLCache();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is public API, so we should deprecate rather than change it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really: the only way to obtain a GlobalSecurityManager is through the component registry. I wouldn't worry about it


}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package org.infinispan.security.impl;

import java.util.Map;

import javax.security.auth.Subject;

import org.infinispan.Cache;
import org.infinispan.configuration.cache.AuthorizationConfiguration;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.global.GlobalConfiguration;
Expand All @@ -11,7 +12,6 @@
import org.infinispan.factories.annotations.Inject;
import org.infinispan.factories.scopes.Scope;
import org.infinispan.factories.scopes.Scopes;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.security.AuditContext;
import org.infinispan.security.AuthorizationManager;
import org.infinispan.security.AuthorizationPermission;
Expand All @@ -35,14 +35,10 @@ public AuthorizationManagerImpl() {
@Inject
public void init(@ComponentName(KnownComponentNames.CACHE_NAME) String cacheName,
GlobalConfiguration globalConfiguration, Configuration configuration,
GlobalSecurityManager globalSecurityManager, EmbeddedCacheManager cacheManager) {
GlobalSecurityManager globalSecurityManager) {
this.configuration = configuration.security().authorization();
Cache<CachePrincipalPair, SubjectACL> globalACLCache =
(Cache<CachePrincipalPair, SubjectACL>) globalSecurityManager.globalACLCache();
Map<CachePrincipalPair, SubjectACL> globalACLCache = globalSecurityManager.globalACLCache();
this.authorizer = new Authorizer(globalConfiguration.security(), AuditContext.CACHE, cacheName, globalACLCache);
if (globalACLCache != null) {
SecurityActions.addCacheDependency(cacheManager, cacheName, globalACLCache.getName());
}
this.writePermission = configuration.module(CreatePermissionConfiguration.class) != null ?
AuthorizationPermission.CREATE : AuthorizationPermission.WRITE;
}
Expand Down