Skip to content

Commit

Permalink
feat: add command to generate new secrets (#14)
Browse files Browse the repository at this point in the history
Closes #14
  • Loading branch information
MarcScheib authored Sep 24, 2023
1 parent 174240f commit e70ded7
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.cycrilabs.keycloak.configurator.commands.generate.boundary;

import java.util.List;
import java.util.stream.Stream;

import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

import org.keycloak.admin.client.Keycloak;
import org.keycloak.representations.idm.ClientRepresentation;

import com.cycrilabs.keycloak.configurator.commands.generate.entity.GenerateSecretsCommandConfiguration;
import com.cycrilabs.keycloak.configurator.shared.control.KeycloakFactory;

import io.quarkus.logging.Log;

@ApplicationScoped
public class GenerateSecrets {
@Inject
GenerateSecretsCommandConfiguration configuration;
Keycloak keycloak;

@PostConstruct
public void init() {
keycloak = KeycloakFactory.create(configuration);
}

public void run() {
final List<String> generatedIds = getClients()
.filter(client -> client.getSecret() != null)
.map(ClientRepresentation::getId)
.map(this::generateSecret)
.toList();
Log.infof("Generated secrets for %d clients.", Integer.valueOf(generatedIds.size()));
}

private Stream<ClientRepresentation> getClients() {
return configuration.getClientId() == null
? keycloak.realm(configuration.getRealmName())
.clients()
.findAll()
.stream()
: keycloak.realm(configuration.getRealmName())
.clients()
.findByClientId(configuration.getClientId())
.stream();
}

private String generateSecret(final String id) {
return keycloak.realm(configuration.getRealmName())
.clients()
.get(id)
.generateNewSecret()
.getId();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.cycrilabs.keycloak.configurator.commands.generate.control;

import jakarta.inject.Inject;

import com.cycrilabs.keycloak.configurator.commands.generate.boundary.GenerateSecrets;
import com.cycrilabs.keycloak.configurator.commands.generate.entity.GenerateSecretsCommandConfiguration;
import com.cycrilabs.keycloak.configurator.shared.control.KeycloakOptions;

import io.quarkus.logging.Log;
import picocli.CommandLine;

@CommandLine.Command(name = "rotate-secrets", mixinStandardHelpOptions = true)
public class GenerateSecretsCommand implements Runnable {
@CommandLine.Mixin
KeycloakOptions keycloakOptions;
@CommandLine.Option(required = true, names = { "-r", "--realm" },
description = "Realm name to generate secrets for.")
String realm;
@CommandLine.Option(names = { "-c", "--client" },
description = "Specific client to generate new secret.")
String clientId;

@Inject
GenerateSecretsCommandConfiguration configuration;
@Inject
GenerateSecrets command;

@Override
public void run() {
try {
Log.infof("Generating secrets of realm '%s'.", configuration.getRealmName());
command.run();
} catch (final Exception e) {
Log.errorf(e, "Failed to generate secrets of realm '%s'.",
configuration.getRealmName());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.cycrilabs.keycloak.configurator.commands.generate.control;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;

import com.cycrilabs.keycloak.configurator.commands.generate.entity.GenerateSecretsCommandConfiguration;

import picocli.CommandLine;

@ApplicationScoped
public class GenerateSecretsCommandConfigurationProducer {
@Produces
@ApplicationScoped
GenerateSecretsCommandConfiguration createConfiguration(
final CommandLine.ParseResult parseResult) {
return new GenerateSecretsCommandConfiguration(parseResult);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.cycrilabs.keycloak.configurator.commands.generate.entity;

import lombok.Getter;

import com.cycrilabs.keycloak.configurator.shared.entity.KeycloakConfiguration;

import picocli.CommandLine.ParseResult;

@Getter
public class GenerateSecretsCommandConfiguration extends KeycloakConfiguration {
private final String realmName;
private final String clientId;

public GenerateSecretsCommandConfiguration(final ParseResult parseResult) {
super(parseResult);
realmName = getMatchedOption(parseResult, "-r");
clientId = getMatchedOption(parseResult, "-c");
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.cycrilabs.keycloak.configurator.shared.control;

import com.cycrilabs.keycloak.configurator.commands.configure.control.ConfigureCommand;
import com.cycrilabs.keycloak.configurator.commands.generate.control.GenerateSecretsCommand;
import com.cycrilabs.keycloak.configurator.commands.secrets.control.ExportSecretsCommand;

import io.quarkus.picocli.runtime.annotations.TopCommand;
Expand All @@ -9,6 +10,7 @@
@TopCommand
@CommandLine.Command(mixinStandardHelpOptions = true,
version = "0.1.0",
subcommands = { ConfigureCommand.class, ExportSecretsCommand.class })
subcommands = { ConfigureCommand.class, ExportSecretsCommand.class,
GenerateSecretsCommand.class })
public class EntryCommand {
}

0 comments on commit e70ded7

Please sign in to comment.