diff --git a/gravitee-management-api-security/src/main/java/io/gravitee/management/security/config/BasicSecurityConfigurerAdapter.java b/gravitee-management-api-security/src/main/java/io/gravitee/management/security/config/BasicSecurityConfigurerAdapter.java index 25a380b87f..7e0b852aac 100644 --- a/gravitee-management-api-security/src/main/java/io/gravitee/management/security/config/BasicSecurityConfigurerAdapter.java +++ b/gravitee-management-api-security/src/main/java/io/gravitee/management/security/config/BasicSecurityConfigurerAdapter.java @@ -106,7 +106,6 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception { if (!found) { LOGGER.error("No authentication provider found for type: {}", provider.type()); - throw new IllegalStateException("No authentication provider found for type: " + provider.type()); } } } diff --git a/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/upgrade/IdentityProviderUpgrader.java b/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/upgrade/IdentityProviderUpgrader.java new file mode 100644 index 0000000000..d7f3b01036 --- /dev/null +++ b/gravitee-management-api-service/src/main/java/io/gravitee/management/service/impl/upgrade/IdentityProviderUpgrader.java @@ -0,0 +1,250 @@ +/** + * Copyright (C) 2015 The Gravitee team (http://gravitee.io) + * + * 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 io.gravitee.management.service.impl.upgrade; + +import io.gravitee.management.model.GroupEntity; +import io.gravitee.management.model.configuration.identity.*; +import io.gravitee.management.service.GroupService; +import io.gravitee.management.service.Upgrader; +import io.gravitee.management.service.configuration.identity.IdentityProviderService; +import io.gravitee.management.service.impl.configuration.identity.IdentityProviderNotFoundException; +import io.gravitee.repository.management.model.RoleScope; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.Ordered; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.stream.Collectors; + +@Component +public class IdentityProviderUpgrader implements Upgrader, Ordered { + private final Logger logger = LoggerFactory.getLogger(IdentityProviderUpgrader.class); + + private List notStorableIDPs = Arrays.asList("gravitee", "ldap", "memory"); + private List idpTypeNames = Arrays.stream(IdentityProviderType.values()).map(Enum::name).collect(Collectors.toList()); + private static final String description = "Configuration provided by the system. Every modifications will be overridden at the next startup."; + + @Autowired + private ConfigurableEnvironment environment; + + @Autowired + private GroupService groupService; + + @Autowired + private IdentityProviderService identityProviderService; + + @Override + public boolean upgrade() { + boolean found = true; + int idx = 0; + + while (found) { + String type = environment.getProperty("security.providers[" + idx + "].type"); + found = (type != null); + if (found && !notStorableIDPs.contains(type)) { + if (idpTypeNames.contains(type.toUpperCase())) { + logger.info("Upsert identity provider config [{}]", type); + String id = environment.getProperty("security.providers[" + idx + "].id"); + if (id == null) { + id = type; + } + try { + identityProviderService.findById(id); + } catch (IdentityProviderNotFoundException e) { + id = createIdp(id, IdentityProviderType.valueOf(type.toUpperCase()), idx); + } + // always update + updateIdp(id, idx); + } else { + logger.info("Unknown identity provider [{}]", type); + } + } + idx++; + } + return true; + } + + private String createIdp(String id, IdentityProviderType type, int providerIndex) { + NewIdentityProviderEntity idp = new NewIdentityProviderEntity(); + idp.setName(id); + idp.setType(type); + idp.setDescription(description); + idp.setEnabled(true); + idp.setConfiguration(getConfiguration(providerIndex)); + + Map userProfileMapping = getUserProfileMapping(providerIndex); + if (!userProfileMapping.isEmpty()) { + idp.setUserProfileMapping(userProfileMapping); + } + + return identityProviderService.create(idp).getId(); + } + + private void updateIdp(String id,int providerIndex) { + UpdateIdentityProviderEntity idp = new UpdateIdentityProviderEntity(); + idp.setName(id); + idp.setDescription(description); + idp.setConfiguration(getConfiguration(providerIndex)); + idp.setEnabled(true); + + Map userProfileMapping = getUserProfileMapping(providerIndex); + if (!userProfileMapping.isEmpty()) { + idp.setUserProfileMapping(userProfileMapping); + } + + List groupMappings = getGroupMappings(providerIndex); + if (!groupMappings.isEmpty()) { + idp.setGroupMappings(groupMappings); + } + + List roleMappings = getRoleMappings(providerIndex); + if (!roleMappings.isEmpty()) { + idp.setRoleMappings(roleMappings); + } + + identityProviderService.update(id, idp); + } + + private Map getConfiguration(int providerIndex) { + HashMap config = new HashMap<>(); + + String prefix = "security.providers[" + providerIndex + "]."; + putIfNotNull(config, prefix, "clientId"); + putIfNotNull(config, prefix, "clientSecret"); + putIfNotNull(config, prefix, "color"); + putIfNotNull(config, prefix, "tokenEndpoint"); + putIfNotNull(config, prefix, "authorizeEndpoint"); + putIfNotNull(config, prefix, "tokenIntrospectionEndpoint"); + putIfNotNull(config, prefix, "userInfoEndpoint"); + putIfNotNull(config, prefix, "userLogoutEndpoint"); + putIfNotNull(config, prefix, "serverURL"); + putIfNotNull(config, prefix, "domain"); + + List scopes = getListOfString("security.providers[" + providerIndex + "].scopes"); + if (!scopes.isEmpty()) { + config.put("scopes", scopes); + } + + return config; + } + + private List getListOfString(String listName) { + boolean found = true; + int idx = 0; + ArrayList scopes = new ArrayList<>(); + + while (found) { + String scope = environment.getProperty(listName + "[" + idx + "]"); + found = (scope != null); + if (found) { + scopes.add(scope); + } + idx++; + } + return scopes; + } + + private Map getUserProfileMapping(int providerIndex) { + HashMap mapping = new HashMap<>(); + + String prefix = "security.providers[" + providerIndex + "].userMapping."; + putIfNotNull(mapping, prefix, "id"); + putIfNotNull(mapping, prefix, "email"); + putIfNotNull(mapping, prefix, "lastname"); + putIfNotNull(mapping, prefix, "firstname"); + putIfNotNull(mapping, prefix, "picture"); + + return mapping; + } + + private List getGroupMappings(int providerIndex) { + boolean found = true; + int idx = 0; + List mapping = new ArrayList<>(); + + while (found) { + String condition = environment.getProperty("security.providers[" + providerIndex + "].groupMapping[" + idx + "].condition"); + found = (condition != null); + if (found) { + GroupMappingEntity groupMappingEntity = new GroupMappingEntity(); + groupMappingEntity.setCondition(condition); + List groupNames = getListOfString("security.providers[" + providerIndex + "].groupMapping[" + idx + "].groups"); + if (!groupNames.isEmpty()) { + List groups = new ArrayList<>(); + groupNames.forEach( groupName -> { + List groupsFound = groupService.findByName(groupName); + + if (groupsFound != null && groupsFound.size() == 1) { + groups.add(groupsFound.get(0).getId()); + } + }); + + groupMappingEntity.setGroups(groups); + } + mapping.add(groupMappingEntity); + } + idx++; + } + + + return mapping; + } + + private List getRoleMappings(int providerIndex) { + boolean found = true; + int idx = 0; + List mapping = new ArrayList<>(); + + while (found) { + String condition = environment.getProperty("security.providers[" + providerIndex + "].roleMapping[" + idx + "].condition"); + found = (condition != null); + if (found) { + RoleMappingEntity roleMappingEntity = new RoleMappingEntity(); + roleMappingEntity.setCondition(condition); + List roles = getListOfString("security.providers[" + providerIndex + "].roleMapping[" + idx + "].roles"); + if (!roles.isEmpty()) { + roles.forEach( role -> { + if (role.startsWith(RoleScope.MANAGEMENT.name())) { + roleMappingEntity.setManagement(role.replace(RoleScope.MANAGEMENT.name() + ":", "")); + } else if (role.startsWith(RoleScope.PORTAL.name())) { + roleMappingEntity.setPortal(role.replace(RoleScope.PORTAL.name() + ":", "")); + } + }); + } + mapping.add(roleMappingEntity); + } + idx++; + } + + + return mapping; + } + + private void putIfNotNull(Map config, String prefix, String key) { + String value = environment.getProperty(prefix + key); + if (value != null) { + config.put(key, value); + } + } + + @Override + public int getOrder() { + return 350; + } +}