forked from keycloak/keycloak
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Warnings for temporary admin user and service account
* UI banner, labels and log messages are shown when temporary admin account is used * added UI tests that check the elements' presence Co-authored-by: Václav Muzikář <[email protected]> Signed-off-by: Peter Zaoral <[email protected]>
- Loading branch information
Showing
17 changed files
with
176 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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? | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,6 +68,7 @@ | |
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
import static org.keycloak.models.light.LightweightUserAdapter.isLightweightUser; | ||
import static org.keycloak.models.Constants.TEMP_ADMIN_ATTR_NAME; | ||
|
||
/** | ||
* @author <a href="mailto:[email protected]">Bill Burke</a> | ||
|
@@ -265,10 +266,21 @@ public static UserRepresentation toBriefRepresentation(UserModel user) { | |
rep.setEnabled(user.isEnabled()); | ||
rep.setEmailVerified(user.isEmailVerified()); | ||
rep.setFederationLink(user.getFederationLink()); | ||
addAttributeToBriefRep(user, rep, TEMP_ADMIN_ATTR_NAME); | ||
|
||
return rep; | ||
} | ||
|
||
public static void addAttributeToBriefRep(UserModel user, UserRepresentation userRep, String attributeName) { | ||
String userAttributeValue = user.getFirstAttribute(attributeName); | ||
if (Boolean.parseBoolean(userAttributeValue)) { | ||
if (userRep.getAttributes() == null) { | ||
userRep.setAttributes(new HashMap<>()); | ||
} | ||
userRep.getAttributes().put(attributeName, Collections.singletonList(user.getFirstAttribute(attributeName))); | ||
} | ||
} | ||
|
||
public static EventRepresentation toRepresentation(Event event) { | ||
EventRepresentation rep = new EventRepresentation(); | ||
rep.setTime(event.getTime()); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,20 +18,25 @@ | |
package org.keycloak.events.log; | ||
|
||
import org.jboss.logging.Logger; | ||
import org.keycloak.Config; | ||
import org.keycloak.common.util.StackUtil; | ||
import org.keycloak.events.Event; | ||
import org.keycloak.events.EventListenerProvider; | ||
import org.keycloak.events.EventListenerTransaction; | ||
import org.keycloak.events.admin.AdminEvent; | ||
import org.keycloak.models.KeycloakContext; | ||
import org.keycloak.models.KeycloakSession; | ||
import org.keycloak.models.RealmModel; | ||
import org.keycloak.sessions.AuthenticationSessionModel; | ||
import org.keycloak.utils.StringUtil; | ||
|
||
import jakarta.ws.rs.core.Cookie; | ||
import jakarta.ws.rs.core.HttpHeaders; | ||
import jakarta.ws.rs.core.UriInfo; | ||
import java.util.Map; | ||
import java.util.function.Supplier; | ||
|
||
import static org.keycloak.models.Constants.TEMP_ADMIN_ATTR_NAME; | ||
|
||
/** | ||
* @author <a href="mailto:[email protected]">Stian Thorgersen</a> | ||
|
@@ -135,6 +140,24 @@ private void logEvent(Event event) { | |
|
||
logger.log(logger.isTraceEnabled() ? Logger.Level.TRACE : level, sb.toString()); | ||
} | ||
|
||
if (event.getRealmName().equals(Config.getAdminRealm())) { | ||
Supplier<RealmModel> getRealm = () -> session.realms().getRealm(event.getRealmId()); | ||
switch (event.getType()) { | ||
case LOGIN: | ||
var user = session.users().getUserById(getRealm.get(), event.getUserId()); | ||
if (Boolean.parseBoolean(user.getFirstAttribute(TEMP_ADMIN_ATTR_NAME))) { | ||
logger.warn(user.getUsername() + " is a temporary admin user account. To harden security, create a permanent account and delete the temporary one."); | ||
} | ||
break; | ||
case CLIENT_LOGIN: | ||
var client = session.clients().getClientByClientId(getRealm.get(), event.getClientId()); | ||
if (Boolean.parseBoolean(client.getAttribute(TEMP_ADMIN_ATTR_NAME))) { | ||
logger.warn(client.getClientId() + " is a temporary admin service account. To harden security, create a permanent account and delete the temporary one."); | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
|
||
private void logAdminEvent(AdminEvent adminEvent, boolean includeRepresentation) { | ||
|
@@ -176,7 +199,7 @@ private void logAdminEvent(AdminEvent adminEvent, boolean includeRepresentation) | |
@Override | ||
public void close() { | ||
} | ||
|
||
private void setKeycloakContext(StringBuilder sb) { | ||
KeycloakContext context = session.getContext(); | ||
UriInfo uriInfo = context.getUri(); | ||
|
@@ -199,7 +222,7 @@ private void setKeycloakContext(StringBuilder sb) { | |
} | ||
sb.append("]"); | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,8 @@ | |
import org.keycloak.userprofile.UserProfileProvider; | ||
import org.keycloak.utils.StringUtil; | ||
|
||
import static org.keycloak.models.Constants.TEMP_ADMIN_ATTR_NAME; | ||
|
||
/** | ||
* @author <a href="mailto:[email protected]">Bill Burke</a> | ||
* @version $Revision: 1 $ | ||
|
@@ -137,15 +139,15 @@ public boolean createTemporaryMasterRealmAdminUser(String username, String passw | |
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); | ||
adminUser.credentialManager().updateCredential(usrCredModel); | ||
|
||
RoleModel adminRole = realm.getRole(AdminRoles.ADMIN); | ||
adminUser.grantRole(adminRole); | ||
|
||
ServicesLogger.LOGGER.createdTemporaryAdminUser(username); | ||
} catch (ModelDuplicateException e) { | ||
ServicesLogger.LOGGER.addUserFailedUserExists(username, Config.getAdminRealm()); | ||
|
@@ -176,15 +178,15 @@ public boolean createTemporaryMasterRealmAdminService(String clientId, String cl | |
|
||
try { | ||
ClientModel adminClientModel = ClientManager.createClient(session, realm, adminClient); | ||
|
||
new ClientManager(new RealmManager(session)).enableServiceAccount(adminClientModel); | ||
UserModel serviceAccount = session.users().getServiceAccount(adminClientModel); | ||
RoleModel adminRole = realm.getRole(AdminRoles.ADMIN); | ||
serviceAccount.grantRole(adminRole); | ||
// TODO: set temporary | ||
|
||
adminClientModel.setAttribute(TEMP_ADMIN_ATTR_NAME, Boolean.TRUE.toString()); | ||
// also set the expiration - could be relative to a creation timestamp, or computed | ||
|
||
ServicesLogger.LOGGER.createdTemporaryAdminService(clientId); | ||
} catch (ModelDuplicateException e) { | ||
ServicesLogger.LOGGER.addClientFailedClientExists(clientId, Config.getAdminRealm()); | ||
|
Oops, something went wrong.