Skip to content

Commit

Permalink
Merge pull request #15955 from sberyozkin/keycloak_authz_synthetic_bean
Browse files Browse the repository at this point in the history
Update KeycloakPolicyEnforcerAuthorizer to init in a PostConstruct method
  • Loading branch information
sberyozkin authored Mar 24, 2021
2 parents 7029f79 + 5ad3f65 commit 1b5614a
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import java.util.Map;

import javax.inject.Singleton;

import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.arc.deployment.BeanContainerBuildItem;
import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
import io.quarkus.deployment.Feature;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
Expand All @@ -12,6 +14,7 @@
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.keycloak.pep.runtime.KeycloakPolicyEnforcerAuthorizer;
import io.quarkus.keycloak.pep.runtime.KeycloakPolicyEnforcerConfig;
import io.quarkus.keycloak.pep.runtime.KeycloakPolicyEnforcerConfigBean;
import io.quarkus.keycloak.pep.runtime.KeycloakPolicyEnforcerRecorder;
import io.quarkus.oidc.runtime.OidcBuildTimeConfig;
import io.quarkus.oidc.runtime.OidcConfig;
Expand Down Expand Up @@ -72,11 +75,18 @@ ExtensionSslNativeSupportBuildItem enableSslInNative() {

@Record(ExecutionTime.RUNTIME_INIT)
@BuildStep
public void setup(OidcBuildTimeConfig oidcBuildTimeConfig, OidcConfig oidcRunTimeConfig, TlsConfig tlsConfig,
KeycloakPolicyEnforcerConfig keycloakConfig, KeycloakPolicyEnforcerRecorder recorder, BeanContainerBuildItem bc,
public SyntheticBeanBuildItem setup(OidcBuildTimeConfig oidcBuildTimeConfig, OidcConfig oidcRunTimeConfig,
TlsConfig tlsConfig,
KeycloakPolicyEnforcerConfig keycloakConfig, KeycloakPolicyEnforcerRecorder recorder,
HttpConfiguration httpConfiguration) {
if (oidcBuildTimeConfig.enabled && keycloakConfig.policyEnforcer.enable) {
recorder.setup(oidcRunTimeConfig, keycloakConfig, tlsConfig, bc.getValue(), httpConfiguration);
return SyntheticBeanBuildItem.configure(KeycloakPolicyEnforcerConfigBean.class).unremovable()
.types(KeycloakPolicyEnforcerConfigBean.class)
.supplier(recorder.setup(oidcRunTimeConfig, keycloakConfig, tlsConfig, httpConfiguration))
.scope(Singleton.class)
.setRuntimeInit()
.done();
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Singleton;

import org.jboss.logging.Logger;
import org.keycloak.AuthorizationContext;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
import org.keycloak.adapters.authorization.KeycloakAdapterPolicyEnforcer;
Expand All @@ -20,23 +21,19 @@

import io.quarkus.oidc.OidcTenantConfig;
import io.quarkus.oidc.common.runtime.OidcCommonConfig.Tls.Verification;
import io.quarkus.oidc.runtime.OidcConfig;
import io.quarkus.runtime.TlsConfig;
import io.quarkus.security.AuthenticationFailedException;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.security.runtime.QuarkusSecurityIdentity;
import io.quarkus.vertx.http.runtime.HttpConfiguration;
import io.quarkus.vertx.http.runtime.security.HttpSecurityPolicy;
import io.smallrye.mutiny.Uni;
import io.vertx.ext.web.RoutingContext;

@Singleton
public class KeycloakPolicyEnforcerAuthorizer
implements HttpSecurityPolicy, BiFunction<RoutingContext, SecurityIdentity, HttpSecurityPolicy.CheckResult> {
private static final Logger LOG = Logger.getLogger(KeycloakPolicyEnforcerAuthorizer.class);

private volatile KeycloakAdapterPolicyEnforcer delegate;
private volatile long readTimeout;
@Inject
KeycloakPolicyEnforcerConfigBean configBean;
private KeycloakAdapterPolicyEnforcer delegate;

@Override
public Uni<CheckResult> checkPermission(RoutingContext request, Uni<SecurityIdentity> identity,
Expand All @@ -46,12 +43,8 @@ public Uni<CheckResult> checkPermission(RoutingContext request, Uni<SecurityIden

@Override
public CheckResult apply(RoutingContext routingContext, SecurityIdentity identity) {
if (delegate == null) {
LOG.debug(
"Keycloak Policy Enforcer has not been initialized - please make sure 'quarkus.oidc.enabled' is not set to 'false'");
throw new AuthenticationFailedException();
}
VertxHttpFacade httpFacade = new VertxHttpFacade(routingContext, readTimeout);
VertxHttpFacade httpFacade = new VertxHttpFacade(routingContext,
configBean.httpConfiguration.readTimeout.toMillis());
AuthorizationContext result = delegate.authorize(httpFacade);

if (result.isGranted()) {
Expand Down Expand Up @@ -99,10 +92,10 @@ public Uni<Boolean> apply(Permission permission) {
}).build();
}

public void init(OidcConfig oidcConfig, KeycloakPolicyEnforcerConfig config, TlsConfig tlsConfig,
HttpConfiguration httpConfiguration) {
@PostConstruct
public void init() {
AdapterConfig adapterConfig = new AdapterConfig();
String authServerUrl = oidcConfig.defaultTenant.getAuthServerUrl().get();
String authServerUrl = configBean.oidcConfig.defaultTenant.getAuthServerUrl().get();

try {
adapterConfig.setRealm(authServerUrl.substring(authServerUrl.lastIndexOf('/') + 1));
Expand All @@ -111,30 +104,31 @@ public void init(OidcConfig oidcConfig, KeycloakPolicyEnforcerConfig config, Tls
throw new RuntimeException("Failed to parse the realm name.", cause);
}

adapterConfig.setResource(oidcConfig.defaultTenant.getClientId().get());
adapterConfig.setCredentials(getCredentials(oidcConfig.defaultTenant));
adapterConfig.setResource(configBean.oidcConfig.defaultTenant.getClientId().get());
adapterConfig.setCredentials(getCredentials(configBean.oidcConfig.defaultTenant));

boolean trustAll = oidcConfig.defaultTenant.tls.getVerification().isPresent()
? oidcConfig.defaultTenant.tls.getVerification().get() == Verification.NONE
: tlsConfig.trustAll;
boolean trustAll = configBean.oidcConfig.defaultTenant.tls.getVerification().isPresent()
? configBean.oidcConfig.defaultTenant.tls.getVerification().get() == Verification.NONE
: configBean.tlsConfig.trustAll;
if (trustAll) {
adapterConfig.setDisableTrustManager(true);
adapterConfig.setAllowAnyHostname(true);
}

if (oidcConfig.defaultTenant.proxy.host.isPresent()) {
adapterConfig.setProxyUrl(oidcConfig.defaultTenant.proxy.host.get() + ":" + oidcConfig.defaultTenant.proxy.port);
if (configBean.oidcConfig.defaultTenant.proxy.host.isPresent()) {
adapterConfig.setProxyUrl(configBean.oidcConfig.defaultTenant.proxy.host.get() + ":"
+ configBean.oidcConfig.defaultTenant.proxy.port);
}

PolicyEnforcerConfig enforcerConfig = getPolicyEnforcerConfig(config, adapterConfig);
PolicyEnforcerConfig enforcerConfig = getPolicyEnforcerConfig(configBean.keycloakPolicyEnforcerConfig,
adapterConfig);

if (enforcerConfig == null) {
return;
}

adapterConfig.setPolicyEnforcerConfig(enforcerConfig);

this.readTimeout = httpConfiguration.readTimeout.toMillis();
this.delegate = new KeycloakAdapterPolicyEnforcer(
new PolicyEnforcer(KeycloakDeploymentBuilder.build(adapterConfig), adapterConfig));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.quarkus.keycloak.pep.runtime;

import io.quarkus.oidc.runtime.OidcConfig;
import io.quarkus.runtime.TlsConfig;
import io.quarkus.vertx.http.runtime.HttpConfiguration;

public class KeycloakPolicyEnforcerConfigBean {

final OidcConfig oidcConfig;
final KeycloakPolicyEnforcerConfig keycloakPolicyEnforcerConfig;
final TlsConfig tlsConfig;
final HttpConfiguration httpConfiguration;

public KeycloakPolicyEnforcerConfigBean(OidcConfig oidcConfig, KeycloakPolicyEnforcerConfig keycloakPolicyEnforcerConfig,
TlsConfig tlsConfig,
HttpConfiguration httpConfiguration) {
this.oidcConfig = oidcConfig;
this.keycloakPolicyEnforcerConfig = keycloakPolicyEnforcerConfig;
this.tlsConfig = tlsConfig;
this.httpConfiguration = httpConfiguration;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkus.keycloak.pep.runtime;

import io.quarkus.arc.runtime.BeanContainer;
import java.util.function.Supplier;

import io.quarkus.oidc.OIDCException;
import io.quarkus.oidc.OidcTenantConfig;
import io.quarkus.oidc.runtime.OidcConfig;
Expand All @@ -11,12 +12,16 @@
@Recorder
public class KeycloakPolicyEnforcerRecorder {

public void setup(OidcConfig oidcConfig, KeycloakPolicyEnforcerConfig config, TlsConfig tlsConfig,
BeanContainer beanContainer,
HttpConfiguration httpConfiguration) {
public Supplier<KeycloakPolicyEnforcerConfigBean> setup(OidcConfig oidcConfig, KeycloakPolicyEnforcerConfig config,
TlsConfig tlsConfig, HttpConfiguration httpConfiguration) {
if (oidcConfig.defaultTenant.applicationType == OidcTenantConfig.ApplicationType.WEB_APP) {
throw new OIDCException("Application type [" + oidcConfig.defaultTenant.applicationType + "] is not supported");
}
beanContainer.instance(KeycloakPolicyEnforcerAuthorizer.class).init(oidcConfig, config, tlsConfig, httpConfiguration);
return new Supplier<KeycloakPolicyEnforcerConfigBean>() {
@Override
public KeycloakPolicyEnforcerConfigBean get() {
return new KeycloakPolicyEnforcerConfigBean(oidcConfig, config, tlsConfig, httpConfiguration);
}
};
}
}

0 comments on commit 1b5614a

Please sign in to comment.