diff --git a/ssh-key-provider/src/main/java/de/ccc/hamburg/keycloak/ssh_key/AdminUiPage.java b/ssh-key-provider/src/main/java/de/ccc/hamburg/keycloak/ssh_key/AdminUiPage.java index ed070f7..b9dc527 100644 --- a/ssh-key-provider/src/main/java/de/ccc/hamburg/keycloak/ssh_key/AdminUiPage.java +++ b/ssh-key-provider/src/main/java/de/ccc/hamburg/keycloak/ssh_key/AdminUiPage.java @@ -12,10 +12,11 @@ import org.keycloak.services.ui.extend.UiPageProviderFactory; import java.util.List; /** - * Implements UiPageProvider to show a config page in the admin ui + * Implements UiPageProvider to show a config page in the admin */ @AutoService(UiPageProviderFactory.class) public class AdminUiPage implements UiPageProvider, UiPageProviderFactory { + public static final String PROVIDER_ID = "🪪 Attribute Endpoints 🚀"; @Override public void init(Config.Scope config) { @@ -31,7 +32,7 @@ public class AdminUiPage implements UiPageProvider, UiPageProviderFactory(ssh-dss AAAAB3NzaC1kc3|ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNT|ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzOD|ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1Mj|sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb2|ssh-ed25519 AAAAC3NzaC1lZDI1NTE5|sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29t|ssh-rsa AAAAB3NzaC1yc2)[0-9A-Za-z+/]+[=]{0,3})(\\s.*)?$"); - public SSHKeyResourceProvider(KeycloakSession keycloakSession) { this.session = keycloakSession; } @@ -58,68 +58,85 @@ public class SSHKeyResourceProvider implements RealmResourceProvider { KeycloakContext context = session.getContext(); RealmModel realm = context.getRealm(); - // TODO: check if slug exists + List componentList = realm.getComponentsStream() + .filter(c -> c.getProviderId().equals(AdminUiPage.PROVIDER_ID)) + .filter(c -> c.getConfig().getFirst("slug").equals(slug)) + .toList(); - // TODO: get config defined by AdminUiPage - - // get config for slug and check if it is valid - RoleModel authRole; - RoleModel matchRole; - String attributeGroup; - String attributeRegex; - try { - authRole = realm.getRole("dooris-export"); - matchRole = realm.getRole("dooris-access"); - attributeGroup = "dooris"; - attributeRegex = "placeholder_config_attributeRegex"; - // TODO: check if AttributeGroup exists - } catch (Exception e) { - System.err.println(e); - return Response.status(500, e.getMessage()).build(); + if (componentList.isEmpty()) { + throw new NotFoundException("Endpoint not found."); } - Auth auth; + Auth auth = SSHKeyResourceProvider.getAuth(session); + + ComponentModel component = componentList.get(0); + + String configAuthRole = component.getConfig().getFirst("auth-role"); + RoleModel authRole = realm.getRole(configAuthRole); + if (authRole == null) { + throw new ServerErrorException("Endpoint Configuration Error - auth-role does not exist.", 500); + } + + String configMatchRole = component.getConfig().getFirst("match-role"); + RoleModel matchRole = realm.getRole(configMatchRole); + if (matchRole == null) { + throw new ServerErrorException("Endpoint Configuration Error - match-role does not exist.", 500); + } + + UserProfileProvider profileProvider = session.getProvider(UserProfileProvider.class); + UPConfig upconfig = profileProvider.getConfiguration(); + String configAttributeGroup = component.getConfig().getFirst("attribute-group"); + if (!upconfig.getGroups().stream().anyMatch(g -> g.getName().equals(configAttributeGroup))) { + throw new ServerErrorException("Endpoint Configuration Error - attribute-group does not exist.", 500); + } + + String configAttributeRegex = component.getConfig().getFirst("attribute-regex"); + Pattern attributeRegex; try { - auth = SSHKeyResourceProvider.getAuth(session); + attributeRegex = Pattern.compile(configAttributeRegex); } catch (Exception e) { - System.err.println(e); - return Response.status(401, e.getMessage()).build(); + throw new ServerErrorException( + "Endpoint Configuration Error - attribute-regex is not a valid regex pattern.", 500); } try { UserModel user = auth.getUser(); if (!user.hasRole(authRole)) { - throw new UnauthorizedException("User does not have requires auth role."); + throw new UnauthorizedException("User does not have required auth role."); } } catch (Exception e) { System.err.println(e); return Response.status(403, e.getMessage()).build(); } - UserProvider userProvider = session.users(); - UserProfileProvider profileProvider = session.getProvider(UserProfileProvider.class); - UPConfig upconfig = profileProvider.getConfiguration(); + if (componentList.size() > 1) { + throw new NotFoundException( + "Endpoint Configuration Error - Multiple configurations exist for this endpoint."); + } + List attributeNames = upconfig.getAttributes() .stream() - .filter(a -> a.getGroup() != null && a.getGroup().equals(attributeGroup)) + .filter(a -> a.getGroup() != null && a.getGroup().equals(configAttributeGroup)) .map(a -> a.getName()) .toList(); + UserProvider userProvider = session.users(); Stream users = userProvider.getRoleMembersStream(realm, matchRole); List attribute_list = users .map(user -> { - return attributeNames - .stream() - .map(attributeName -> user.getAttributeStream(attributeName).findFirst()) - .filter(attribute -> attribute.isPresent()) - .map(attribute -> attribute.get()) + Stream attributeStream = attributeNames.stream() + .map(attributeName -> user.getAttributeStream(attributeName).toList()) + .flatMap(Collection::stream); + + return attributeStream + .filter(attribute -> !attribute.isEmpty()) .toList(); }) .flatMap(List::stream) - .map(key -> { - final Matcher matcher = SSH_PUBLIC_KEY.matcher(key); - return matcher.find() ? matcher.group("key") : null; + .map(attribute -> { + final Matcher matcher = attributeRegex.matcher(attribute); + return matcher.find() ? attribute : null; }) .filter(Objects::nonNull) .toList();