org.apache.qpid.server.management.plugin.HttpManagementUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.qpid.server.management.plugin.HttpManagementUtil.java

Source

/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.qpid.server.management.plugin;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.security.Principal;
import java.security.PrivilegedAction;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.zip.GZIPOutputStream;

import javax.security.auth.Subject;
import javax.security.auth.x500.X500Principal;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.binary.Base64;

import org.apache.qpid.server.management.plugin.servlet.ServletConnectionPrincipal;
import org.apache.qpid.server.management.plugin.session.LoginLogoutReporter;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.SubjectCreator;
import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus;
import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
import org.apache.qpid.server.security.auth.UsernamePrincipal;
import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager;
import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManager;
import org.apache.qpid.transport.network.security.ssl.SSLUtil;

public class HttpManagementUtil {

    /**
     * Servlet context attribute holding a reference to a broker instance
     */
    public static final String ATTR_BROKER = "Qpid.broker";

    /**
     * Servlet context attribute holding a reference to plugin configuration
     */
    public static final String ATTR_MANAGEMENT_CONFIGURATION = "Qpid.managementConfiguration";

    /**
     * Default management entry URL
     */
    public static final String ENTRY_POINT_PATH = "/management";

    private static final String ATTR_LOGIN_LOGOUT_REPORTER = "Qpid.loginLogoutReporter";
    private static final String ATTR_SUBJECT = "Qpid.subject";
    private static final String ATTR_LOG_ACTOR = "Qpid.logActor";

    private static final String ACCEPT_ENCODING_HEADER = "Accept-Encoding";
    private static final String CONTENT_ENCODING_HEADER = "Content-Encoding";
    private static final String GZIP_CONTENT_ENCODING = "gzip";

    public static Broker<?> getBroker(ServletContext servletContext) {
        return (Broker<?>) servletContext.getAttribute(ATTR_BROKER);
    }

    public static HttpManagementConfiguration getManagementConfiguration(ServletContext servletContext) {
        return (HttpManagementConfiguration) servletContext.getAttribute(ATTR_MANAGEMENT_CONFIGURATION);
    }

    public static SocketAddress getSocketAddress(HttpServletRequest request) {
        return InetSocketAddress.createUnresolved(request.getServerName(), request.getServerPort());
    }

    public static Subject getAuthorisedSubject(HttpSession session) {
        return (Subject) session.getAttribute(ATTR_SUBJECT);
    }

    public static void checkRequestAuthenticatedAndAccessAuthorized(HttpServletRequest request, Broker broker,
            HttpManagementConfiguration managementConfig) {
        HttpSession session = request.getSession();
        Subject subject = getAuthorisedSubject(session);
        if (subject == null) {
            subject = tryToAuthenticate(request, managementConfig);
            if (subject == null) {
                throw new SecurityException("Only authenticated users can access the management interface");
            }

            Subject original = subject;
            subject = new Subject(false, original.getPrincipals(), original.getPublicCredentials(),
                    original.getPrivateCredentials());
            subject.getPrincipals().add(new ServletConnectionPrincipal(request));
            subject.setReadOnly();

            assertManagementAccess(broker.getSecurityManager(), subject);

            saveAuthorisedSubject(session, subject);

        }
    }

    public static void assertManagementAccess(final SecurityManager securityManager, Subject subject) {
        Subject.doAs(subject, new PrivilegedAction<Void>() {
            @Override
            public Void run() {
                securityManager.accessManagement();
                return null;
            }
        });
    }

    public static void saveAuthorisedSubject(HttpSession session, Subject subject) {
        session.setAttribute(ATTR_SUBJECT, subject);

        // Cause the user logon to be logged.
        session.setAttribute(ATTR_LOGIN_LOGOUT_REPORTER,
                new LoginLogoutReporter(subject, getBroker(session.getServletContext())));
    }

    public static Subject tryToAuthenticate(HttpServletRequest request,
            HttpManagementConfiguration managementConfig) {
        Subject subject = null;
        SocketAddress localAddress = getSocketAddress(request);
        final AuthenticationProvider authenticationProvider = managementConfig
                .getAuthenticationProvider(localAddress);
        SubjectCreator subjectCreator = authenticationProvider.getSubjectCreator(request.isSecure());
        String remoteUser = request.getRemoteUser();

        if (remoteUser != null || authenticationProvider instanceof AnonymousAuthenticationManager) {
            subject = authenticateUser(subjectCreator, remoteUser, null);
        } else if (authenticationProvider instanceof ExternalAuthenticationManager && Collections
                .list(request.getAttributeNames()).contains("javax.servlet.request.X509Certificate")) {
            Principal principal = null;
            X509Certificate[] certificates = (X509Certificate[]) request
                    .getAttribute("javax.servlet.request.X509Certificate");
            if (certificates != null && certificates.length != 0) {
                principal = certificates[0].getSubjectX500Principal();

                if (!Boolean.valueOf(String.valueOf(authenticationProvider
                        .getAttribute(ExternalAuthenticationManager.ATTRIBUTE_USE_FULL_DN)))) {
                    String username;
                    String dn = ((X500Principal) principal).getName(X500Principal.RFC2253);

                    username = SSLUtil.getIdFromSubjectDN(dn);
                    principal = new UsernamePrincipal(username);
                }

                subject = subjectCreator.createSubjectWithGroups(new AuthenticatedPrincipal(principal));
            }
        } else {
            String header = request.getHeader("Authorization");
            if (header != null) {
                String[] tokens = header.split("\\s");
                if (tokens.length >= 2 && "BASIC".equalsIgnoreCase(tokens[0])) {
                    boolean isBasicAuthSupported = false;
                    if (request.isSecure()) {
                        isBasicAuthSupported = managementConfig.isHttpsBasicAuthenticationEnabled();
                    } else {
                        isBasicAuthSupported = managementConfig.isHttpBasicAuthenticationEnabled();
                    }
                    if (isBasicAuthSupported) {
                        String base64UsernameAndPassword = tokens[1];
                        String[] credentials = (new String(
                                Base64.decodeBase64(base64UsernameAndPassword.getBytes()))).split(":", 2);
                        if (credentials.length == 2) {
                            subject = authenticateUser(subjectCreator, credentials[0], credentials[1]);
                        }
                    }
                }
            }
        }
        return subject;
    }

    private static Subject authenticateUser(SubjectCreator subjectCreator, String username, String password) {
        SubjectAuthenticationResult authResult = subjectCreator.authenticate(username, password);
        if (authResult.getStatus() == AuthenticationStatus.SUCCESS) {
            return authResult.getSubject();
        }
        return null;
    }

    public static Writer getOutputWriter(final HttpServletRequest request, final HttpServletResponse response)
            throws IOException {
        return getOutputWriter(request, response, getManagementConfiguration(request.getServletContext()));
    }

    public static Writer getOutputWriter(final HttpServletRequest request, final HttpServletResponse response,
            HttpManagementConfiguration managementConfiguration) throws IOException {
        Writer writer;
        writer = new BufferedWriter(
                new OutputStreamWriter(getOutputStream(request, response, managementConfiguration)));

        return writer;
    }

    public static OutputStream getOutputStream(final HttpServletRequest request, final HttpServletResponse response)
            throws IOException {
        return getOutputStream(request, response, getManagementConfiguration(request.getServletContext()));
    }

    public static OutputStream getOutputStream(final HttpServletRequest request, final HttpServletResponse response,
            HttpManagementConfiguration managementConfiguration) throws IOException {
        OutputStream outputStream;
        if (managementConfiguration.isCompressResponses()
                && Collections.list(request.getHeaderNames()).contains(ACCEPT_ENCODING_HEADER)
                && request.getHeader(ACCEPT_ENCODING_HEADER).contains(GZIP_CONTENT_ENCODING)) {
            outputStream = new GZIPOutputStream(response.getOutputStream());
            response.setHeader(CONTENT_ENCODING_HEADER, GZIP_CONTENT_ENCODING);
        } else {
            outputStream = response.getOutputStream();
        }
        return outputStream;
    }
}