All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.vincentrussell.nexus3.x509.dn.security.plugin.X509DnAuthenticatingRealm Maven / Gradle / Ivy

package com.github.vincentrussell.nexus3.x509.dn.security.plugin;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.x509.X509AuthenticationInfo;
import org.apache.shiro.authc.x509.X509AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.x509.AbstractX509Realm;
import org.apache.shiro.subject.PrincipalCollection;
import org.eclipse.sisu.Description;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonatype.nexus.security.anonymous.AnonymousPrincipalCollection;
import org.yaml.snakeyaml.Yaml;

import javax.inject.Named;
import javax.inject.Singleton;
import javax.security.auth.x500.X500Principal;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.*;

/**
 * The Class X509DnAuthenticatingRealm.
 */
@Singleton
@Named(X509DnAuthenticatingRealm.NAME)
@Description("X509-Dn Authenticating Realm")
public class X509DnAuthenticatingRealm extends AbstractX509Realm {

    private static final Logger LOGGER = LoggerFactory.getLogger(X509DnAuthenticatingRealm.class);

    public static final X509Certificate DEFAULT_ANONYMOUS_CERT = getDefaultAnonymousCert();

    private static X509Certificate getDefaultAnonymousCert() {
        try (InputStream inputStream = X509DnAuthenticatingRealm.class.getResourceAsStream("/certs/anonymous/anonymous.cer")) {
            final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
            final X509Certificate certificate = (X509Certificate) certFactory.generateCertificate(inputStream);
            return certificate;
        } catch (Throwable e) {
            LOGGER.error(e.getMessage(), e);
            throw new RuntimeException(e.getMessage(), e);
        }
    }


    protected static final String NAME = "X509DnAuthenticatingRealm";
    protected static final String CONFIG_FILE = X509DnAuthenticatingRealm.class.getSimpleName() + ".config.file";
    public static final SimpleAuthorizationInfo ANONYMOUS_AUTHORIZATION_INFO = new SimpleAuthorizationInfo(Sets.newHashSet("nx-anonymous"));
    private final Yaml yaml = new Yaml();
    private final Multimap roleToDnMultimap = HashMultimap.create();
    private final Multimap dnToRoleMultimap = HashMultimap.create();

    public X509DnAuthenticatingRealm() {
            try (FileInputStream fileInputStream = new FileInputStream(System.getProperty(CONFIG_FILE))) {
            Map> compiledYaml = yaml.load(fileInputStream);
            generateMultiMaps(compiledYaml);
        } catch (Throwable e) {
            throw new IllegalStateException(e);
        }
        setAuthenticationTokenClass(X509AuthenticationToken.class);
        setName(NAME);
        setAuthenticationCachingEnabled(true);
    }

    private void generateMultiMaps(Map> compiledYaml) {
        for (Map.Entry>  entry : compiledYaml.entrySet()) {
            String role = entry.getKey();
            for (String dn : entry.getValue()) {
                String normalizedDn = normalizeDn(dn);
                dnToRoleMultimap.put(normalizedDn, role);
                roleToDnMultimap.put(normalizedDn, dn);
            }
        }
    }

    private String normalizeDn(String dn) {
        X500Principal x500Principal = new X500Principal(dn);
        return x500Principal.getName();
    }


    @Override
    protected X509AuthenticationInfo doGetX509AuthenticationInfo(X509AuthenticationToken x509AuthenticationToken) {
        final String dn = x509AuthenticationToken.getSubjectDN().getName();
        LOGGER.info("dn received: {}", dn);
        X509AuthenticationInfo x509AuthenticationInfo = new X509AuthenticationInfo(dn, x509AuthenticationToken.getSubjectDN(), NAME);
        x509AuthenticationInfo.setCredentials(dn);
        return x509AuthenticationInfo;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        if (AnonymousPrincipalCollection.class.isInstance(principals)) {
            return ANONYMOUS_AUTHORIZATION_INFO;
        }
        String normalizeDn = normalizeDn((String) principals.getPrimaryPrincipal());
        Set roles = new HashSet<>();
        Collection potentialRoles = dnToRoleMultimap.get(normalizeDn);

        if (potentialRoles == null || potentialRoles.size() == 0) {
            return ANONYMOUS_AUTHORIZATION_INFO;
        }

        roles.addAll(potentialRoles);
        return new SimpleAuthorizationInfo(roles);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy