Skip to content

Commit

Permalink
Fix keycloak deployment in dev profile
Browse files Browse the repository at this point in the history
  • Loading branch information
barreiro authored and lampajr committed Aug 29, 2024
1 parent 5199e6f commit b3af2d9
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import io.hyperfoil.tools.horreum.svc.Roles;
import io.hyperfoil.tools.horreum.svc.user.UserBackEnd;
import io.quarkus.logging.Log;
import io.quarkus.runtime.LaunchMode;
import io.quarkus.runtime.StartupEvent;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
Expand All @@ -25,8 +26,6 @@
import java.util.Map;
import java.util.Optional;

import static io.quarkus.runtime.configuration.ProfileManager.getLaunchMode;

@ApplicationScoped public class SecurityBootstrap {

@ConfigProperty(name = "quarkus.keycloak.admin-client.server-url") Optional<String> keycloakURL;
Expand All @@ -39,7 +38,7 @@
private static final String MIGRATION_PROVIDER = "database";
private static final String BOOTSTRAP_ACCOUNT = "horreum.bootstrap";

private static final char[] RANDOM_PASSWRORD_CHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789").toCharArray();
private static final char[] RANDOM_PASSWORD_CHARS = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789").toCharArray();
private static final int RANDOM_PASSWORD_DEFAULT_LENGTH = 16;

@Inject RoleManager roleManager;
Expand Down Expand Up @@ -115,15 +114,16 @@ private void addTeamMembership(UserInfo userInfo, String teamName, TeamRole role
* Create an admin account if there are no accounts in the system.
* The account should be removed once other accounts are created.
*/
public void checkBootstrapAccount() {
@WithRoles(extras = BOOTSTRAP_ACCOUNT)
@Transactional public void checkBootstrapAccount() {
// checks the list of administrators. a user cannot remove himself nor create the bootstrap account (restricted namespace)
List<String> administrators = backend.get().administrators().stream().map(userData -> userData.username).toList();
if (administrators.isEmpty()) {
UserService.NewUser user = new UserService.NewUser();
user.user = new UserService.UserData("", BOOTSTRAP_ACCOUNT, "Bootstrap", "Acount", "[email protected]");
user.password = providedBootstrapPassword.orElseGet(() -> getLaunchMode().isDevOrTest() ? "secret" : generateRandomPassword(RANDOM_PASSWORD_DEFAULT_LENGTH));
user.user = new UserService.UserData("", BOOTSTRAP_ACCOUNT, "Bootstrap", "Account", "[email protected]");
user.password = providedBootstrapPassword.orElseGet(() -> LaunchMode.current().isDevOrTest() ? "secret" : generateRandomPassword(RANDOM_PASSWORD_DEFAULT_LENGTH));

// create bootstrap acconut with admin role
// create bootstrap account with admin role
backend.get().createUser(user);
backend.get().setPassword(BOOTSTRAP_ACCOUNT, user.password); // KeycloakUserBackend.createUser() creates a temp password, with this call the password is usable
backend.get().updateAdministrators(List.of(BOOTSTRAP_ACCOUNT));
Expand All @@ -132,6 +132,10 @@ public void checkBootstrapAccount() {
backend.get().addTeam("dev-team");
backend.get().updateTeamMembers("dev-team", Map.of(BOOTSTRAP_ACCOUNT, List.of(Roles.MANAGER, Roles.TESTER, Roles.UPLOADER, Roles.VIEWER)));

// create db entry, if not existent, like in UserService.createLocalUser()
UserInfo userInfo = UserInfo.<UserInfo>findByIdOptional(BOOTSTRAP_ACCOUNT).orElse(new UserInfo(BOOTSTRAP_ACCOUNT));
userInfo.defaultTeam = "dev-team";

Log.infov("\n>>>\n>>> Created temporary account {0} with password {1}\n>>>", BOOTSTRAP_ACCOUNT, user.password);
} else if (administrators.size() > 1 && administrators.contains(BOOTSTRAP_ACCOUNT)) {
Log.warnv("The temporary account {0} can be removed", BOOTSTRAP_ACCOUNT);
Expand All @@ -140,7 +144,7 @@ public void checkBootstrapAccount() {

public static String generateRandomPassword(int lenght) {
StringBuilder builder = new StringBuilder(lenght);
new SecureRandom().ints(lenght, 0, RANDOM_PASSWRORD_CHARS.length).mapToObj(i -> RANDOM_PASSWRORD_CHARS[i]).forEach(builder::append);
new SecureRandom().ints(lenght, 0, RANDOM_PASSWORD_CHARS.length).mapToObj(i -> RANDOM_PASSWORD_CHARS[i]).forEach(builder::append);
return builder.toString();
}

Expand Down
4 changes: 1 addition & 3 deletions horreum-backend/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ quarkus.oidc.client-id=horreum

## Do not un comment the line below, there appears to be a bug in Quarkus 3.4.1 where dev services do not overwrite the config property
quarkus.oidc.credentials.secret=overridden-in-file-dot-env
%dev.quarkus.oidc.credentials.secret=**********

# This option lets HorreumAuthorizationFilter transform app keys sent as tokens
quarkus.http.auth.proactive=false
Expand All @@ -113,9 +114,6 @@ quarkus.keycloak.admin-client.client-id=horreum
quarkus.keycloak.admin-client.client-secret=${quarkus.oidc.credentials.secret}
quarkus.keycloak.admin-client.realm=${horreum.keycloak.realm}
quarkus.keycloak.admin-client.grant-type=CLIENT_CREDENTIALS
%dev.quarkus.keycloak.admin-client.client-id=admin-cli
%dev.quarkus.keycloak.admin-client.realm=master
%dev.quarkus.keycloak.admin-client.grant-type=PASSWORD

# Secret used to sign database rows
horreum.db.secret=secret
Expand Down

0 comments on commit b3af2d9

Please sign in to comment.