parent
f55794f8bf
commit
409e1c3581
8 changed files with 500 additions and 27 deletions
|
@ -30,35 +30,29 @@
|
|||
<name>Keycloak Authz: Policy Enforcer</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<jakarta.servlet.version>6.0.0</jakarta.servlet.version>
|
||||
<wildfly-elytron.version>2.0.0.Final</wildfly-elytron.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Built-in Elytron/Jakarta Servlet integration -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>${jakarta.servlet.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<groupId>org.wildfly.security</groupId>
|
||||
<artifactId>wildfly-elytron-http-oidc</artifactId>
|
||||
<version>${wildfly-elytron.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
|
|
@ -82,7 +82,25 @@ public class PolicyEnforcer {
|
|||
|
||||
protected PolicyEnforcer(Builder builder) {
|
||||
enforcerConfig = builder.getEnforcerConfig();
|
||||
authzClient = AuthzClient.create(builder.authzClientConfig);
|
||||
Configuration authzClientConfig = builder.authzClientConfig;
|
||||
|
||||
if (authzClientConfig.getRealm() == null) {
|
||||
authzClientConfig.setRealm(enforcerConfig.getRealm());
|
||||
}
|
||||
|
||||
if (authzClientConfig.getAuthServerUrl() == null) {
|
||||
authzClientConfig.setAuthServerUrl(enforcerConfig.getAuthServerUrl());
|
||||
}
|
||||
|
||||
if (authzClientConfig.getCredentials() == null || authzClientConfig.getCredentials().isEmpty()) {
|
||||
authzClientConfig.setCredentials(enforcerConfig.getCredentials());
|
||||
}
|
||||
|
||||
if (authzClientConfig.getResource() == null) {
|
||||
authzClientConfig.setResource(enforcerConfig.getResource());
|
||||
}
|
||||
|
||||
authzClient = AuthzClient.create(authzClientConfig);
|
||||
httpClient = authzClient.getConfiguration().getHttpClient();
|
||||
pathMatcher = new PathConfigMatcher(builder.getEnforcerConfig(), authzClient);
|
||||
paths = pathMatcher.getPathConfig();
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
package org.keycloak.adapters.authorization.integration.elytron;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.FilterConfig;
|
||||
import jakarta.servlet.ServletContextAttributeListener;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import jakarta.servlet.ServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.AuthorizationContext;
|
||||
import org.keycloak.adapters.authorization.PolicyEnforcer;
|
||||
import org.keycloak.adapters.authorization.TokenPrincipal;
|
||||
import org.keycloak.adapters.authorization.spi.ConfigurationResolver;
|
||||
import org.keycloak.adapters.authorization.spi.HttpRequest;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||
import org.wildfly.security.http.oidc.OidcClientConfiguration;
|
||||
import org.wildfly.security.http.oidc.OidcPrincipal;
|
||||
import org.wildfly.security.http.oidc.RefreshableOidcSecurityContext;
|
||||
|
||||
/**
|
||||
* A {@link Filter} acting as a policy enforcer. This filter does not enforce access for anonymous subjects.</p>
|
||||
*
|
||||
* For authenticated subjects, this filter delegates the access decision to the {@link PolicyEnforcer} and decide if
|
||||
* the request should continue.</p>
|
||||
*
|
||||
* If access is not granted, this filter aborts the request and relies on the {@link PolicyEnforcer} to properly
|
||||
* respond to client.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class PolicyEnforcerFilter implements Filter, ServletContextAttributeListener {
|
||||
|
||||
private final Logger logger = Logger.getLogger(getClass());
|
||||
private final Map<PolicyEnforcerConfig, PolicyEnforcer> policyEnforcer;
|
||||
private final ConfigurationResolver configResolver;
|
||||
|
||||
public PolicyEnforcerFilter(ConfigurationResolver configResolver) {
|
||||
this.configResolver = configResolver;
|
||||
this.policyEnforcer = Collections.synchronizedMap(new HashMap<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) {
|
||||
// no-init
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
HttpSession session = request.getSession(false);
|
||||
|
||||
if (session == null) {
|
||||
logger.debug("Anonymous request, continuing the filter chain");
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
RefreshableOidcSecurityContext securityContext = (RefreshableOidcSecurityContext) ((OidcPrincipal) request.getUserPrincipal()).getOidcSecurityContext();
|
||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
String accessToken = securityContext.getTokenString();
|
||||
ServletHttpRequest httpRequest = new ServletHttpRequest(request, new TokenPrincipal() {
|
||||
@Override
|
||||
public String getRawToken() {
|
||||
return accessToken;
|
||||
}
|
||||
});
|
||||
|
||||
PolicyEnforcer policyEnforcer = getOrCreatePolicyEnforcer(httpRequest, securityContext);
|
||||
AuthorizationContext authzContext = policyEnforcer.enforce(httpRequest, new ServletHttpResponse(response));
|
||||
|
||||
request.setAttribute(AuthorizationContext.class.getName(), authzContext);
|
||||
|
||||
if (authzContext.isGranted()) {
|
||||
logger.debug("Request authorized, continuing the filter chain");
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
} else {
|
||||
logger.debugf("Unauthorized request to path [%s], aborting the filter chain", request.getRequestURI());
|
||||
}
|
||||
}
|
||||
|
||||
private PolicyEnforcer getOrCreatePolicyEnforcer(HttpRequest request, RefreshableOidcSecurityContext securityContext) {
|
||||
return policyEnforcer.computeIfAbsent(configResolver.resolve(request), new Function<PolicyEnforcerConfig, PolicyEnforcer>() {
|
||||
@Override
|
||||
public PolicyEnforcer apply(PolicyEnforcerConfig enforcerConfig) {
|
||||
OidcClientConfiguration configuration = securityContext.getOidcClientConfiguration();
|
||||
String authServerUrl = configuration.getAuthServerBaseUrl();
|
||||
|
||||
return PolicyEnforcer.builder()
|
||||
.authServerUrl(authServerUrl)
|
||||
.realm(configuration.getRealm())
|
||||
.clientId(configuration.getClientId())
|
||||
.credentials(configuration.getResourceCredentials())
|
||||
.bearerOnly(false)
|
||||
.enforcerConfig(enforcerConfig)
|
||||
.httpClient(configuration.getClient()).build();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package org.keycloak.adapters.authorization.integration.elytron;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import jakarta.servlet.ServletContext;
|
||||
import jakarta.servlet.ServletContextEvent;
|
||||
import jakarta.servlet.ServletContextListener;
|
||||
import jakarta.servlet.annotation.WebListener;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.authorization.spi.ConfigurationResolver;
|
||||
import org.keycloak.adapters.authorization.spi.HttpRequest;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
/**
|
||||
* A {@link ServletContextListener} to programmatically configure the {@link ServletContext} in order to
|
||||
* enable the policy enforcer.</p>
|
||||
*
|
||||
* By default, the policy enforcer configuration is loaded from a file at {@code WEB-INF/policy-enforcer.json}.</p>
|
||||
*
|
||||
* Applications can also dynamically resolve the configuration by implementing the {@link ConfigurationResolver} SPI. For that,
|
||||
* make sure to create a {@link META-INF/services/org.keycloak.adapters.authorization.spi.ConfigurationResolver} to register
|
||||
* the implementation.
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
@WebListener
|
||||
public class PolicyEnforcerServletContextListener implements ServletContextListener {
|
||||
|
||||
private final Logger logger = Logger.getLogger(getClass());
|
||||
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent sce) {
|
||||
ServletContext servletContext = sce.getServletContext();
|
||||
Iterator<ConfigurationResolver> configResolvers = ServiceLoader.load(ConfigurationResolver.class).iterator();
|
||||
ConfigurationResolver configResolver;
|
||||
|
||||
if (configResolvers.hasNext()) {
|
||||
configResolver = configResolvers.next();
|
||||
|
||||
if (configResolvers.hasNext()) {
|
||||
throw new IllegalStateException("Multiple " + ConfigurationResolver.class.getName() + " implementations found");
|
||||
}
|
||||
|
||||
logger.debugf("Configuration resolver found from classpath: %s", configResolver);
|
||||
} else {
|
||||
String enforcerConfigLocation = "WEB-INF/policy-enforcer.json";
|
||||
InputStream config = servletContext.getResourceAsStream(enforcerConfigLocation);
|
||||
|
||||
if (config == null) {
|
||||
logger.debugf("Could not find the policy enforcer configuration file: %s", enforcerConfigLocation);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
configResolver = createDefaultConfigurationResolver(JsonSerialization.readValue(config, PolicyEnforcerConfig.class));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to parse policy enforcer configuration: " + enforcerConfigLocation);
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("Policy enforcement filter is enabled.");
|
||||
|
||||
servletContext.addFilter("keycloak-policy-enforcer", new PolicyEnforcerFilter(configResolver))
|
||||
.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*");
|
||||
}
|
||||
|
||||
private ConfigurationResolver createDefaultConfigurationResolver(PolicyEnforcerConfig enforcerConfig) {
|
||||
return new ConfigurationResolver() {
|
||||
@Override
|
||||
public PolicyEnforcerConfig resolve(HttpRequest request) {
|
||||
return enforcerConfig;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright 2023 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.authorization.integration.elytron;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.keycloak.adapters.authorization.TokenPrincipal;
|
||||
import org.keycloak.adapters.authorization.spi.HttpRequest;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ServletHttpRequest implements HttpRequest {
|
||||
|
||||
private final HttpServletRequest request;
|
||||
private final TokenPrincipal tokenPrincipal;
|
||||
private InputStream inputStream;
|
||||
|
||||
public ServletHttpRequest(HttpServletRequest request, TokenPrincipal tokenPrincipal) {
|
||||
this.request = request;
|
||||
this.tokenPrincipal = tokenPrincipal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRelativePath() {
|
||||
return request.getServletPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return request.getMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getURI() {
|
||||
return request.getRequestURI();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getHeaders(String name) {
|
||||
return Collections.list(request.getHeaders(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstParam(String name) {
|
||||
Map<String, String[]> parameters = request.getParameterMap();
|
||||
String[] values = parameters.get(name);
|
||||
|
||||
if (values == null || values.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return values[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCookieValue(String name) {
|
||||
Cookie[] cookies = request.getCookies();
|
||||
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie.getName().equals(name)) {
|
||||
return cookie.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteAddr() {
|
||||
return request.getRemoteAddr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return request.isSecure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String name) {
|
||||
return request.getHeader(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream(boolean buffered) {
|
||||
if (inputStream != null) {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
if (buffered) {
|
||||
try {
|
||||
return inputStream = new BufferedInputStream(request.getInputStream());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return request.getInputStream();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TokenPrincipal getPrincipal() {
|
||||
return tokenPrincipal;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright 2023 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.authorization.integration.elytron;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.keycloak.adapters.authorization.spi.HttpResponse;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class ServletHttpResponse implements HttpResponse {
|
||||
|
||||
private HttpServletResponse response;
|
||||
|
||||
public ServletHttpResponse(HttpServletResponse response) {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(int status) {
|
||||
try {
|
||||
response.sendError(status);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(int status, String reason) {
|
||||
try {
|
||||
response.sendError(status, reason);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeader(String name, String value) {
|
||||
response.setHeader(name, value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2023 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.authorization.spi;
|
||||
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||
|
||||
/**
|
||||
* Resolves a {@link PolicyEnforcerConfig} based on the information from the {@link HttpRequest}.</p>
|
||||
*
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public interface ConfigurationResolver {
|
||||
|
||||
/**
|
||||
* Resolves a {@link PolicyEnforcerConfig} based on the information from the {@link HttpRequest}.
|
||||
*
|
||||
* @param request the request
|
||||
* @return the policy enforcer configuration for the given request
|
||||
*/
|
||||
PolicyEnforcerConfig resolve(HttpRequest request);
|
||||
}
|
|
@ -23,12 +23,14 @@ import java.util.Map;
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.keycloak.representations.idm.authorization.ResourceRepresentation;
|
||||
import org.keycloak.representations.idm.authorization.ScopeRepresentation;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
|
@ -39,31 +41,42 @@ public class PolicyEnforcerConfig {
|
|||
private EnforcementMode enforcementMode = EnforcementMode.ENFORCING;
|
||||
|
||||
@JsonProperty("paths")
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@JsonInclude(Include.NON_EMPTY)
|
||||
private List<PathConfig> paths = new ArrayList<>();
|
||||
|
||||
@JsonProperty("path-cache")
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
@JsonInclude(Include.NON_EMPTY)
|
||||
private PathCacheConfig pathCacheConfig;
|
||||
|
||||
@JsonProperty("lazy-load-paths")
|
||||
private Boolean lazyLoadPaths = Boolean.FALSE;
|
||||
|
||||
@JsonProperty("on-deny-redirect-to")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
private String onDenyRedirectTo;
|
||||
|
||||
@JsonProperty("user-managed-access")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
private UserManagedAccessConfig userManagedAccess;
|
||||
|
||||
@JsonProperty("claim-information-point")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
private Map<String, Map<String, Object>> claimInformationPointConfig;
|
||||
|
||||
@JsonProperty("http-method-as-scope")
|
||||
private Boolean httpMethodAsScope;
|
||||
|
||||
private String realm;
|
||||
|
||||
@JsonProperty("auth-server-url")
|
||||
private String authServerUrl;
|
||||
|
||||
@JsonProperty("credentials")
|
||||
protected Map<String, Object> credentials = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
@JsonProperty("resource")
|
||||
private String resource;
|
||||
|
||||
public List<PathConfig> getPaths() {
|
||||
return this.paths;
|
||||
}
|
||||
|
@ -128,6 +141,38 @@ public class PolicyEnforcerConfig {
|
|||
this.httpMethodAsScope = httpMethodAsScope;
|
||||
}
|
||||
|
||||
public String getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
public void setRealm(String realm) {
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
public String getAuthServerUrl() {
|
||||
return authServerUrl;
|
||||
}
|
||||
|
||||
public void setAuthServerUrl(String authServerUrl) {
|
||||
this.authServerUrl = authServerUrl;
|
||||
}
|
||||
|
||||
public Map<String, Object> getCredentials() {
|
||||
return credentials;
|
||||
}
|
||||
|
||||
public void setCredentials(Map<String, Object> credentials) {
|
||||
this.credentials = credentials;
|
||||
}
|
||||
|
||||
public String getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void setResource(String resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public static class PathConfig {
|
||||
|
||||
public static Set<PathConfig> createPathConfigs(ResourceRepresentation resourceDescription) {
|
||||
|
|
Loading…
Reference in a new issue