Skip to content

Commit

Permalink
add support for azure keyvault and tomcat filters
Browse files Browse the repository at this point in the history
  • Loading branch information
SavvasMisaghMoayyed committed Dec 9, 2017
1 parent 21f3e32 commit 005c5ab
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 538 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public class HttpRequestProperties implements Serializable {
*/
@NestedConfigurationProperty
private HttpCorsRequestProperties cors = new HttpCorsRequestProperties();

public boolean isAllowMultiValueParameters() {
return allowMultiValueParameters;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
description = "Apereo CAS Core Configuration - Microsoft Azure KeyVault"
dependencies {
implementation libraries.azurekeyvault
implementation project(":core:cas-server-core-util-api")
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,18 @@ Load settings from a MongoDb instance.
# cas.spring.cloud.mongo.uri=mongodb://casuser:Mellon@ds135522.mlab.com:35522/jasigcas
```

### Azure KeyVault Secrets

Load settings from Microsoft Azure's KeyVault instance.

```properties
# azure.keyvault.enabled=true
# azure.keyvault.uri=put-your-azure-keyvault-uri-here
# azure.keyvault.client-id=put-your-azure-client-id-here
# azure.keyvault.client-key=put-your-azure-client-key-here
# azure.keyvault.token-acquire-timeout-seconds=60
```

### ZooKeeper

Load settings from an Apache ZooKeeper instance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,22 @@ The `DynamoDbCasProperties` table is automatically created by CAS with the follo

To see the relevant list of CAS properties for this feature, please [review this guide](Configuration-Properties.html#dynamodb).

##### Azure KeyVault Secrets

CAS is also able to use Microsoft Azure's KeyVault Secrets to locate properties and settings. Support is provided via the following dependency in the WAR overlay:

```xml
<dependency>
<groupId>org.apereo.cas</groupId>
<artifactId>cas-server-core-configuration-cloud-azure-keyvault</artifactId>
<version>${cas.version}</version>
</dependency>
```

To see the relevant list of CAS properties for this feature, please [review this guide](Configuration-Properties.html#azure-keyvault-secrets).

**IMPORTANT**: The allowed name pattern in Azure Key Vault is `^[0-9a-zA-Z-]+$`.For properties that contain that contain `.` in the name (i.e. `cas.some.property`), replace `.` with `-` when you store the setting in Azure Key Vault (i.e. `cas-some-property`). The module will handle the transformation for you.

##### JDBC

CAS is also able to use a relational database to locate properties and settings.
Expand Down
2 changes: 2 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ amazonSdkVersion=1.11.241
springDataCosmosDbVersion=0.1.2
cosmosdbVersion=1.15.0

azureKeyVaultSecretsVersion=0.2.0

jsonVersion=20160810
hjsonVersion=3.0.0
personDirectoryVersion=1.8.5
Expand Down
5 changes: 5 additions & 0 deletions gradle/dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,11 @@ ext.libraries = [
force = true
}
],
azurekeyvault : [
dependencies.create("com.microsoft.azure:azure-keyvault-secrets-spring-boot-starter:$azureKeyVaultSecretsVersion") {
exclude(group: "org.slf4j", module: "slf4j-api")
}
],
cosmosdb : [
dependencies.create("com.microsoft.azure:azure-documentdb:$cosmosdbVersion") {
exclude(group: "org.slf4j", module: "slf4j-api")
Expand Down
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ include "core:cas-server-core-audit"
include "core:cas-server-core-configuration-api"
include "core:cas-server-core-configuration"
include "core:cas-server-core-configuration-metadata-repository"
include "core:cas-server-core-configuration-cloud-azure-keyvault"
include "core:cas-server-core-configuration-cloud-jdbc"
include "core:cas-server-core-configuration-cloud-amqp"
include "core:cas-server-core-configuration-cloud-kafka"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@
import org.apache.coyote.http2.Http2Protocol;
import org.apereo.cas.CasEmbeddedContainerUtils;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.configuration.model.core.CasServerProperties;
import org.apereo.cas.configuration.model.core.web.tomcat.CasEmbeddedApacheTomcatAjpProperties;
import org.apereo.cas.configuration.model.core.web.tomcat.CasEmbeddedApacheTomcatExtendedAccessLogProperties;
import org.apereo.cas.configuration.model.core.web.tomcat.CasEmbeddedApacheTomcatHttpProperties;
import org.apereo.cas.configuration.model.core.web.tomcat.CasEmbeddedApacheTomcatHttpProxyProperties;
import org.apereo.cas.configuration.model.core.web.tomcat.CasEmbeddedApacheTomcatSslValveProperties;
import org.apereo.cas.util.ResourceUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -54,7 +58,7 @@ public class CasEmbeddedContainerTomcatConfiguration {

@Autowired
private CasConfigurationProperties casProperties;

@ConditionalOnClass(value = {Tomcat.class, Http2Protocol.class})
@Bean
public EmbeddedServletContainerFactory servletContainer() {
Expand All @@ -74,7 +78,7 @@ private void configureRewriteValve(final TomcatEmbeddedServletContainerFactory t
final Resource res = casProperties.getServer().getRewriteValve().getLocation();
if (ResourceUtils.doesResourceExist(res)) {
LOGGER.debug("Configuring rewrite valve at [{}]", res);

final RewriteValve valve = new RewriteValve() {
@Override
protected synchronized void startInternal() throws LifecycleException {
Expand All @@ -97,7 +101,7 @@ protected synchronized void startInternal() throws LifecycleException {
}

private void configureExtendedAccessLogValve(final TomcatEmbeddedServletContainerFactory tomcat) {
final CasServerProperties.ExtendedAccessLog ext = casProperties.getServer().getExtAccessLog();
final CasEmbeddedApacheTomcatExtendedAccessLogProperties ext = casProperties.getServer().getExtAccessLog();

if (ext.isEnabled() && StringUtils.isNotBlank(ext.getPattern())) {
LOGGER.debug("Creating extended access log valve configuration for the embedded tomcat container...");
Expand All @@ -121,7 +125,7 @@ private void configureExtendedAccessLogValve(final TomcatEmbeddedServletContaine
}

private void configureHttp(final TomcatEmbeddedServletContainerFactory tomcat) {
final CasServerProperties.Http http = casProperties.getServer().getHttp();
final CasEmbeddedApacheTomcatHttpProperties http = casProperties.getServer().getHttp();
if (http.isEnabled()) {
LOGGER.debug("Creating HTTP configuration for the embedded tomcat container...");
final Connector connector = new Connector(http.getProtocol());
Expand All @@ -142,7 +146,7 @@ private void configureHttp(final TomcatEmbeddedServletContainerFactory tomcat) {
}

private void configureHttpProxy(final TomcatEmbeddedServletContainerFactory tomcat) {
final CasServerProperties.HttpProxy proxy = casProperties.getServer().getHttpProxy();
final CasEmbeddedApacheTomcatHttpProxyProperties proxy = casProperties.getServer().getHttpProxy();
if (proxy.isEnabled()) {
LOGGER.debug("Customizing HTTP proxying for connector listening on port [{}]", tomcat.getPort());
tomcat.getTomcatConnectorCustomizers().add(connector -> {
Expand Down Expand Up @@ -172,7 +176,7 @@ private void configureHttpProxy(final TomcatEmbeddedServletContainerFactory tomc
}

private void configureAjp(final TomcatEmbeddedServletContainerFactory tomcat) {
final CasServerProperties.Ajp ajp = casProperties.getServer().getAjp();
final CasEmbeddedApacheTomcatAjpProperties ajp = casProperties.getServer().getAjp();
if (ajp.isEnabled() && ajp.getPort() > 0) {
LOGGER.debug("Creating AJP configuration for the embedded tomcat container...");
final Connector ajpConnector = new Connector(ajp.getProtocol());
Expand Down Expand Up @@ -203,7 +207,7 @@ private void configureAjp(final TomcatEmbeddedServletContainerFactory tomcat) {
}

private void configureSSLValve(final TomcatEmbeddedServletContainerFactory tomcat) {
final CasServerProperties.SslValve valveConfig = casProperties.getServer().getSslValve();
final CasEmbeddedApacheTomcatSslValveProperties valveConfig = casProperties.getServer().getSslValve();

if (valveConfig.isEnabled()) {
LOGGER.debug("Adding SSLValve to engine of the embedded tomcat container...");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.apereo.cas.config;

import org.apache.catalina.filters.CsrfPreventionFilter;
import org.apache.catalina.filters.RemoteAddrFilter;
import org.apereo.cas.CasEmbeddedContainerUtils;
import org.apereo.cas.configuration.CasConfigurationProperties;
import org.apereo.cas.configuration.model.core.web.tomcat.CasEmbeddedApacheTomcatRemoteAddressProperties;
import org.apereo.cas.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;

/**
* This is {@link CasEmbeddedContainerTomcatFiltersConfiguration}.
*
* @author Misagh Moayyed
* @since 5.0.0
*/
@Configuration("casEmbeddedContainerTomcatFiltersConfiguration")
@EnableConfigurationProperties(CasConfigurationProperties.class)
@ConditionalOnProperty(name = CasEmbeddedContainerUtils.EMBEDDED_CONTAINER_CONFIG_ACTIVE, havingValue = "true")
@ImportAutoConfiguration(CasEmbeddedContainerTomcatConfiguration.class)
public class CasEmbeddedContainerTomcatFiltersConfiguration {
@Autowired
private CasConfigurationProperties casProperties;

@ConditionalOnProperty(prefix = "cas.server.csrf", name = "enabled", havingValue = "true")
@RefreshScope
@Bean
public FilterRegistrationBean tomcatCsrfPreventionFilter() {
final FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new CsrfPreventionFilter());
bean.setUrlPatterns(CollectionUtils.wrap("/*"));
bean.setName("tomcatCsrfPreventionFilter");
return bean;
}

@ConditionalOnProperty(prefix = "cas.server.remoteAddr", name = "enabled", havingValue = "true")
@RefreshScope
@Bean
public FilterRegistrationBean tomcatRemoteAddressFilter() {
final FilterRegistrationBean bean = new FilterRegistrationBean();
final CasEmbeddedApacheTomcatRemoteAddressProperties addr = casProperties.getServer().getRemoteAddr();
final RemoteAddrFilter filter = new RemoteAddrFilter();
filter.setAllow(addr.getAllowedClientIpAddressRegex());
filter.setDeny(addr.getDeniedClientIpAddressRegex());
filter.setDenyStatus(HttpStatus.UNAUTHORIZED.value());
bean.setFilter(filter);
bean.setUrlPatterns(CollectionUtils.wrap("/*"));
bean.setName("tomcatRemoteAddressFilter");
return bean;
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.apereo.cas.config.CasEmbeddedContainerTomcatConfiguration
org.apereo.cas.config.CasEmbeddedContainerTomcatConfiguration,\
org.apereo.cas.config.CasEmbeddedContainerTomcatFiltersConfiguration

0 comments on commit 005c5ab

Please sign in to comment.