8000 Review of ImpersonationTest by jimmychakkalakal · Pull Request #50378 · keycloak/keycloak · GitHub
[go: up one dir, main page]

Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -89,15 +88,16 @@
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.hamcrest.MatcherAssert;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.Cookie;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;

/**
* Tests Undertow Adapter
Expand Down Expand Up @@ -152,6 +152,7 @@ public void testImpersonateByMasterImpersonator() {
try (Response response = masterRealm.admin().users().create(UserBuilder.create().username("master-impersonator").build())) {
userId = ApiUtil.getCreatedId(response);
}
masterRealm.cleanup().add(r -> r.users().delete(userId).close());

UserResource user = masterRealm.admin().users().get(userId);
user.resetPassword(CredentialBuilder.password("password").build());
Expand All @@ -165,12 +166,10 @@ public void testImpersonateByMasterImpersonator() {
user.roles().clientLevel(testRealmClient.toRepresentation().getId()).add(roles);

testSuccessfulImpersonation("master-impersonator", Config.getAdminRealm());

masterRealm.admin().users().get(userId).remove();
}

@Test
public void testImpersongetServiceAccountUserateByTestImpersonator() {
public void testImpersonateByTestImpersonator() {
testSuccessfulImpersonation("impersonator", managedRealm.getName());
Comment thread
jimmychakkalakal marked this conversation as resolved.
Resolved
}

Expand Down Expand Up @@ -200,16 +199,15 @@ public void testImpersonationFailsForDisabledUser() {
}

@Test
public void testImpersonateByMastertBadImpersonator() {
public void testImpersonateByMasterBadImpersonator() {
String userId;
try (Response response = masterRealm.admin().users().create(UserBuilder.create().username("master-bad-impersonator").build())) {
userId = ApiUtil.getCreatedId(response);
}
masterRealm.admin().users().get(userId).resetPassword(CredentialBuilder.create().password("password").build());
masterRealm.cleanup().add(r -> r.users().delete(userId).close());
masterRealm.admin().users().get(userId).resetPassword(CredentialBuilder.password("password").build());

testForbiddenImpersonation("master-bad-impersonator", Config.getAdminRealm());

masterRealm.admin().users().get(userId).remove();
}


Expand All @@ -229,7 +227,7 @@ public void testImpersonationWorksWhenAuthenticationSessionExists() throws Excep
oauth.openLoginForm();

//KEYCLOAK-12783
Assertions.assertTrue(Objects.requireNonNull(driver.getCurrentUrl()).contains(testApp.getRedirectionUri()));
assertThat(driver.getCurrentUrl(), containsString(testApp.getRedirectionUri()));
}

// KEYCLOAK-17655
Expand All @@ -242,7 +240,11 @@ public void testImpersonationBySameRealmServiceAccount() throws Exception {
.serviceAccountsEnabled(true)
.build();
clientApp.setServiceAccountsEnabled(true);
managedRealm.admin().clients().create(clientApp);
String clientId;
try (Response response = managedRealm.admin().clients().create(clientApp)) {
clientId = ApiUtil.getCreatedId(response);
}
managedRealm.cleanup().add(r -> r.clients().get(clientId).remove());

UserRepresentation user = AdminApiUtil.findClientByClientId(managedRealm.admin(), "service-account-cl").getServiceAccountUser();
user.setServiceAccountClientId("service-account-cl");
Expand All @@ -255,9 +257,6 @@ public void testImpersonationBySameRealmServiceAccount() throws Exception {

// test impersonation over the service account fails
testBadRequestImpersonation("impersonator", managedRealm.getName(), user.getId(), managedRealm.getName(), "Service accounts cannot be impersonated");

// Remove test client
AdminApiUtil.findClientByClientId(managedRealm.admin(), "service-account-cl").remove();
}
@Test
public void testImpersonationByMasterRealmServiceAccount() throws Exception {
Expand All @@ -267,7 +266,11 @@ public void testImpersonationByMasterRealmServiceAccount() throws Exception {
.secret("password")
.serviceAccountsEnabled(true)
.build();
masterRealm.admin().clients().create(clientApp);
String clientId;
try (Response response = masterRealm.admin().clients().create(clientApp)) {
clientId = ApiUtil.getCreatedId(response);
}
masterRealm.cleanup().add(r -> r.clients().get(clientId).remove());

UserRepresentation user = AdminApiUtil.findClientByClientId(masterRealm.admin(), "service-account-cl").getServiceAccountUser();
user.setServiceAccountClientId("service-account-cl");
Expand All @@ -277,9 +280,6 @@ public void testImpersonationByMasterRealmServiceAccount() throws Exception {

// Impersonation
testSuccessfulServiceAccountImpersonation(user, masterRealm.getName());

// Remove test client
AdminApiUtil.findClientByClientId(masterRealm.admin(), "service-account-cl").remove();
}

// Return the SSO cookie from the impersonated session
Expand All @@ -291,20 +291,27 @@ private Set<Cookie> testSuccessfulImpersonation(String admin, String adminRealm)
}
}

private Set<Cookie> extractIdentityCookies(BasicCookieStore cookieStore) {
return cookieStore.getCookies().stream()
.filter(c -> c.getName().startsWith(CookieType.IDENTITY.getName()))
.map(c -> new Cookie(c.getName(), c.getValue(), c.getDomain(), c.getPath(), c.getExpiryDate(), c.isSecure(), true))
.collect(Collectors.toSet());
}

private Set<Cookie> impersonate(Keycloak adminClient, String admin, String adminRealm) {
BasicCookieStore cookieStore = new BasicCookieStore();
try (CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build()) {

HttpUriRequest req = RequestBuilder.post()
.setUri(keycloakUrls.getBase() + "/admin/realms/test/users/" + managedUser.getId() + "/impersonation")
.setUri(keycloakUrls.getBase() + "/admin/realms/" + managedRealm.getName() + "/users/" + managedUser.getId() + "/impersonation")
.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + adminClient.tokenManager().getAccessTokenString())
.build();

HttpResponse res = httpClient.execute(req);
String resBody = EntityUtils.toString(res.getEntity());

Assertions.assertNotNull(resBody);
Assertions.assertTrue(resBody.contains("redirect"));
assertThat(resBody, notNullValue());
assertThat(resBody, containsString("redirect"));

EventRepresentation event = events.poll();
EventAssertion.assertSuccess(event)
Expand All @@ -320,23 +327,22 @@ private Set<Cookie> impersonate(Keycloak adminClient, String admin, String admin
final UserSessionNotesHolder notesHolder = runOnServer.fetch(session -> {
final RealmModel realm = session.realms().getRealmByName(testRealm);
final UserModel user = session.users().getUserById(realm, userId);
final UserSessionModel userSession = session.sessions().getUserSessionsStream(realm, user).filter(u -> u.getNotes().containsValue(admin)).findFirst().get();
final UserSessionModel userSession = session.sessions().getUserSessionsStream(realm, user)
.filter(u -> u.getNotes().containsValue(admin))
.findFirst()
.orElseThrow(() -> new IllegalStateException("No user session found with admin: " + admin));
return new UserSessionNotesHolder(userSession.getNotes());
}, UserSessionNotesHolder.class);

// Check impersonation details
final Map<String, String> notes = notesHolder.getNotes();
Assertions.assertNotNull(notes.get(ImpersonationSessionNote.IMPERSONATOR_ID.toString()));
Assertions.assertEquals(admin, notes.get(ImpersonationSessionNote.IMPERSONATOR_USERNAME.toString()));
assertThat(notes.get(ImpersonationSessionNote.IMPERSONATOR_ID.toString()), notNullValue());
assertThat(notes.get(ImpersonationSessionNote.IMPERSONATOR_USERNAME.toString()), is(admin));

Set<Cookie> cookies = cookieStore.getCookies().stream()
.filter(c -> c.getName().startsWith(CookieType.IDENTITY.getName()))
.map(c -> new Cookie(c.getName(), c.getValue(), c.getDomain(), c.getPath(), c.getExpiryDate(), c.isSecure(), true))
.collect(Collectors.toSet());
Set<Cookie> cookies = extractIdentityCookies(cookieStore);

Assertions.assertNotNull(cookies);
MatcherAssert.assertThat(cookies, is(not(empty())));
httpClient.close();
assertThat(cookies, notNullValue());
assertThat(cookies, not(empty()));

return cookies;
} catch (IOException e) {
Expand All @@ -349,7 +355,7 @@ private void testForbiddenImpersonation(String admin, String adminRealm) {
client.realms().realm(managedRealm.getName()).users().get(managedUser.getId()).impersonate();
Assertions.fail("Expected ClientErrorException wasn't thrown.");
} catch (ClientErrorException e) {
MatcherAssert.assertThat(e.getMessage(), containsString("403 Forbidden"));
assertThat(e.getMessage(), containsString("403 Forbidden"));
}
}

Expand All @@ -359,9 +365,9 @@ private void testBadRequestImpersonation(String admin, String adminRealm, String
client.realms().realm(impersonatedRealm).users().get(impersonatedId).impersonate();
Assertions.fail("Expected ClientErrorException wasn't thrown.");
} catch (ClientErrorException e) {
Assertions.assertEquals(Response.Status.BAD_REQUEST, e.getResponse().getStatusInfo());
assertThat(e.getResponse().getStatus(), is(Response.Status.BAD_REQUEST.getStatusCode()));
ErrorRepresentation error = e.getResponse().readEntity(ErrorRepresentation.class);
Assertions.assertEquals(errorExpected, error.getErrorMessage());
assertThat(error.getErrorMessage(), is(errorExpected));
}
}

Expand Down Expand Up @@ -421,23 +427,20 @@ private Set<Cookie> impersonateServiceAccount(Keycloak adminClient) {
try (CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build()) {

HttpUriRequest req = RequestBuilder.post()
.setUri(keycloakUrls.getBase() + "/admin/realms/test/users/" + managedUser.getId() + "/impersonation")
.setUri(keycloakUrls.getBase() + "/admin/realms/" + managedRealm.getName() + "/users/" + managedUser.getId() + "/impersonation")
.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + adminClient.tokenManager().getAccessTokenString())
.build();

HttpResponse res = httpClient.execute(req);
String resBody = EntityUtils.toString(res.getEntity());

Assertions.assertNotNull(resBody);
Assertions.assertTrue(resBody.contains("redirect"));
Set<Cookie> cookies = cookieStore.getCookies().stream()
.filter(c -> c.getName().startsWith(CookieType.IDENTITY.getName()))
.map(c -> new Cookie(c.getName(), c.getValue(), c.getDomain(), c.getPath(), c.getExpiryDate(), c.isSecure(), true))
.collect(Collectors.toSet());
assertThat(resBody, notNullValue());
assertThat(resBody, containsString("redirect"));

Set<Cookie> cookies = extractIdentityCookies(cookieStore);
Comment thread
jimmychakkalakal marked this conversation as resolved.
Resolved

Comment thread
jimmychakkalakal marked this conversation as resolved.
Resolved
Assertions.assertNotNull(cookies);
MatcherAssert.assertThat(cookies, is(not(empty())));
httpClient.close();
assertThat(cookies, notNullValue());
assertThat(cookies, not(empty()));

return cookies;
} catch (IOException e) {
Expand Down
Loading
0