Use java http client because keycloak api in incompatible
This commit is contained in:
parent
07ece7e10f
commit
3e54614037
4 changed files with 55 additions and 34 deletions
2
.github/workflows/pr.yaml
vendored
2
.github/workflows/pr.yaml
vendored
|
@ -49,7 +49,7 @@ jobs:
|
||||||
version:
|
version:
|
||||||
- 21.0.2
|
- 21.0.2
|
||||||
- 21.1.2
|
- 21.1.2
|
||||||
- 22.0.2
|
- 22.0.3
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-java@v3
|
- uses: actions/setup-java@v3
|
||||||
|
|
|
@ -3,7 +3,7 @@ package io.kokuwa.keycloak.metrics;
|
||||||
import static org.junit.jupiter.api.Assertions.assertAll;
|
import static org.junit.jupiter.api.Assertions.assertAll;
|
||||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
@ -18,6 +18,7 @@ import org.keycloak.events.EventType;
|
||||||
import io.kokuwa.keycloak.metrics.junit.KeycloakClient;
|
import io.kokuwa.keycloak.metrics.junit.KeycloakClient;
|
||||||
import io.kokuwa.keycloak.metrics.junit.KeycloakExtension;
|
import io.kokuwa.keycloak.metrics.junit.KeycloakExtension;
|
||||||
import io.kokuwa.keycloak.metrics.junit.Prometheus;
|
import io.kokuwa.keycloak.metrics.junit.Prometheus;
|
||||||
|
import jakarta.ws.rs.NotAuthorizedException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Integration tests with Keycloak.
|
* Integration tests with Keycloak.
|
||||||
|
@ -55,10 +56,10 @@ public class KeycloakIT {
|
||||||
var loginErrorBefore1 = prometheus.userEvent(EventType.LOGIN_ERROR, realmName1, clientId1);
|
var loginErrorBefore1 = prometheus.userEvent(EventType.LOGIN_ERROR, realmName1, clientId1);
|
||||||
var loginErrorBefore2 = prometheus.userEvent(EventType.LOGIN_ERROR, realmName2, clientId2);
|
var loginErrorBefore2 = prometheus.userEvent(EventType.LOGIN_ERROR, realmName2, clientId2);
|
||||||
|
|
||||||
assertTrue(keycloak.login(clientId1, realmName1, username1, password1));
|
assertDoesNotThrow(() -> keycloak.login(clientId1, realmName1, username1, password1));
|
||||||
assertTrue(keycloak.login(clientId1, realmName1, username1, password1));
|
assertDoesNotThrow(() -> keycloak.login(clientId1, realmName1, username1, password1));
|
||||||
assertTrue(keycloak.login(clientId2, realmName2, username2, password2));
|
assertDoesNotThrow(() -> keycloak.login(clientId2, realmName2, username2, password2));
|
||||||
assertFalse(keycloak.login(clientId2, realmName2, username2, "nope"));
|
assertThrows(NotAuthorizedException.class, () -> keycloak.login(clientId2, realmName2, username2, "nope"));
|
||||||
|
|
||||||
prometheus.scrap();
|
prometheus.scrap();
|
||||||
var loginAfter = prometheus.userEvent(EventType.LOGIN);
|
var loginAfter = prometheus.userEvent(EventType.LOGIN);
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
package io.kokuwa.keycloak.metrics.junit;
|
package io.kokuwa.keycloak.metrics.junit;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpRequest.BodyPublishers;
|
||||||
|
import java.net.http.HttpResponse.BodyHandlers;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -9,12 +16,16 @@ import java.util.UUID;
|
||||||
import org.keycloak.OAuth2Constants;
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.admin.client.Keycloak;
|
import org.keycloak.admin.client.Keycloak;
|
||||||
import org.keycloak.admin.client.token.TokenService;
|
import org.keycloak.admin.client.token.TokenService;
|
||||||
|
import org.keycloak.representations.AccessTokenResponse;
|
||||||
import org.keycloak.representations.idm.ClientRepresentation;
|
import org.keycloak.representations.idm.ClientRepresentation;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
|
||||||
import jakarta.ws.rs.NotAuthorizedException;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import jakarta.ws.rs.core.HttpHeaders;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
import jakarta.ws.rs.core.MultivaluedHashMap;
|
import jakarta.ws.rs.core.MultivaluedHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,11 +36,18 @@ import jakarta.ws.rs.core.MultivaluedHashMap;
|
||||||
public class KeycloakClient {
|
public class KeycloakClient {
|
||||||
|
|
||||||
private final Keycloak keycloak;
|
private final Keycloak keycloak;
|
||||||
private final TokenService token;
|
private final TokenService tokenService;
|
||||||
|
|
||||||
KeycloakClient(Keycloak keycloak, TokenService token) {
|
private final ObjectMapper mapper = new ObjectMapper();
|
||||||
|
private final HttpClient client = HttpClient.newHttpClient();
|
||||||
|
private final String url;
|
||||||
|
private final String adminToken;
|
||||||
|
|
||||||
|
KeycloakClient(String url, Keycloak keycloak, TokenService tokenService) {
|
||||||
this.keycloak = keycloak;
|
this.keycloak = keycloak;
|
||||||
this.token = token;
|
this.tokenService = tokenService;
|
||||||
|
this.url = url;
|
||||||
|
this.adminToken = login("admin-cli", "master", "admin", "password").getToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createRealm(String realmName) {
|
public void createRealm(String realmName) {
|
||||||
|
@ -52,18 +70,25 @@ public class KeycloakClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createUser(String realmName, String username, String password) {
|
public void createUser(String realmName, String username, String password) {
|
||||||
var credential = new CredentialRepresentation();
|
try {
|
||||||
credential.setType(CredentialRepresentation.PASSWORD);
|
var response = client.send(HttpRequest.newBuilder()
|
||||||
credential.setValue(password);
|
.uri(URI.create(url + "/admin/realms/" + realmName + "/users"))
|
||||||
credential.setTemporary(false);
|
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON)
|
||||||
var user = new UserRepresentation();
|
.header(HttpHeaders.AUTHORIZATION, "Bearer " + adminToken)
|
||||||
user.setEnabled(true);
|
.POST(BodyPublishers.ofString(mapper.writeValueAsString(Map.of(
|
||||||
user.setEmail(username + "@example.org");
|
"enabled", true,
|
||||||
user.setEmailVerified(true);
|
"emailVerified", true,
|
||||||
user.setUsername(username);
|
"email", username + "@example.org",
|
||||||
user.setCredentials(List.of(credential));
|
"username", username,
|
||||||
var response = keycloak.realms().realm(realmName).users().create(user);
|
"credentials", List.of(Map.of(
|
||||||
assertEquals(201, response.getStatus());
|
"type", CredentialRepresentation.PASSWORD,
|
||||||
|
"value", password,
|
||||||
|
"temporary", false))))))
|
||||||
|
.build(), BodyHandlers.ofString());
|
||||||
|
assertEquals(201, response.statusCode(), "Body: " + response.body());
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
fail("Failed to create user", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteUser(String realmName, String username) {
|
public void deleteUser(String realmName, String username) {
|
||||||
|
@ -73,16 +98,11 @@ public class KeycloakClient {
|
||||||
.forEach(keycloak.realms().realm(realmName).users()::delete);
|
.forEach(keycloak.realms().realm(realmName).users()::delete);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean login(String clientId, String realmName, String username, String password) {
|
public AccessTokenResponse login(String clientId, String realmName, String username, String password) {
|
||||||
try {
|
return tokenService.grantToken(realmName, new MultivaluedHashMap<>(Map.of(
|
||||||
token.grantToken(realmName, new MultivaluedHashMap<>(Map.of(
|
|
||||||
OAuth2Constants.CLIENT_ID, clientId,
|
OAuth2Constants.CLIENT_ID, clientId,
|
||||||
OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD,
|
OAuth2Constants.GRANT_TYPE, OAuth2Constants.PASSWORD,
|
||||||
OAuth2Constants.USERNAME, username,
|
OAuth2Constants.USERNAME, username,
|
||||||
OAuth2Constants.PASSWORD, password)));
|
OAuth2Constants.PASSWORD, password)));
|
||||||
return true;
|
|
||||||
} catch (NotAuthorizedException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ public class KeycloakExtension implements BeforeAllCallback, ParameterResolver {
|
||||||
var target = ClientBuilder.newClient().target(url);
|
var target = ClientBuilder.newClient().target(url);
|
||||||
var token = Keycloak.getClientProvider().targetProxy(target, TokenService.class);
|
var token = Keycloak.getClientProvider().targetProxy(target, TokenService.class);
|
||||||
prometheus = new Prometheus(Keycloak.getClientProvider().targetProxy(target, PrometheusClient.class));
|
prometheus = new Prometheus(Keycloak.getClientProvider().targetProxy(target, PrometheusClient.class));
|
||||||
client = new KeycloakClient(keycloak, token);
|
client = new KeycloakClient(url, keycloak, token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue