Compare commits
7 commits
05785661d7
...
324fe35f5a
| Author | SHA1 | Date | |
|---|---|---|---|
|
324fe35f5a |
|||
|
bd9e5a6f3e |
|||
|
964a593dbd |
|||
|
85bd0c6572 |
|||
|
5e791af057 |
|||
|
393284ebdc |
|||
|
ffa6c92c65 |
6 changed files with 45 additions and 5213 deletions
7
Makefile
Normal file
7
Makefile
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
verify:
|
||||
mvn -f attribute-endpoints-provider verify
|
||||
|
||||
clean:
|
||||
mvn -f attribute-endpoints-provider clean
|
||||
|
||||
.PHONY: verify clean
|
||||
20
README.md
20
README.md
|
|
@ -5,17 +5,25 @@ For this it will provide API endpoints for every configured attribute-group.
|
|||
The configuration of the provider is possible via an admin page.
|
||||
|
||||
Every endpoint responds with a list of all attribute values, that:
|
||||
- is in the attribute group matching `attribute-group`
|
||||
- matches an optional RegEx Pattern `attribute-regex`
|
||||
- belongs to a user with a role matching `match-role`
|
||||
- is non-empty
|
||||
- are in the attribute group matching `attribute-group`
|
||||
- match an optional RegEx Pattern `attribute-regex`
|
||||
- belong to a user with a role matching `match-role`
|
||||
- are non-empty
|
||||
|
||||
Multivalue attributes are flattened in the response.
|
||||
|
||||
## Building
|
||||
|
||||
Maven is required for building the provider.
|
||||
|
||||
Once all dependencies are met, simply call `make` to build the provider, which should then produce a `attribute-endpoints-provider-1.0-SNAPSHOT.jar` in the `attribute-endpoints-provider/target/` directory.
|
||||
|
||||
There's also `make clean` available for removing the output directory.
|
||||
|
||||
## Example Setup
|
||||
|
||||
We assume an unconfigured, fresh Keycloak installation running under `http://localhost:8080`.
|
||||
We assume an unconfigured, fresh Keycloak installation running under `http://localhost:8080`.
|
||||
(This can be achieved by running the provided `compose.yaml` after building the provider as outlined in [Building](#building).)
|
||||
|
||||
1. Add a new realm
|
||||
e.g. "TestRealm"
|
||||
|
|
@ -53,7 +61,7 @@ We assume an unconfigured, fresh Keycloak installation running under `http://loc
|
|||
- After creating:
|
||||
- give it the role `myattribute-export`
|
||||
- set a password in the users settings `Creadentials > Set password`. For Example `"password"`
|
||||
8. Under `🪪 Attribute Endpoints 🚀 > Create item`, add a new endpoint to the provider
|
||||
8. Under `Attribute Endpoints > Create item`, add a new endpoint to the provider
|
||||
Example:
|
||||
- `Slug` = `"ssh_keys"`
|
||||
- `Attribute Group` = `"my-attributes-group"`
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import com.google.auto.service.AutoService;
|
|||
*/
|
||||
@AutoService(UiPageProviderFactory.class)
|
||||
public class AdminUiPage implements UiPageProvider, UiPageProviderFactory<ComponentModel> {
|
||||
public static final String PROVIDER_ID = "🪪 Attribute Endpoints 🚀";
|
||||
public static final String PROVIDER_ID = "Attribute Endpoints";
|
||||
|
||||
@Override
|
||||
public void init(Config.Scope config) {
|
||||
|
|
@ -54,22 +54,28 @@ public class AdminUiPage implements UiPageProvider, UiPageProviderFactory<Compon
|
|||
|
||||
Pattern slugPattern = Pattern.compile("^[a-zA-Z0-9_-]*$");
|
||||
String configAttributeSlug = model.getConfig().getFirst("slug");
|
||||
|
||||
if (!slugPattern.matcher(configAttributeSlug).matches()) {
|
||||
if (configAttributeSlug == null) {
|
||||
hasError = true;
|
||||
errorString += " • [Slug] can not be empty\n";
|
||||
} else if (!slugPattern.matcher(configAttributeSlug).matches()) {
|
||||
hasError = true;
|
||||
errorString += " • [Slug] can only contain anlphanumeric characters, dash and underscore (a-z A-Z 0-9 _ - )\n";
|
||||
}
|
||||
|
||||
String configAuthRole = model.getConfig().getFirst("auth-role");
|
||||
RoleModel authRole = realm.getRole(configAuthRole);
|
||||
if (authRole == null) {
|
||||
if (configAuthRole == null) {
|
||||
hasError = true;
|
||||
errorString += " • [Auth Role] can not be empty\n";
|
||||
} else if (realm.getRole(configAuthRole) == null) {
|
||||
hasError = true;
|
||||
errorString += " • [Auth Role] does not exist\n";
|
||||
}
|
||||
|
||||
String configMatchRole = model.getConfig().getFirst("match-role");
|
||||
RoleModel matchRole = realm.getRole(configMatchRole);
|
||||
if (matchRole == null) {
|
||||
if (configMatchRole == null) {
|
||||
hasError = true;
|
||||
errorString += " • [Match Role] can not be empty\n";
|
||||
} else if (realm.getRole(configMatchRole) == null) {
|
||||
hasError = true;
|
||||
errorString += " • [Match Role] does not exist\n";
|
||||
}
|
||||
|
|
@ -77,7 +83,10 @@ public class AdminUiPage implements UiPageProvider, UiPageProviderFactory<Compon
|
|||
UserProfileProvider profileProvider = session.getProvider(UserProfileProvider.class);
|
||||
UPConfig upconfig = profileProvider.getConfiguration();
|
||||
String configAttributeGroup = model.getConfig().getFirst("attribute-group");
|
||||
if (!upconfig.getGroups().stream().anyMatch(g -> g.getName().equals(configAttributeGroup))) {
|
||||
if (configAttributeGroup == null) {
|
||||
hasError = true;
|
||||
errorString += " • [Attribute Group] can not be empty\n";
|
||||
} else if (!upconfig.getGroups().stream().anyMatch(g -> g.getName().equals(configAttributeGroup))) {
|
||||
hasError = true;
|
||||
errorString += " • [Attribute Group] does not exist\n";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public class AttributeEndpointsResourceProvider implements RealmResourceProvider
|
|||
@GET
|
||||
@Path("export/{slug}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response exportKeys(@PathParam("slug") String slug) {
|
||||
public Response exportAttributeValues(@PathParam("slug") String slug) {
|
||||
KeycloakContext context = session.getContext();
|
||||
RealmModel realm = context.getRealm();
|
||||
|
||||
|
|
@ -62,11 +62,16 @@ public class AttributeEndpointsResourceProvider implements RealmResourceProvider
|
|||
.filter(c -> c.getConfig().getFirst("slug").equals(slug))
|
||||
.toList();
|
||||
|
||||
Auth auth = AttributeEndpointsResourceProvider.getAuth(session);
|
||||
|
||||
if (componentList.isEmpty()) {
|
||||
throw new NotFoundException("Endpoint not found.");
|
||||
}
|
||||
|
||||
Auth auth = AttributeEndpointsResourceProvider.getAuth(session);
|
||||
if (componentList.size() > 1) {
|
||||
throw new NotFoundException(
|
||||
"Endpoint Configuration Error - Multiple configurations exist for this endpoint.");
|
||||
}
|
||||
|
||||
ComponentModel component = componentList.get(0);
|
||||
|
||||
|
|
@ -106,11 +111,6 @@ public class AttributeEndpointsResourceProvider implements RealmResourceProvider
|
|||
throw new ForbiddenException("User does not have required auth role.");
|
||||
}
|
||||
|
||||
if (componentList.size() > 1) {
|
||||
throw new NotFoundException(
|
||||
"Endpoint Configuration Error - Multiple configurations exist for this endpoint.");
|
||||
}
|
||||
|
||||
List<String> attributeNames = upconfig.getAttributes()
|
||||
.stream()
|
||||
.filter(a -> a.getGroup() != null && a.getGroup().equals(configAttributeGroup))
|
||||
|
|
|
|||
2667
realm-export.json
2667
realm-export.json
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue