Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add option to generate clound event request in HTTP Sender Even… #86

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ Configuration values:
| `backoffMaxInterval` | N | 60000 | Maximum back off time in milliseconds |
| `backoffMultiplier` | N | 1.5 | Multiplier value (E.g. 1.5 is 50% increase per back off) |
| `backoffRandomizationFactor` | N | 0.5 | Randomization factor (E.g. 0.5 results in a random period ranging between 50% below and 50% above the retry interval) |
| `cloudEventEnabled` | N | false | Generate a cloud event request to Http Server |

### Adding Configuration to your EventListenerProvider

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import org.apache.http.impl.client.HttpClients;
import org.keycloak.broker.provider.util.LegacySimpleHttp;
import org.keycloak.models.KeycloakSession;
import org.keycloak.representations.idm.AdminEventRepresentation;
import org.keycloak.representations.idm.EventRepresentation;
import org.keycloak.util.JsonSerialization;

@JBossLog
Expand All @@ -30,6 +32,7 @@ public class HttpSenderEventListenerProvider extends SenderEventListenerProvider
protected static final String BACKOFF_MAX_INTERVAL = "backoffMaxInterval";
protected static final String BACKOFF_MULTIPLIER = "backoffMultiplier";
protected static final String BACKOFF_RANDOMIZATION_FACTOR = "backoffRandomizationFactor";
protected static final String CLOUD_EVENTS_ENABLED = "cloudEventEnabled";

public HttpSenderEventListenerProvider(KeycloakSession session, ScheduledExecutorService exec) {
super(session, exec);
Expand All @@ -54,6 +57,10 @@ String getTargetUri() {
return config.get(TARGET_URI).toString();
}

Boolean getCloudEventsEnabled() {
return getBooleanOr(config, CLOUD_EVENTS_ENABLED, false);
}

Optional<String> getSharedSecret() {
return Optional.ofNullable(config.get(SHARED_SECRET)).map(Object::toString);
}
Expand All @@ -78,6 +85,32 @@ protected void send(
request.header(
"X-Keycloak-Signature",
hmacFor(task.getEvent(), secret, algorithm.orElse(HMAC_SHA256_ALGORITHM))));

if (getCloudEventsEnabled()) {
Object eventObject = null;
eventObject = task.getEvent();
if (eventObject instanceof EventRepresentation) {
EventRepresentation event = (EventRepresentation) eventObject;
request
.header("content-type", "application/json")
.header("ce-specversion", "1.0")
.header("ce-source", "keycloak")
.header("ce-type", event.getType())
.header("ce-id", event.getRealmId() + "-" + event.getTime())
.header("ce-partitionkey", event.getRealmId());

} else {
AdminEventRepresentation event = (AdminEventRepresentation) eventObject;
request
.header("content-type", "application/json")
.header("ce-specversion", "1.0")
.header("ce-source", "keycloak")
.header("ce-type", event.getOperationType() + "-" + event.getResourceType())
.header("ce-id", event.getRealmId() + "-" + event.getTime())
.header("ce-partitionkey", event.getRealmId());
}
}

LegacySimpleHttp.Response response = request.asResponse();
int status = response.getStatus();
log.debugf("sent to %s (%d)", targetUri, status);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ private ExtendedAdminEvent completeAdminEventAttributes(String uid, Event event)
private ExtendedAdminEvent completeAdminEventAttributes(String uid, AdminEvent adminEvent) {
RealmModel eventRealm = session.realms().getRealm(adminEvent.getRealmId());
RealmModel authRealm = session.realms().getRealm(adminEvent.getAuthDetails().getRealmId());
ExtendedAdminEvent extendedAdminEvent = new ExtendedAdminEvent(uid, adminEvent, eventRealm, authRealm);
ExtendedAdminEvent extendedAdminEvent =
new ExtendedAdminEvent(uid, adminEvent, eventRealm, authRealm);
// add always missing agent username
ExtendedAuthDetails extendedAuthDetails = extendedAdminEvent.getAuthDetails();
if (!Strings.isNullOrEmpty(extendedAuthDetails.getUserId())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ private static String createType(Event event) {

public ExtendedAdminEvent() {}

public ExtendedAdminEvent(String uid, AdminEvent event, RealmModel eventRealm, RealmModel authRealm) {
public ExtendedAdminEvent(
String uid, AdminEvent event, RealmModel eventRealm, RealmModel authRealm) {
this.uid = uid;
this.type = createType(event);

Expand Down
19 changes: 8 additions & 11 deletions src/test/java/io/phasetwo/keycloak/Helpers.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,15 @@ public static String createWebhook(
}

public static void removeWebhook(
Keycloak keycloak,
CloseableHttpClient httpClient,
String baseUrl,
String webhookId)
throws Exception {
Keycloak keycloak, CloseableHttpClient httpClient, String baseUrl, String webhookId)
throws Exception {

LegacySimpleHttp.Response response =
LegacySimpleHttp.doDelete(baseUrl + "/" + webhookId, httpClient)
.auth(keycloak.tokenManager().getAccessTokenString())
.asResponse();
assertThat(response.getStatus(), is(204));
}
LegacySimpleHttp.Response response =
LegacySimpleHttp.doDelete(baseUrl + "/" + webhookId, httpClient)
.auth(keycloak.tokenManager().getAccessTokenString())
.asResponse();
assertThat(response.getStatus(), is(204));
}

public static String urlencode(String u) {
try {
Expand Down
Loading