Skip to content

Commit

Permalink
improve identity provider handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Ramon Spahr committed Jul 3, 2020
1 parent 59080f3 commit 209eac3
Show file tree
Hide file tree
Showing 23 changed files with 1,034 additions and 29 deletions.
3 changes: 2 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ indent_style = space
[*.{json, yaml, xml}]
indent_size = 2

[*.xml]
[*.{xml, java}]
indent_size = 4
continuation_indent_size = 8
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Create, Update, Delete IdentityProviderMappers
- Support for only updating changed IdentityProviders
- Support for managed IdentityProviders

### Changed

### Fixed
Expand Down
7 changes: 6 additions & 1 deletion docs/FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@
| Add required-actions | 1.0.0 | Add required-actions while creating or updating realms |
| Update required-actions | 1.0.0 | Update properties of existing required-actions while updating realms |
| Remove required-actions | 2.0.0 | Remove existing required-actions while updating realms |
| Update identity providers | 1.2.0 | Update properties of existing identity providers while updating realms |
| Add identity providers | 1.2.0 | Add identity providers while creating or updating realms |
| Update identity providers | 1.2.0 | Update identity providers while updating realms (improved with 2.0.0) |
| Remove identity providers | 2.0.0 | Remove identity providers while updating realms |
| Add identity provider mappers | 2.0.0 | Add identityProviderMappers while updating realms |
| Update identity provider mappers | 2.0.0 | Update identityProviderMappers while updating realms |
| Remove identity provider mappers | 2.0.0 | Remove identityProviderMappers while updating realms |
| Add clientScopes | 2.0.0 | Add clientScopes (inclusive protocolMappers) while creating or updating realms |
| Update clientScopes | 2.0.0 | Update existing (inclusive protocolMappers) clientScopes while creating or updating realms |
| Remove clientScopes | 2.0.0 | Remove existing clientScopes while creating or updating realms |
20 changes: 11 additions & 9 deletions docs/MANAGED.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ For example if you define `groups` but set an empty array, keycloak will delete

## Supported full managed entities

| Type | Additional Information |
| -------------------- | -------------------------------------------------------------------------------- |
| Groups | - |
| Required Actions | You have to copy the default one to you import json. |
| Client Scopes | - |
| Scope Mappings | - |
| Components | You have to copy the default components to you import json. |
| Sub Components | You have to copy the default components to you import json. |
| Authentication Flows | You have to copy the default components to you import json, expect bulitin flows |
| Type | Additional Information | Property Name |
| --------------------------- | -------------------------------------------------------------------------------- | --------------------------- |
| Groups | - | `group` |
| Required Actions | You have to copy the default one to you import json. | `required-action` |
| Client Scopes | - | `client-scope` |
| Scope Mappings | - | `scope-mapping` |
| Components | You have to copy the default components to you import json. | `component` |
| Sub Components | You have to copy the default components to you import json. | `sub-component` |
| Authentication Flows | You have to copy the default components to you import json, expect bulitin flows | `authentication-flow` |
| Identity Providers | - | `identity-provider` |
| Identity Provider Mappers | - | `identity-provider-mapper` |

## Disable deletion of managed entities

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,18 +119,27 @@ public static class ImportManagedProperties {
@NotNull
private final ImportManagedPropertiesValues authenticationFlow;

@NotNull
private final ImportManagedPropertiesValues identityProvider;

@NotNull
private final ImportManagedPropertiesValues identityProviderMapper;

public ImportManagedProperties(
ImportManagedPropertiesValues requiredAction, ImportManagedPropertiesValues group,
ImportManagedPropertiesValues clientScope, ImportManagedPropertiesValues scopeMapping,
ImportManagedPropertiesValues component, ImportManagedPropertiesValues subComponent,
ImportManagedPropertiesValues authenticationFlow) {
ImportManagedPropertiesValues authenticationFlow, ImportManagedPropertiesValues identityProvider,
ImportManagedPropertiesValues identityProviderMapper) {
this.requiredAction = requiredAction;
this.group = group;
this.clientScope = clientScope;
this.scopeMapping = scopeMapping;
this.component = component;
this.subComponent = subComponent;
this.authenticationFlow = authenticationFlow;
this.identityProvider = identityProvider;
this.identityProviderMapper = identityProviderMapper;
}

public ImportManagedPropertiesValues getRequiredAction() {
Expand Down Expand Up @@ -161,6 +170,10 @@ public ImportManagedPropertiesValues getGroup() {
return group;
}

public ImportManagedPropertiesValues getIdentityProvider() { return identityProvider; }

public ImportManagedPropertiesValues getIdentityProviderMapper() { return identityProviderMapper; }

public enum ImportManagedPropertiesValues {
FULL,
NO_DELETE
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*-
* ---license-start
* keycloak-config-cli
* ---
* Copyright (C) 2017 - 2020 adorsys GmbH & Co. KG @ https://adorsys.de
* ---
* 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.
* ---license-end
*/

package de.adorsys.keycloak.config.repository;

import de.adorsys.keycloak.config.util.ResponseUtil;
import de.adorsys.keycloak.config.util.StreamUtil;
import org.keycloak.admin.client.resource.IdentityProvidersResource;
import org.keycloak.representations.idm.IdentityProviderMapperRepresentation;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class IdentityProviderMapperRepository {

private final RealmRepository realmRepository;

@Autowired
public IdentityProviderMapperRepository(RealmRepository realmRepository) {
this.realmRepository = realmRepository;
}

public Optional<IdentityProviderMapperRepresentation> tryToFindIdentityProviderMapper(String realm, String identityProviderAlias, String name) {
return loadIdentityProviderMapperByName(realm, identityProviderAlias, name);
}

public IdentityProviderMapperRepresentation getIdentityProviderMapperByName(String realm, String identityProviderAlias, String name) {
Optional<IdentityProviderMapperRepresentation> maybeIdentityProviderMapper = loadIdentityProviderMapperByName(realm, identityProviderAlias, name);

return maybeIdentityProviderMapper.orElse(null);
}

public List<IdentityProviderMapperRepresentation> getIdentityProviderMappers(String realm) {
List<IdentityProviderMapperRepresentation> mappers = new ArrayList<>();
IdentityProvidersResource identityProvidersResource = realmRepository.loadRealm(realm).identityProviders();
List<IdentityProviderRepresentation> identityProviders = identityProvidersResource.findAll();

for(IdentityProviderRepresentation identityProvider : identityProviders) {
mappers.addAll(identityProvidersResource.get(identityProvider.getAlias()).getMappers());
}
return mappers;
}

public void createIdentityProviderMapper(String realm, IdentityProviderMapperRepresentation identityProviderMapper) {
IdentityProvidersResource identityProvidersResource = realmRepository.loadRealm(realm).identityProviders();

Response response = identityProvidersResource.get(identityProviderMapper.getIdentityProviderAlias()).addMapper(identityProviderMapper);
ResponseUtil.throwOnError(response);
}

public void updateIdentityProviderMapper(String realm, IdentityProviderMapperRepresentation identityProviderMapperToUpdate) {
IdentityProvidersResource identityProvidersResource = realmRepository.loadRealm(realm).identityProviders();

identityProvidersResource.get(identityProviderMapperToUpdate.getIdentityProviderAlias()).update(identityProviderMapperToUpdate.getId(), identityProviderMapperToUpdate);
}

public void deleteIdentityProviderMapper(String realm, IdentityProviderMapperRepresentation identityProviderMapperToDelete) {
IdentityProvidersResource identityProvidersResource = realmRepository.loadRealm(realm).identityProviders();
String identityProviderAlias = identityProviderMapperToDelete.getIdentityProviderAlias();

identityProvidersResource.get(identityProviderAlias).delete(identityProviderMapperToDelete.getId());
}

private Optional<IdentityProviderMapperRepresentation> loadIdentityProviderMapperByName(String realm, String identityProviderAlias, String name) {
return StreamUtil.collectionAsStream(realmRepository.get(realm).getIdentityProviderMappers()).filter(m -> m.getName().equals(name) && m.getIdentityProviderAlias().equals(identityProviderAlias)).findFirst();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@

package de.adorsys.keycloak.config.repository;

import de.adorsys.keycloak.config.util.ResponseUtil;
import org.keycloak.admin.client.resource.IdentityProviderResource;
import org.keycloak.admin.client.resource.IdentityProvidersResource;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.Response;
import java.util.List;
import java.util.Optional;

@Service
Expand All @@ -35,17 +38,14 @@ public class IdentityProviderRepository {
private final RealmRepository realmRepository;

@Autowired
public IdentityProviderRepository(
RealmRepository realmRepository
) {
public IdentityProviderRepository(RealmRepository realmRepository) {
this.realmRepository = realmRepository;
}

public Optional<IdentityProviderRepresentation> tryToFindIdentityProvider(String realm, String name) {
public Optional<IdentityProviderRepresentation> tryToFindIdentityProvider(String realm, String alias) {
Optional<IdentityProviderRepresentation> maybeIdentityProvider;

IdentityProvidersResource identityProvidersResource = realmRepository.loadRealm(realm).identityProviders();
IdentityProviderResource identityProviderResource = identityProvidersResource.get(name);
IdentityProviderResource identityProviderResource = loadIdentityProviderByAlias(realm, alias);

try {
maybeIdentityProvider = Optional.of(identityProviderResource.toRepresentation());
Expand All @@ -56,9 +56,22 @@ public Optional<IdentityProviderRepresentation> tryToFindIdentityProvider(String
return maybeIdentityProvider;
}

public IdentityProviderRepresentation getIdentityProviderByAlias(String realm, String alias) {
IdentityProviderResource identityProviderResource = loadIdentityProviderByAlias(realm, alias);
if (identityProviderResource == null) {
return null;
}
return identityProviderResource.toRepresentation();
}

public List<IdentityProviderRepresentation> getIdentityProviders(String realm) {
return realmRepository.loadRealm(realm).identityProviders().findAll();
}

public void createIdentityProvider(String realm, IdentityProviderRepresentation identityProvider) {
IdentityProvidersResource identityProvidersResource = realmRepository.loadRealm(realm).identityProviders();
identityProvidersResource.create(identityProvider);
Response response = identityProvidersResource.create(identityProvider);
ResponseUtil.throwOnError(response);
}

public void updateIdentityProvider(String realm, IdentityProviderRepresentation identityProviderToUpdate) {
Expand All @@ -68,4 +81,17 @@ public void updateIdentityProvider(String realm, IdentityProviderRepresentation

identityProviderResource.update(identityProviderToUpdate);
}

public void deleteIdentityProvider(String realm, IdentityProviderRepresentation identityProviderToDelete) {
IdentityProviderResource identityProviderResource = realmRepository.loadRealm(realm)
.identityProviders()
.get(identityProviderToDelete.getInternalId());

identityProviderResource.remove();
}

private IdentityProviderResource loadIdentityProviderByAlias(String realm, String identityProviderAlias) {
return realmRepository.loadRealm(realm)
.identityProviders().get(identityProviderAlias);
}
}
Loading

0 comments on commit 209eac3

Please sign in to comment.