Package org.wildfly.extension.undertow.security

Source Code of org.wildfly.extension.undertow.security.JbossAuthorizationManager

/*
* JBoss, Home of Professional Open Source.
* Copyright 2014, Red Hat Middleware LLC, 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.wildfly.extension.undertow.security;

import io.undertow.security.idm.Account;
import io.undertow.server.HttpServerExchange;
import io.undertow.servlet.api.AuthorizationManager;
import io.undertow.servlet.api.Deployment;
import io.undertow.servlet.api.SecurityRoleRef;
import io.undertow.servlet.api.ServletInfo;
import io.undertow.servlet.api.SingleConstraintMatch;
import io.undertow.servlet.api.TransportGuaranteeType;
import io.undertow.servlet.handlers.ServletRequestContext;
import org.jboss.as.core.security.SimplePrincipal;
import org.jboss.security.SecurityContext;
import org.jboss.security.authorization.ResourceKeys;
import org.jboss.security.javaee.AbstractWebAuthorizationHelper;
import org.jboss.security.javaee.SecurityHelperFactory;
import org.wildfly.extension.undertow.logging.UndertowLogger;

import javax.security.auth.Subject;
import javax.security.jacc.PolicyContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
* @author Stuart Douglas
*/
public class JbossAuthorizationManager implements AuthorizationManager {

    private final AuthorizationManager delegate;

    public JbossAuthorizationManager(AuthorizationManager delegate) {
        this.delegate = delegate;
    }

    @Override
    public boolean isUserInRole(String role, Account account, ServletInfo servletInfo, HttpServletRequest request, Deployment deployment) {
        boolean authzDecision = true;
        boolean baseDecision = delegate.isUserInRole(role, account, servletInfo, request, deployment);
        // if the RealmBase check has passed, then we can go to authz framework
        if (baseDecision) {
            String servletName = servletInfo.getName();
            String roleName = role;
            List<SecurityRoleRef> roleRefs = servletInfo.getSecurityRoleRefs();
            if (roleRefs != null) {
                for (SecurityRoleRef ref : roleRefs) {
                    if (ref.getLinkedRole().equals(role)) {
                        roleName = ref.getRole();
                        break;
                    }
                }
            }

            SecurityContext sc = SecurityActions.getSecurityContext();
            AbstractWebAuthorizationHelper helper = null;
            try {
                helper = SecurityHelperFactory.getWebAuthorizationHelper(sc);
            } catch (Exception e) {
                UndertowLogger.ROOT_LOGGER.noAuthorizationHelper(e);
                return false;

            }
            Subject callerSubject = sc.getUtil().getSubject();
            //if (callerSubject == null) {
            //    // During hasResourcePermission check, Catalina calls hasRole. But we have not established
            //    // a subject yet in the security context. So we will get the subject from the cached principal
            //    callerSubject = getSubjectFromRequestPrincipal(principal);
            //}

            authzDecision = helper.hasRole(roleName, account.getPrincipal(), servletName, getPrincipalRoles(account),
                    PolicyContext.getContextID(), callerSubject, new ArrayList<String>(account.getRoles()));
        }
        boolean finalDecision = baseDecision && authzDecision;
        UndertowLogger.ROOT_LOGGER.tracef("hasRole:RealmBase says: %s ::Authz framework says: %s :final= %s", baseDecision, authzDecision, finalDecision);
        //TODO: do we need audit for this?
        /*
        if (finalDecision) {
            if (!disableAudit) {
                Map<String, Object> entries = new HashMap<String, Object>();
                entries.put("Step", "hasRole");
                successAudit(principal, entries);
            }
        } else {
            if (!disableAudit) {
                Map<String, Object> entries = new HashMap<String, Object>();
                entries.put("Step", "hasRole");
                failureAudit(principal, entries);
            }
        }
        */

        return finalDecision;
    }

    private Set<Principal> getPrincipalRoles(Account account) {
        final Set<Principal> roles = new HashSet<>();
        for (String role : account.getRoles()) {
            roles.add(new SimplePrincipal(role));
        }
        return roles;
    }

    @Override
    public boolean canAccessResource(List<SingleConstraintMatch> mappedConstraints, Account account, ServletInfo servletInfo, HttpServletRequest request, Deployment deployment) {
        ServletRequestContext src = ServletRequestContext.current();
        boolean baseDecision = delegate.canAccessResource(mappedConstraints, account, servletInfo, request, deployment);
        boolean authzDecision = false;
        // if the RealmBase check has passed, then we can go to authz framework
        if (baseDecision) {
            SecurityContext sc = SecurityActions.getSecurityContext();
            Subject caller = sc.getUtil().getSubject();
            //if (caller == null) {
            //    caller = getSubjectFromRequestPrincipal(request.getPrincipal());
            //}
            Map<String, Object> contextMap = new HashMap<String, Object>();
            contextMap.put(ResourceKeys.RESOURCE_PERM_CHECK, Boolean.TRUE);
            contextMap.put("securityConstraints", mappedConstraints); //TODO? What should this be?

            AbstractWebAuthorizationHelper helper = null;
            try {
                helper = SecurityHelperFactory.getWebAuthorizationHelper(sc);
            } catch (Exception e) {
                UndertowLogger.ROOT_LOGGER.noAuthorizationHelper(e);
                return false;
            }

            ArrayList<String> roles = new ArrayList<String>();
            if(account != null) {
                roles.addAll(account.getRoles());
            }
            authzDecision = helper.checkResourcePermission(contextMap, request, src.getServletResponse(), caller, PolicyContext.getContextID(),
                    requestURI(src.getExchange()), roles);
        }
        boolean finalDecision = baseDecision && authzDecision && hasUserDataPermission(request, src.getOriginalResponse(), account, mappedConstraints);

        UndertowLogger.ROOT_LOGGER.tracef("hasResourcePermission:RealmBase says: %s ::Authz framework says: %s :final= %s", baseDecision, authzDecision, finalDecision);
        //TODO: audit?

        return finalDecision;

    }


    public boolean hasUserDataPermission(HttpServletRequest request, HttpServletResponse response, Account account, List<SingleConstraintMatch> constraints) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("securityConstraints", constraints);
        map.put(ResourceKeys.USERDATA_PERM_CHECK, Boolean.TRUE);

        SecurityContext sc = SecurityActions.getSecurityContext();
        AbstractWebAuthorizationHelper helper = null;
        try {
            helper = SecurityHelperFactory.getWebAuthorizationHelper(sc);
        } catch (Exception e) {
            UndertowLogger.ROOT_LOGGER.noAuthorizationHelper(e);
            return false;
        }

        Subject callerSubject = sc.getUtil().getSubject();
        // JBAS-6419:CallerSubject has no bearing on the user data permission check
        if (callerSubject == null) {
            callerSubject = new Subject();
        }

        ArrayList<String> roles = new ArrayList<String>();
        if(account != null) {
            roles.addAll(account.getRoles());
        }
        boolean ok = helper.hasUserDataPermission(map, request, response, PolicyContext.getContextID(), callerSubject,
                roles);

        //If the status of the response has already been changed (it is different from the default Response.SC_OK) we should not attempt to change it.
        if (!ok && response.getStatus() == HttpServletResponse.SC_OK) {
            try {
                response.sendError(HttpServletResponse.SC_FORBIDDEN);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return ok;
    }

    @Override
    public TransportGuaranteeType transportGuarantee(TransportGuaranteeType currentConnectionGuarantee, TransportGuaranteeType configuredRequiredGuarantee, HttpServletRequest request) {
        return delegate.transportGuarantee(currentConnectionGuarantee, configuredRequiredGuarantee, request);
    }


    /**
     * Get the canonical request URI from the request mapping data requestPath
     *
     * @param request
     * @return the request URI path
     */
    protected String requestURI(HttpServerExchange request) {
        String uri = request.getRelativePath();
        if (uri == null || uri.equals("/")) {
            uri = "";
        }
        return uri;
    }

}
TOP

Related Classes of org.wildfly.extension.undertow.security.JbossAuthorizationManager

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.