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

Correction of whoami response type for backwards compatibility and output of mapped roles from whoami. #31

Closed
wants to merge 4 commits into from
Closed
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
Expand Up @@ -331,7 +331,13 @@ public void run() {
}
}
};
injectedExecutorService.getValue().execute(r);
ExecutorService executorService = injectedExecutorService.getOptionalValue();
if (executorService != null) {
injectedExecutorService.getValue().execute(r);
} else {
Thread executorShutdown = new Thread(r, getClass().getSimpleName() + " Shutdown Thread");
executorShutdown.start();
}
}

/**
Expand Down
Expand Up @@ -22,7 +22,6 @@

package org.jboss.as.controller.access;


import java.util.Set;

/**
Expand Down Expand Up @@ -72,20 +71,16 @@ public interface Authorizer {
AuthorizationResult authorizeJmxOperation(Caller caller, Environment callEnvironment, JmxAction action);

/**
* Gets whether the given caller can run in the given role.
* Gets the set of roles the caller can run as taking into account and requested 'run as' roles.
*
* @param roleName the name of the role. Cannot be {@code null}
* @param caller the caller. Cannot be {@code null}
* @param callEnvironment the call environment. Cannot be {@code null}
* @param operationHeaderRoles any roles specified as headers in the operation. May be {@code null}
* @param runAsRoles any requested 'run as' roles. May be {@code null}
*
* @return {@code true} if the caller maps to the given role in the given environment. {@code false} if the
* caller does not map to the role for whatever reason, including because the authorizer implementation
* is not {@link AuthorizerDescription#isRoleBased() role based} or because the implementation does not support mapping roles
* without {@link Action}, {@link JmxAction}, {@link TargetResource} and/or {@link TargetAttribute}
* information.
* @return The set of roles assigned to the caller, an empty set may be returned of no roles are assigned or {@code null}
* may be returned if the access control provider does not support role mapping.
*/
boolean isCallerInRole(String roleName, Caller caller, Environment callEnvironment, Set<String> operationHeaderRoles);
Set<String> getCallerRoles(Caller caller, Environment callEnvironment, Set<String> runAsroles);

/**
* Description of standard information about the custom authorizer.
Expand Down
Expand Up @@ -79,8 +79,8 @@ public void setDelegate(Authorizer delegate) {
}

@Override
public boolean isCallerInRole(String roleName, Caller caller, Environment callEnvironment, Set<String> operationHeaderRoles) {
return delegate.isCallerInRole(roleName, caller, callEnvironment, operationHeaderRoles);
public Set<String> getCallerRoles(Caller caller, Environment callEnvironment, Set<String> runAsroles) {
return delegate.getCallerRoles(caller, callEnvironment, runAsroles);
}

@Override
Expand Down
Expand Up @@ -34,6 +34,7 @@
import org.jboss.as.controller.access.Authorizer;
import org.jboss.as.controller.access.AuthorizerConfiguration;
import org.jboss.as.controller.access.Caller;
import org.jboss.as.controller.access.rbac.StandardRBACAuthorizer;

/**
* Standard {@link AuthorizerConfiguration} implementation that also exposes mutator APIs for use by
Expand All @@ -51,11 +52,33 @@ public class WritableAuthorizerConfiguration implements AuthorizerConfiguration
private volatile RoleMaps roleMaps;
private final Set<ScopedRoleListener> scopedRoleListeners = new LinkedHashSet<ScopedRoleListener>();

WritableAuthorizerConfiguration(Authorizer.AuthorizerDescription authorizerDescription) {
public WritableAuthorizerConfiguration(Authorizer.AuthorizerDescription authorizerDescription) {
this.authorizerDescription = authorizerDescription;
this.roleMaps = new RoleMaps(authorizerDescription.getStandardRoles(), Collections.<String, ScopedRole>emptyMap());
}

/**
* Reset the internal state of this object back to what it originally was.
* Only to be used in a slave host controller following a post-boot reconnect
* to the master.
*/
public synchronized void domainReconnectReset() {
this.authorizerDescription = StandardRBACAuthorizer.AUTHORIZER_DESCRIPTION;
this.useRealmRoles = this.nonFacadeMBeansSensitive = false;
this.roleMappings = new HashMap<String, RoleMappingImpl>();
RoleMaps oldRoleMaps = this.roleMaps;
this.roleMaps = new RoleMaps(authorizerDescription.getStandardRoles(), Collections.<String, ScopedRole>emptyMap());
for (ScopedRole role : oldRoleMaps.scopedRoles.values()) {
for (ScopedRoleListener listener : scopedRoleListeners) {
try {
listener.scopedRoleRemoved(role);
} catch (Exception ignored) {
// TODO log an ERROR
}
}
}
}

public synchronized void registerScopedRoleListener(ScopedRoleListener listener) {
scopedRoleListeners.add(listener);
}
Expand Down
Expand Up @@ -130,9 +130,9 @@ public AuthorizationResult authorizeJmxOperation(Caller caller, Environment call
}

@Override
public boolean isCallerInRole(String roleName, Caller caller, Environment callEnvironment, Set<String> operationHeaderRoles) {
public Set<String> getCallerRoles(Caller caller, Environment callEnvironment, Set<String> runAsroles) {
// Not supported in this base class; see StandardRBACAuthorizer
return false;
return null;
}

private AuthorizationResult authorize(Set<String> callerRoles, StandardRole...roles) {
Expand Down
Expand Up @@ -91,18 +91,8 @@ private StandardRBACAuthorizer(final AuthorizerConfiguration configuration,
}

@Override
public boolean isCallerInRole(String roleName, Caller caller, Environment callEnvironment, Set<String> operationHeaderRoles) {
Set<String> mappedRoles = roleMapper.mapRoles(caller, callEnvironment, operationHeaderRoles);
if (mappedRoles.contains(roleName)) {
return true;
} else {
for (String role : mappedRoles) {
if (role.equalsIgnoreCase(roleName)) {
return true;
}
}
}
return false;
public Set<String> getCallerRoles(Caller caller, Environment callEnvironment, Set<String> runAsroles) {
return roleMapper.mapRoles(caller, callEnvironment, runAsroles);
}

@Override
Expand Down
Expand Up @@ -1079,8 +1079,8 @@ public AuthorizationResult authorizeJmxOperation(Caller caller, Environment call
}

@Override
public boolean isCallerInRole(String roleName, Caller caller, Environment callEnvironment, Set<String> operationHeaderRoles) {
return false;
public Set<String> getCallerRoles(Caller caller, Environment callEnvironment, Set<String> runAsroles) {
return null;
}

@Override
Expand Down
Expand Up @@ -463,7 +463,7 @@ public void initCoreModel(Resource rootResource, ManagementResourceRegistration
@Override
public void registerHostModel(String hostName, ManagementResourceRegistration rootRegistration) {
}
},ProcessType.HOST_CONTROLLER);
},ProcessType.HOST_CONTROLLER, authorizer);

HostModelUtil.createHostRegistry(
hostName,
Expand Down Expand Up @@ -516,7 +516,7 @@ public void initCoreModel(Resource rootResource, ManagementResourceRegistration
@Override
public void registerHostModel(String hostName, ManagementResourceRegistration root) {
}
},processType);
},processType, authorizer);
}

}
Expand Down
Expand Up @@ -36,6 +36,7 @@
import org.jboss.as.controller.access.management.DelegatingConfigurableAuthorizer;
import org.jboss.as.controller.audit.ManagedAuditLogger;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
import org.jboss.as.controller.registry.Resource;
import org.jboss.as.controller.services.path.PathManagerService;
import org.jboss.as.domain.management._private.DomainManagementResolver;
import org.jboss.as.domain.management.access.AccessAuthorizationResourceDefinition;
Expand All @@ -56,6 +57,12 @@ public class CoreManagementResourceDefinition extends SimpleResourceDefinition {

public static final PathElement PATH_ELEMENT = PathElement.pathElement(CORE_SERVICE, MANAGEMENT);

public static void registerDomainResource(Resource parent) {
Resource coreManagement = Resource.Factory.create();
coreManagement.registerChild(AccessAuthorizationResourceDefinition.PATH_ELEMENT, AccessAuthorizationResourceDefinition.RESOURCE);
parent.registerChild(PATH_ELEMENT, coreManagement);
}

private final Environment environment;
private final List<ResourceDefinition> interfaces;
private final DelegatingConfigurableAuthorizer authorizer;
Expand Down
Expand Up @@ -43,6 +43,7 @@ public class ModelDescriptionConstants {
public static final String KEYSTORE_PATH = "keystore-path";
public static final String KEYSTORE_RELATIVE_TO = "keystore-relative-to";
public static final String LOCAL = "local";
public static final String MAPPED_ROLES = "mapped-roles";
public static final String MECHANISM = "mechanism";
public static final String NAME = "name";
public static final String PASSWORD = "password";
Expand Down
Expand Up @@ -46,8 +46,7 @@ public ModelNode getModel() {

@Override
public void writeModel(ModelNode newModel) {
//TODO i18n
throw new IllegalStateException("Not writable");
// called in slave host boot; ignore this unless overridden
}

@Override
Expand Down
@@ -0,0 +1,77 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2013, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/

package org.jboss.as.domain.management.access;

import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.OperationContext;
import org.jboss.as.controller.OperationDefinition;
import org.jboss.as.controller.OperationFailedException;
import org.jboss.as.controller.OperationStepHandler;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.SimpleOperationDefinitionBuilder;
import org.jboss.as.controller.access.management.DelegatingConfigurableAuthorizer;
import org.jboss.as.controller.registry.OperationEntry;
import org.jboss.as.domain.management._private.DomainManagementResolver;
import org.jboss.dmr.ModelNode;

/**
* Internal op called.
*
* @author Brian Stansberry (c) 2013 Red Hat Inc.
*/
public class AccessAuthorizationDomainSlaveConfigHandler implements OperationStepHandler {

public static final String OPERATION_NAME = "configure-from-domain";
public static final OperationDefinition DEFINITION = new SimpleOperationDefinitionBuilder(OPERATION_NAME, DomainManagementResolver.getResolver("core.access-control"))
.withFlag(OperationEntry.Flag.HOST_CONTROLLER_ONLY)
.setPrivateEntry()
.build();

private final DelegatingConfigurableAuthorizer configurableAuthorizer;

AccessAuthorizationDomainSlaveConfigHandler(DelegatingConfigurableAuthorizer configurableAuthorizer) {
this.configurableAuthorizer = configurableAuthorizer;
}

@Override
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {
final ModelNode model = context.readResourceForUpdate(PathAddress.EMPTY_ADDRESS).getModel();
for (AttributeDefinition ad : AccessAuthorizationResourceDefinition.ATTRIBUTES) {
ad.validateAndSet(operation, model);
}
context.addStep(new OperationStepHandler() {
@Override
public void execute(OperationContext context, ModelNode operation) throws OperationFailedException {

ModelNode provider = AccessAuthorizationResourceDefinition.PROVIDER.resolveModelAttribute(context, model);
AccessAuthorizationProviderWriteAttributeHander.updateAuthorizer(provider, configurableAuthorizer);
boolean useRealmRoles = AccessAuthorizationResourceDefinition.USE_REALM_ROLES.resolveModelAttribute(context, model).asBoolean();
configurableAuthorizer.getWritableAuthorizerConfiguration().setUseRealmRoles(useRealmRoles);

context.completeStep(OperationContext.RollbackHandler.NOOP_ROLLBACK_HANDLER);
}
}, OperationContext.Stage.RUNTIME);

context.stepCompleted();
}
}
Expand Up @@ -31,8 +31,8 @@
import org.jboss.as.controller.access.AuthorizerConfiguration;
import org.jboss.as.controller.access.management.DelegatingConfigurableAuthorizer;
import org.jboss.as.controller.access.rbac.RoleMapper;
import org.jboss.as.controller.access.rbac.StandardRoleMapper;
import org.jboss.as.controller.access.rbac.StandardRBACAuthorizer;
import org.jboss.as.controller.access.rbac.StandardRoleMapper;
import org.jboss.as.controller.access.rbac.SuperUserRoleMapper;
import org.jboss.as.controller.registry.Resource;
import org.jboss.as.domain.management.access.AccessAuthorizationResourceDefinition.Provider;
Expand Down Expand Up @@ -63,7 +63,7 @@ protected void finishModelStage(OperationContext context, ModelNode operation, S
/*
* As the provider is being set to RBAC we need to be sure roles can be assigned.
*/
RbacSanityCheckOperation.registerOperation(context);
RbacSanityCheckOperation.addOperation(context);
}
}

Expand All @@ -81,7 +81,7 @@ protected boolean applyUpdateToRuntime(OperationContext context, ModelNode opera
if (!context.isBooting()) {
return true;
}
updateAuthorizer(resolvedValue);
updateAuthorizer(resolvedValue, configurableAuthorizer);
}

return false;
Expand All @@ -90,30 +90,22 @@ protected boolean applyUpdateToRuntime(OperationContext context, ModelNode opera
@Override
protected void revertUpdateToRuntime(OperationContext context, ModelNode operation, String attributeName,
ModelNode valueToRestore, ModelNode valueToRevert, Void handback) throws OperationFailedException {
updateAuthorizer(valueToRestore);
updateAuthorizer(valueToRestore, configurableAuthorizer);
}

private void updateAuthorizer(final ModelNode value) {
static void updateAuthorizer(final ModelNode value, final DelegatingConfigurableAuthorizer configurableAuthorizer) {
String providerName = value.asString().toUpperCase(Locale.ENGLISH);
Provider provider = Provider.valueOf(providerName);
AuthorizerConfiguration authorizerConfiguration = configurableAuthorizer.getWritableAuthorizerConfiguration();
RoleMapper roleMapper;
if (provider == Provider.SIMPLE) {
roleMapper = new SuperUserRoleMapper(authorizerConfiguration);
} else {
roleMapper = getRoleBasedAuthorizer();
roleMapper = new StandardRoleMapper(configurableAuthorizer.getWritableAuthorizerConfiguration());
}
Authorizer delegate = StandardRBACAuthorizer.create(configurableAuthorizer.getWritableAuthorizerConfiguration(),
roleMapper);
configurableAuthorizer.setDelegate(delegate);
}

private RoleMapper getSimpleAuthorizer(AuthorizerConfiguration authorizerConfiguration) {
return new SuperUserRoleMapper(configurableAuthorizer.getWritableAuthorizerConfiguration());
}

private RoleMapper getRoleBasedAuthorizer() {
return new StandardRoleMapper(configurableAuthorizer.getWritableAuthorizerConfiguration());
}

}
Expand Up @@ -26,6 +26,9 @@
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.AUTHORIZATION;
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ROLE;

import java.util.Arrays;
import java.util.List;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

Expand Down Expand Up @@ -101,6 +104,8 @@ public void marshallAsElement(AttributeDefinition attribute, ModelNode resourceM
.setDefaultValue(new ModelNode(false))
.setAllowExpression(true).build();

public static final List<AttributeDefinition> ATTRIBUTES = Arrays.<AttributeDefinition>asList(PROVIDER, USE_REALM_ROLES);

public static AccessAuthorizationResourceDefinition forDomain(DelegatingConfigurableAuthorizer configurableAuthorizer) {
return new AccessAuthorizationResourceDefinition(configurableAuthorizer, true, false);
}
Expand Down Expand Up @@ -173,6 +178,16 @@ public void registerChildren(ManagementResourceRegistration resourceRegistration
}
}

@Override
public void registerOperations(ManagementResourceRegistration resourceRegistration) {
super.registerOperations(resourceRegistration);
if (isDomain) {
// Op to apply config from the master to a slave
resourceRegistration.registerOperationHandler(AccessAuthorizationDomainSlaveConfigHandler.DEFINITION,
new AccessAuthorizationDomainSlaveConfigHandler(configurableAuthorizer));
}
}

private static Resource createResource() {
Resource accessControlRoot = Resource.Factory.create();
accessControlRoot.registerChild(AccessConstraintResources.APPLICATION_PATH_ELEMENT, AccessConstraintResources.APPLICATION_RESOURCE);
Expand Down
Expand Up @@ -53,7 +53,7 @@ protected void finishModelStage(OperationContext context, ModelNode operation, S
* Using roles from the realm has been disabled so now need to check if there that RBAC has been disabled or an
* alternative mapping strategy is in place.
*/
RbacSanityCheckOperation.registerOperation(context);
RbacSanityCheckOperation.addOperation(context);
}
}

Expand Down