Skip to content
This repository has been archived by the owner on Jan 5, 2021. It is now read-only.

Commit

Permalink
Issue wildfly-security#123 Pull over the RunAsLifecycleInterceptor.
Browse files Browse the repository at this point in the history
  • Loading branch information
darranl committed Feb 28, 2018
1 parent c0d41e0 commit e4cdc42
Show file tree
Hide file tree
Showing 2 changed files with 204 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright 2018 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.wildfly.elytron.web.undertow.server.servlet;

import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;

import org.jboss.metadata.javaee.jboss.RunAsIdentityMetaData;
import org.wildfly.security.auth.server.RealmIdentity;
import org.wildfly.security.auth.server.RealmUnavailableException;
import org.wildfly.security.auth.server.SecurityDomain;
import org.wildfly.security.auth.server.SecurityIdentity;
import org.wildfly.security.authz.AuthorizationFailureException;
import org.wildfly.security.authz.RoleMapper;
import org.wildfly.security.authz.Roles;

import io.undertow.server.HttpServerExchange;
import io.undertow.servlet.handlers.ServletChain;
import io.undertow.servlet.handlers.ServletRequestContext;

/**
* Utility class to contain identity mapping methods.
*
* @author <a href="mailto:[email protected]">Darran Lofthouse</a>
*/
class IdentityMapping {

private static final String ANONYMOUS_PRINCIPAL = "anonymous";
private static final String SERVLET = "servlet";
private static final String EJB = "ejb";

static SecurityIdentity mapIdentity(SecurityIdentity securityIdentity, SecurityDomain securityDomain, HttpServerExchange exchange, Function<String, RunAsIdentityMetaData> runAsMapper) {
final ServletChain servlet = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getCurrentServlet();

RunAsIdentityMetaData runAsMetaData = runAsMapper.apply(servlet.getManagedServlet().getServletInfo().getName());
return performMapping(securityIdentity, securityDomain, runAsMetaData);
}

static SecurityIdentity performMapping(SecurityIdentity securityIdentity, SecurityDomain securityDomain, RunAsIdentityMetaData runAsMetaData) {
if (runAsMetaData != null) {
SecurityIdentity newIdentity = securityIdentity != null ? securityIdentity : securityDomain.getAnonymousSecurityIdentity();
String runAsPrincipal = runAsMetaData.getPrincipalName();
if (runAsPrincipal.equals(ANONYMOUS_PRINCIPAL)) {
try {
newIdentity = newIdentity.createRunAsAnonymous();
} catch (AuthorizationFailureException ex) {
newIdentity = newIdentity.createRunAsAnonymous(false);
}
} else {
if (! runAsPrincipalExists(securityDomain, runAsPrincipal)) {
newIdentity = securityDomain.createAdHocIdentity(runAsPrincipal);
} else {
try {
newIdentity = newIdentity.createRunAsIdentity(runAsPrincipal);
} catch (AuthorizationFailureException ex) {
newIdentity = newIdentity.createRunAsIdentity(runAsPrincipal, false);
}
}
}

final Set<String> runAsRoleNames = new HashSet<>(runAsMetaData.getRunAsRoles().size());
runAsRoleNames.add(runAsMetaData.getRoleName());
runAsRoleNames.addAll(runAsMetaData.getRunAsRoles());

RoleMapper runAsRoleMaper = RoleMapper.constant(Roles.fromSet(runAsRoleNames));

Roles servletRoles = newIdentity.getRoles(SERVLET);
newIdentity = newIdentity.withRoleMapper(SERVLET, runAsRoleMaper.or((roles) -> servletRoles));

Roles ejbRoles = newIdentity.getRoles(EJB);
newIdentity = newIdentity.withRoleMapper(EJB, runAsRoleMaper.or((roles) -> ejbRoles));

return newIdentity;
}

return securityIdentity;
}

static boolean runAsPrincipalExists(final SecurityDomain securityDomain, final String runAsPrincipal) {
RealmIdentity realmIdentity = null;
try {
realmIdentity = securityDomain.getIdentity(runAsPrincipal);
return realmIdentity.exists();
} catch (RealmUnavailableException e) {
// TODO Throw a replcement exception
throw new IllegalStateException(String.format("Unable to obtain identity for name %s", runAsPrincipal), e);
//throw UndertowLogger.ROOT_LOGGER.unableToObtainIdentity(runAsPrincipal, e);
} finally {
if (realmIdentity != null) {
realmIdentity.dispose();
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright 2018 Red Hat, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.wildfly.elytron.web.undertow.server.servlet;

import static org.wildfly.elytron.web.undertow.server.servlet.IdentityMapping.performMapping;

import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.function.Function;

import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.ServletException;

import org.jboss.metadata.javaee.jboss.RunAsIdentityMetaData;
import org.wildfly.security.auth.server.SecurityDomain;
import org.wildfly.security.auth.server.SecurityIdentity;

import io.undertow.servlet.api.FilterInfo;
import io.undertow.servlet.api.LifecycleInterceptor;
import io.undertow.servlet.api.ServletInfo;

/**
* A {@link LifecycleInterceptor} to associate the correct run as identity for lifecycle calls.
*
* @author <a href="mailto:[email protected]">Darran Lofthouse</a>
*/
class RunAsLifecycleInterceptor implements LifecycleInterceptor {

private final Function<String, RunAsIdentityMetaData> runAsMapper;
private final SecurityDomain securityDomain;

RunAsLifecycleInterceptor(Function<String, RunAsIdentityMetaData> runAsMapper, SecurityDomain securityDomain) {
this.runAsMapper = runAsMapper;
this.securityDomain = securityDomain;
}

private void doIt(ServletInfo servletInfo, LifecycleContext context) throws ServletException {
RunAsIdentityMetaData runAsMetaData = runAsMapper.apply(servletInfo.getName());

if (runAsMetaData != null) {
SecurityIdentity securityIdentity = performMapping(securityDomain.getAnonymousSecurityIdentity(), securityDomain, runAsMetaData);
try {
securityIdentity.runAs((PrivilegedExceptionAction<Void>) () -> {
context.proceed();
return null;
});
} catch (PrivilegedActionException e) {
Throwable cause = e.getCause();
if (cause instanceof ServletException) {
throw (ServletException) cause;
}
throw new ServletException(cause);
}
} else {
context.proceed();
}
}

@Override
public void init(ServletInfo servletInfo, Servlet servlet, LifecycleContext context) throws ServletException {
doIt(servletInfo, context);
}

@Override
public void init(FilterInfo filterInfo, Filter filter, LifecycleContext context) throws ServletException {
context.proceed();
}

@Override
public void destroy(ServletInfo servletInfo, Servlet servlet, LifecycleContext context) throws ServletException {
doIt(servletInfo, context);
}

@Override
public void destroy(FilterInfo filterInfo, Filter filter, LifecycleContext context) throws ServletException {
context.proceed();
}

}

0 comments on commit e4cdc42

Please sign in to comment.