Skip to content

Commit

Permalink
Temp admin banner
Browse files Browse the repository at this point in the history
Signed-off-by: Václav Muzikář <[email protected]>
  • Loading branch information
vmuzikar committed Jul 3, 2024
1 parent f40a72d commit b53760f
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3206,4 +3206,6 @@ redirectWhenEmailMatchesHelp=Automatically redirect the user to this identity pr
emailVerificationHelp=Specifies independent timeout for email verification.
idpAccountEmailVerificationHelp=Specifies independent timeout for IdP account email verification.
forgotPasswordHelp=Specifies independent timeout for forgot password.
executeActionsHelp=Specifies independent timeout for execute actions.
executeActionsHelp=Specifies independent timeout for execute actions.
loggedInAsTempAdminUser=You are logged in as a temporary admin user. To harden security, create a permanent admin account and delete the temporary one.
temporaryAdmin=temporary admin
4 changes: 2 additions & 2 deletions js/apps/admin-ui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { WhoAmIContextProvider } from "./context/whoami/WhoAmI";
import type { Environment } from "./environment";
import { SubGroups } from "./groups/SubGroupsContext";
import { AuthWall } from "./root/AuthWall";
import { Banners } from "./Banner";
import { Banners } from "./Banners";

const AppContexts = ({ children }: PropsWithChildren) => (
<ErrorBoundaryProvider>
Expand Down Expand Up @@ -69,10 +69,10 @@ export const App = () => {
breadcrumb={<PageBreadCrumbs />}
mainContainerId={mainPageContentId}
>
<Banners />
<ErrorBoundaryFallback fallback={ErrorRenderer}>
<Suspense fallback={<KeycloakSpinner />}>
<AuthWall>
<Banners />
<Outlet />
</AuthWall>
</Suspense>
Expand Down
19 changes: 0 additions & 19 deletions js/apps/admin-ui/src/Banner.tsx

This file was deleted.

26 changes: 26 additions & 0 deletions js/apps/admin-ui/src/Banners.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Banner, Flex, FlexItem } from "@patternfly/react-core";
import { ExclamationTriangleIcon } from "@patternfly/react-icons";
import { useWhoAmI } from "./context/whoami/WhoAmI";
import { useTranslation } from "react-i18next";

const WarnBanner = (msg: string) => {
const { t } = useTranslation();

return (
<Banner screenReaderText={t(msg)} variant="gold" isSticky>
<Flex spaceItems={{ default: "spaceItemsSm" }}>
<FlexItem>
<ExclamationTriangleIcon />
</FlexItem>
<FlexItem>{t(msg)}</FlexItem>
</Flex>
</Banner>
);
};

export const Banners = () => {
const { whoAmI } = useWhoAmI();

if (whoAmI.isTemporary()) return WarnBanner("loggedInAsTempAdminUser");
// more banners in the future?
};
4 changes: 4 additions & 0 deletions js/apps/admin-ui/src/context/whoami/WhoAmI.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ export class WhoAmI {

return this.#me.realm_access;
}

public isTemporary(): boolean {
return this.#me?.temporary ?? false;
}
}

type WhoAmIProps = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ export default interface WhoAmIRepresentation {
locale: string;
createRealm: boolean;
realm_access: { [key: string]: AccessType[] };
temporary: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class ApplianceBootstrap {
public static final String DEFAULT_TEMP_ADMIN_USERNAME = "temp-admin";
public static final String DEFAULT_TEMP_ADMIN_SERVICE = "temp-admin-service";
public static final int DEFAULT_TEMP_ADMIN_EXPIRATION = 120;
public static final String TEMP_ADMIN_ATTR_NAME = "temporary_admin";

private final KeycloakSession session;

Expand Down Expand Up @@ -127,8 +128,7 @@ public void createTemporaryMasterRealmAdminUser(String username, String password

UserModel adminUser = session.users().addUser(realm, username);
adminUser.setEnabled(true);
// TODO: is this appropriate, does it need to be managed?
// adminUser.setSingleAttribute("temporary_admin", Boolean.TRUE.toString());
adminUser.setSingleAttribute(TEMP_ADMIN_ATTR_NAME, Boolean.TRUE.toString());
// also set the expiration - could be relative to a creation timestamp, or computed

UserCredentialModel usrCredModel = UserCredentialModel.password(password);
Expand Down Expand Up @@ -161,7 +161,7 @@ public void createTemporaryMasterRealmAdminService(String clientId, String clien
RoleModel adminRole = realm.getRole(AdminRoles.ADMIN);
serviceAccount.grantRole(adminRole);

// TODO: set temporary
serviceAccount.setSingleAttribute(TEMP_ADMIN_ATTR_NAME, Boolean.TRUE.toString());
// also set the expiration - could be relative to a creation timestamp, or computed

ServicesLogger.LOGGER.createdTemporaryAdminService(clientId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
import java.util.Set;
import java.util.stream.Collectors;

import static org.keycloak.services.managers.ApplianceBootstrap.TEMP_ADMIN_ATTR_NAME;

/**
* @author <a href="mailto:[email protected]">Bill Burke</a>
* @version $Revision: 1 $
Expand Down Expand Up @@ -98,6 +100,7 @@ public static class WhoAmI {
protected String realm;
protected String displayName;
protected Locale locale;
protected boolean isTemporary;

@JsonProperty("createRealm")
protected boolean createRealm;
Expand All @@ -107,13 +110,14 @@ public static class WhoAmI {
public WhoAmI() {
}

public WhoAmI(String userId, String realm, String displayName, boolean createRealm, Map<String, Set<String>> realmAccess, Locale locale) {
public WhoAmI(String userId, String realm, String displayName, boolean createRealm, Map<String, Set<String>> realmAccess, Locale locale, boolean isTemporary) {
this.userId = userId;
this.realm = realm;
this.displayName = displayName;
this.createRealm = createRealm;
this.realmAccess = realmAccess;
this.locale = locale;
this.isTemporary = isTemporary;
}

public String getUserId() {
Expand Down Expand Up @@ -168,6 +172,14 @@ public void setLocale(Locale locale) {
public String getLocaleLanguageTag() {
return locale != null ? locale.toLanguageTag() : null;
}

public boolean isTemporary() {
return isTemporary;
}

public void setTemporary(boolean temporary) {
isTemporary = temporary;
}
}

/**
Expand Down Expand Up @@ -269,7 +281,7 @@ public Response whoAmI(@QueryParam("currentRealm") String currentRealm) {
.allowedOrigins(authResult.getToken())
.allowedMethods("GET")
.auth()
.add(Response.ok(new WhoAmI(user.getId(), realm.getName(), displayName, createRealm, realmAccess, locale)));
.add(Response.ok(new WhoAmI(user.getId(), realm.getName(), displayName, createRealm, realmAccess, locale, Boolean.parseBoolean(user.getFirstAttribute(TEMP_ADMIN_ATTR_NAME)))));
}

private void addRealmAccess(RealmModel realm, UserModel user, Map<String, Set<String>> realmAdminAccess) {
Expand Down

0 comments on commit b53760f

Please sign in to comment.