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

cn.home1.cloud.config.server.security.GitFileConfigUserDetailsService Maven / Gradle / Ivy

The newest version!
package cn.home1.cloud.config.server.security;

import static cn.home1.cloud.config.server.util.Consts.DOT_ENV;
import static cn.home1.cloud.config.server.util.Consts.PRIVILEGE_ENV_PROFILE_;
import static cn.home1.cloud.config.server.util.Consts.PRIVILEGE_ENV_PROFILE_WILDCARD;
import static cn.home1.cloud.config.server.util.EnvironmentUtils.getConfigPassword;
import static java.util.stream.Collectors.toList;

import com.google.common.collect.ImmutableList;

import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import org.springframework.cloud.config.environment.Environment;
import org.springframework.cloud.config.server.environment.EnvironmentController;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import java.util.Collection;
import java.util.Iterator;
import java.util.Optional;
import java.util.regex.Pattern;

/**
 * config-server-client use the password configured in GIT. the user name must be the app name.
 */
@Slf4j
public class GitFileConfigUserDetailsService implements UserDetailsService {

    private static final Pattern PATTERN_AT = Pattern.compile("@");

    private static final Collection ANONYMOUS_AUTHORITY = ImmutableList.of();

    private static final Collection HOOK_AUTHORITY =
        ImmutableList.of(new SimpleGrantedAuthority("ROLE_" + Role.HOOK.toString()));

    private static final GrantedAuthority USER_AUTHORITY = new SimpleGrantedAuthority( //
        "ROLE_" + Role.USER.toString());

    @Setter
    private ConfigSecurity configSecurity;

    @Setter
    private String defaultLabel;

    @Setter
    private EnvironmentController environmentController;

    @Setter
    private PrivilegedUserProperties privilegedUserProperties;

    @Override
    public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
        if (username == null) {
            return new User("anonymous", "", ANONYMOUS_AUTHORITY);
        }

        if (username.equals(this.privilegedUserProperties.getAdminName())) {
            final Collection adminAuthority = this.privilegedUserProperties.getAdminRoles() //
                .stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).collect(toList());
            return new User(username, this.privilegedUserProperties.getAdminPassword(), adminAuthority);
        }

        if (username.equals(this.privilegedUserProperties.getHookName())) {
            return new User(username, this.privilegedUserProperties.getHookPassword(), HOOK_AUTHORITY);
        }

        // username is `spring.application.name` or `spring.application.name@{profile.env}`
        final String application;
        final String profileToAuth;
        final Optional privilege; // privilege of environment profile: can be specific one, none or anyone
        if (username.contains("@") && username.endsWith(DOT_ENV)) {
            final Iterator parts = PATTERN_AT.splitAsStream(username).iterator();
            application = parts.next();
            profileToAuth = parts.next();
            privilege = Optional.of(new SimpleGrantedAuthority(PRIVILEGE_ENV_PROFILE_ + profileToAuth));
        } else if (username.endsWith("@default")) {
            final Iterator parts = PATTERN_AT.splitAsStream(username).iterator();
            application = parts.next();
            profileToAuth = parts.next();
            privilege = Optional.empty();
        } else {
            application = username;
            profileToAuth = "default";
            privilege = Optional.of(new SimpleGrantedAuthority(PRIVILEGE_ENV_PROFILE_WILDCARD));
        }
        final Collection authorities = privilege.isPresent() ? //
            ImmutableList.of(USER_AUTHORITY, privilege.get()) : ImmutableList.of(USER_AUTHORITY);


        final String expectedPassword = this.findExpectedPassword(application, profileToAuth);
        if (expectedPassword == null) {
            throw new BadCredentialsException(
                "can not find 'spring.cloud.config.password' application: " + application + ", profile: " + profileToAuth);
        }
        final String rawExpectedPassword = this.configSecurity.decryptProperty(expectedPassword);

        return new User(application, rawExpectedPassword, authorities);
    }

    String findExpectedPassword(final String application, final String profile) {
        final String result;

        if (this.defaultLabel != null) {
            final String found = this.findExpectedPassword(application, profile, this.defaultLabel);
            result = found != null ? found : this.findExpectedPassword(application, profile, null);
        } else {
            result = this.findExpectedPassword(application, profile, null);
        }

        return result;
    }

    String findExpectedPassword(final String application, final String profile, final String label) {
        final Environment environment;

        try {
            environment = this.environmentController.labelled(application, profile, label);
        } catch (final Exception exception) {
            log.warn("error on loadUserByUsername from git configuration file, username: {}", //
                application, exception);
            throw exception;
        }

        if (environment == null) {
            throw new UsernameNotFoundException("can not find the project by username: " + application);
        }

        return getConfigPassword(environment);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy