Skip to content

Commit

Permalink
Refactor: Use --datastore-bootstrap-files and schema.yml for initial …
Browse files Browse the repository at this point in the history
…seeding. remove obsolete code.
  • Loading branch information
DGuhr committed Jan 31, 2023
1 parent 06aa2db commit 9f39e5a
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 89 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ much more. as said highly experimental, dunno where to go with this, but it's fu
# Done
1) extended to (experimentally) handle "add group" events
2) extended to (experimentally) handle "group membership" events
3) using ChatGPT to create myself a user generation script for keycloak. More about that [here](https://github.com/DGuhr/keycloak-spicedb-eventlistener/blob/main/CHATGPT_GENERATOR.md)
3) using ChatGPT to create myself a user generation script for keycloak. More about that [here](https://github.com/DGuhr/keycloak-spicedb-eventlistener/blob/main/CHATGPT_GENERATOR.md)
4) refactor initial schema creation, use spicedb and schema.yml directly instead of doing it codewise.
6 changes: 4 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ services:
aliases:
- keycloak
spicedb:
image: "authzed/spicedb"
command: "serve"
image: authzed/spicedb
command: "serve --datastore-bootstrap-files /var/lib/spicedb/initial/initial_schema.yml"
restart: "always"
volumes:
- ./schema.yml:/var/lib/spicedb/initial/initial_schema.yml
ports:
- "8081:8080"
- "9090:9090"
Expand Down
26 changes: 26 additions & 0 deletions schema.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
schema: |-
definition principal {}
definition tenant {
relation member : principal
relation tenant_admin : principal
permission admin = tenant_admin
}
definition group {
relation parent : tenant | group
relation direct_member : principal
relation group_admin : principal
permission member = direct_member + group_admin + parent->admin
permission admin = group_admin + parent->admin
}
definition role {
relation assigned_group: group
permission member = assigned_group->member
}
relationships: ""
assertions: null
validation: null
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@
public class SpiceDbServiceHandler extends ServiceHandler {
private static final Logger logger = Logger.getLogger(SpiceDbServiceHandler.class);

public SpiceDbServiceHandler(KeycloakSession session, Config.Scope config) { //TODO : refactor getOrCreate - called everytime, should only once.
public SpiceDbServiceHandler(KeycloakSession session, Config.Scope config) {
super(session, config);
getOrCreateSchema();
}

@Override
Expand Down Expand Up @@ -58,90 +57,6 @@ private void addGroupMember(SpiceDbTupleEvent sdbEvent) {
writeSpiceDbRelationship(sdbEvent);
}

private SchemaServiceOuterClass.ReadSchemaResponse getOrCreateSchema() {

ManagedChannel channel = ManagedChannelBuilder
.forTarget(config.get("spicedbHost") +":"+config.get("spicedbPort"))
.usePlaintext()
.build();

SchemaServiceGrpc.SchemaServiceBlockingStub schemaService = SchemaServiceGrpc.newBlockingStub(channel)
.withCallCredentials(new BearerToken(config.get("spicedbToken")));

SchemaServiceOuterClass.ReadSchemaRequest readRequest = SchemaServiceOuterClass.ReadSchemaRequest
.newBuilder()
.build();

SchemaServiceOuterClass.ReadSchemaResponse readResponse;

try {
readResponse = schemaService.readSchema(readRequest);
} catch (Exception e) {
//ugly but hey..
if(e.getMessage().contains("No schema has been defined")) {
logger.warn("No scheme there yet, creating initial one.");
writeSchema(schemaService, getInitialSchema());
} else {
throw new RuntimeException("connection to spicedb not available.");
}
return getOrCreateSchema();
} finally {
channel.shutdown();
try {
if (!channel.awaitTermination(3000, TimeUnit.MILLISECONDS)) {
channel.shutdownNow();
}
} catch (InterruptedException e) {
channel.shutdownNow();
}
}
logger.info("Scheme found.");
return readResponse;
}

private String writeSchema(SchemaServiceGrpc.SchemaServiceBlockingStub schemaService, String schema) {
SchemaServiceOuterClass.WriteSchemaRequest request = SchemaServiceOuterClass.WriteSchemaRequest
.newBuilder()
.setSchema(schema)
.build();

SchemaServiceOuterClass.WriteSchemaResponse writeSchemaResponse;
try {
writeSchemaResponse = schemaService.writeSchema(request);
} catch (Exception e) {
logger.warn("Writing initial Schema failed!", e);
throw new RuntimeException(e);
}
logger.info("writeSchemaResponse: " + writeSchemaResponse.toString());
return writeSchemaResponse.toString();
}

private static String getInitialSchema() {

return "definition principal {}\n" +
"\n" +
"definition tenant {\n" +
" relation member : principal\n" +
" relation tenant_admin : principal\n" +
" permission admin = tenant_admin\n" +
"}\n" +
"\n" +
"definition group {\n" +
" relation parent : tenant | group\n" +
" relation direct_member : principal\n" +
" relation group_admin : principal\n" +
"\n" +
" permission member = direct_member + group_admin + parent->admin\n" +
" permission admin = group_admin + parent->admin\n" +
"}\n" +
"\n" +
"definition role {\n" +
" relation assigned_group: group\n" +
"\n" +
" permission member = assigned_group->member\n" +
"}";
}

private String writeSpiceDbRelationship(SpiceDbTupleEvent sdbEvent) {

ManagedChannel channel = ManagedChannelBuilder
Expand Down

0 comments on commit 9f39e5a

Please sign in to comment.