Author: aduprat Date: Wed Jan 13 09:38:41 2016 New Revision: 1724377 URL: http://svn.apache.org/viewvc?rev=1724377&view=rev Log: JAMES-1654 Add JWT PublicKey in JMAP configuration. Contributed by Duprat <antdup...@gmail.com>
Added: james/project/trunk/dockerfiles/run/guice/destination/conf/jwt_publickey james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPConfigurationTest.java Modified: james/project/trunk/dockerfiles/run/guice/destination/conf/jmap.properties james/project/trunk/server/container/cassandra-guice/sample-configuration/jmap.properties james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/JMAPModule.java james/project/trunk/server/container/cassandra-guice/src/test/java/org/apache/james/modules/TestJMAPServerModule.java james/project/trunk/server/container/jetty/pom.xml james/project/trunk/server/pom.xml james/project/trunk/server/protocols/jmap/pom.xml james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfiguration.java james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerProvider.java Modified: james/project/trunk/dockerfiles/run/guice/destination/conf/jmap.properties URL: http://svn.apache.org/viewvc/james/project/trunk/dockerfiles/run/guice/destination/conf/jmap.properties?rev=1724377&r1=1724376&r2=1724377&view=diff ============================================================================== --- james/project/trunk/dockerfiles/run/guice/destination/conf/jmap.properties (original) +++ james/project/trunk/dockerfiles/run/guice/destination/conf/jmap.properties Wed Jan 13 09:38:41 2016 @@ -1,4 +1,11 @@ # Configuration file for JMAP tls.keystoreURL=file://conf/keystore -tls.secret=james72laBalle \ No newline at end of file +tls.secret=james72laBalle + +# +# If you wish to use OAuth authentication, you should provide a valid JWT public key. +# The following entry specify the link to the URL of the public key file, +# which should be a PEM format file. +# +jwt.publickeypem.url=file://conf/jwt_publickey Added: james/project/trunk/dockerfiles/run/guice/destination/conf/jwt_publickey URL: http://svn.apache.org/viewvc/james/project/trunk/dockerfiles/run/guice/destination/conf/jwt_publickey?rev=1724377&view=auto ============================================================================== --- james/project/trunk/dockerfiles/run/guice/destination/conf/jwt_publickey (added) +++ james/project/trunk/dockerfiles/run/guice/destination/conf/jwt_publickey Wed Jan 13 09:38:41 2016 @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh +16XrMRf6M4NeyGa7j5+1UKm42IKUf3lM28oe82MqIIRyvskPc11NuzSor8HmvH8H +lhDs5DyJtx2qp35AT0zCqfwlaDnlDc/QDlZv1CoRZGpQk1Inyh6SbZwYpxxwh0fi ++d/4RpE3LBVo8wgOaXPylOlHxsDizfkL8QwXItyakBfMO6jWQRrj7/9WDhGf4Hi+ +GQur1tPGZDl9mvCoRHjFrD5M/yypIPlfMGWFVEvV5jClNMLAQ9bYFuOc7H1fEWw6 +U1LZUUbJW9/CH45YXz82CYqkrfbnQxqRb2iVbVjs/sHopHd1NTiCfUtwvcYJiBVj +kwIDAQAB +-----END PUBLIC KEY----- Modified: james/project/trunk/server/container/cassandra-guice/sample-configuration/jmap.properties URL: http://svn.apache.org/viewvc/james/project/trunk/server/container/cassandra-guice/sample-configuration/jmap.properties?rev=1724377&r1=1724376&r2=1724377&view=diff ============================================================================== --- james/project/trunk/server/container/cassandra-guice/sample-configuration/jmap.properties (original) +++ james/project/trunk/server/container/cassandra-guice/sample-configuration/jmap.properties Wed Jan 13 09:38:41 2016 @@ -1,4 +1,11 @@ # Configuration file for JMAP tls.keystoreURL=file://conf/keystore -tls.secret=james72laBalle \ No newline at end of file +tls.secret=james72laBalle + +# +# If you wish to use OAuth authentication, you should provide a valid JWT public key. +# The following entry specify the link to the URL of the public key file, +# which should be a PEM format file. +# +jwt.publickeypem.url= \ No newline at end of file Modified: james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/JMAPModule.java URL: http://svn.apache.org/viewvc/james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/JMAPModule.java?rev=1724377&r1=1724376&r2=1724377&view=diff ============================================================================== --- james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/JMAPModule.java (original) +++ james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/jmap/JMAPModule.java Wed Jan 13 09:38:41 2016 @@ -19,12 +19,16 @@ package org.apache.james.jmap; import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Optional; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; +import org.apache.commons.io.FileUtils; import org.apache.james.filesystem.api.FileSystem; import org.apache.james.jmap.methods.RequestHandler; +import com.github.fge.lambdas.Throwing; import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.google.inject.Singleton; @@ -42,14 +46,20 @@ public class JMAPModule extends Abstract @Provides @Singleton - JMAPConfiguration provideConfiguration(FileSystem fileSystem) throws FileNotFoundException, ConfigurationException{ + JMAPConfiguration provideConfiguration(FileSystem fileSystem) throws ConfigurationException, IOException{ PropertiesConfiguration configuration = getConfiguration(fileSystem); - String keystore = configuration.getString("tls.keystoreURL"); - String secret = configuration.getString("tls.secret"); - return new JMAPConfiguration(keystore, secret); + return JMAPConfiguration.builder() + .keystore(configuration.getString("tls.keystoreURL")) + .secret(configuration.getString("tls.secret")) + .jwtPublicKeyPem(loadPublicKey(fileSystem, Optional.ofNullable(configuration.getString("jwt.publickeypem.url")))) + .build(); } private PropertiesConfiguration getConfiguration(FileSystem fileSystem) throws FileNotFoundException, ConfigurationException { return new PropertiesConfiguration(fileSystem.getFile(FileSystem.FILE_PROTOCOL_AND_CONF + "jmap.properties")); } + + private Optional<String> loadPublicKey(FileSystem fileSystem, Optional<String> jwtPublickeyPemUrl) { + return jwtPublickeyPemUrl.map(Throwing.function(url -> FileUtils.readFileToString(fileSystem.getFile(url)))); + } } Modified: james/project/trunk/server/container/cassandra-guice/src/test/java/org/apache/james/modules/TestJMAPServerModule.java URL: http://svn.apache.org/viewvc/james/project/trunk/server/container/cassandra-guice/src/test/java/org/apache/james/modules/TestJMAPServerModule.java?rev=1724377&r1=1724376&r2=1724377&view=diff ============================================================================== --- james/project/trunk/server/container/cassandra-guice/src/test/java/org/apache/james/modules/TestJMAPServerModule.java (original) +++ james/project/trunk/server/container/cassandra-guice/src/test/java/org/apache/james/modules/TestJMAPServerModule.java Wed Jan 13 09:38:41 2016 @@ -50,7 +50,10 @@ public class TestJMAPServerModule extend @Provides @Singleton JMAPConfiguration provideConfiguration() throws FileNotFoundException, ConfigurationException{ - return new JMAPConfiguration("keystore", "james72laBalle"); + return JMAPConfiguration.builder() + .keystore("keystore") + .secret("james72laBalle") + .build(); } private static class RandomPortConfiguration implements PortConfiguration { Modified: james/project/trunk/server/container/jetty/pom.xml URL: http://svn.apache.org/viewvc/james/project/trunk/server/container/jetty/pom.xml?rev=1724377&r1=1724376&r2=1724377&view=diff ============================================================================== --- james/project/trunk/server/container/jetty/pom.xml (original) +++ james/project/trunk/server/container/jetty/pom.xml Wed Jan 13 09:38:41 2016 @@ -129,6 +129,10 @@ </activation> <dependencies> <dependency> + <groupId>com.github.fge</groupId> + <artifactId>throwing-lambdas</artifactId> + </dependency> + <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> </dependency> Modified: james/project/trunk/server/pom.xml URL: http://svn.apache.org/viewvc/james/project/trunk/server/pom.xml?rev=1724377&r1=1724376&r2=1724377&view=diff ============================================================================== --- james/project/trunk/server/pom.xml (original) +++ james/project/trunk/server/pom.xml Wed Jan 13 09:38:41 2016 @@ -193,6 +193,7 @@ <cassandra-unit.version>2.1.9.2</cassandra-unit.version> <assertj-1.version>1.7.1</assertj-1.version> <assertj-3.version>3.2.0</assertj-3.version> + <throwing-lambdas.version>0.5.0</throwing-lambdas.version> </properties> <dependencyManagement> @@ -1413,6 +1414,11 @@ <artifactId>jetty-servlet</artifactId> <version>${jetty.version}</version> </dependency> + <dependency> + <groupId>com.github.fge</groupId> + <artifactId>throwing-lambdas</artifactId> + <version>${throwing-lambdas.version}</version> + </dependency> </dependencies> </dependencyManagement> Modified: james/project/trunk/server/protocols/jmap/pom.xml URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/pom.xml?rev=1724377&r1=1724376&r2=1724377&view=diff ============================================================================== --- james/project/trunk/server/protocols/jmap/pom.xml (original) +++ james/project/trunk/server/protocols/jmap/pom.xml Wed Jan 13 09:38:41 2016 @@ -215,7 +215,6 @@ <dependency> <groupId>com.github.fge</groupId> <artifactId>throwing-lambdas</artifactId> - <version>0.5.0</version> </dependency> <dependency> <groupId>com.jayway.restassured</groupId> Modified: james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfiguration.java URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfiguration.java?rev=1724377&r1=1724376&r2=1724377&view=diff ============================================================================== --- james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfiguration.java (original) +++ james/project/trunk/server/protocols/jmap/src/main/java/org/apache/james/jmap/JMAPConfiguration.java Wed Jan 13 09:38:41 2016 @@ -18,14 +18,58 @@ ****************************************************************/ package org.apache.james.jmap; +import java.util.Optional; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.base.Strings; + public class JMAPConfiguration { - public final String keystore; - public final String secret; + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + public String keystore; + public String secret; + public Optional<String> jwtPublicKeyPem; + + private Builder() { + jwtPublicKeyPem = Optional.empty(); + } + + public Builder keystore(String keystore) { + this.keystore = keystore; + return this; + } + + public Builder secret(String secret) { + this.secret = secret; + return this; + } - public JMAPConfiguration(String keystore, String secret) { + public Builder jwtPublicKeyPem(Optional<String> jwtPublicKeyPem) { + Preconditions.checkNotNull(jwtPublicKeyPem); + this.jwtPublicKeyPem = jwtPublicKeyPem; + return this; + } + + public JMAPConfiguration build() { + Preconditions.checkState(!Strings.isNullOrEmpty(keystore), "'keystore' is mandatory"); + Preconditions.checkState(!Strings.isNullOrEmpty(secret), "'secret' is mandatory"); + return new JMAPConfiguration(keystore, secret, jwtPublicKeyPem); + } + } + + private final String keystore; + private final String secret; + private final Optional<String> jwtPublicKeyPem; + + @VisibleForTesting JMAPConfiguration(String keystore, String secret, Optional<String> jwtPublicKeyPem) { this.keystore = keystore; this.secret = secret; + this.jwtPublicKeyPem = jwtPublicKeyPem; } public String getKeystore() { @@ -35,4 +79,8 @@ public class JMAPConfiguration { public String getSecret() { return secret; } + + public Optional<String> getJwtPublicKeyPem() { + return jwtPublicKeyPem; + } } Added: james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPConfigurationTest.java URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPConfigurationTest.java?rev=1724377&view=auto ============================================================================== --- james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPConfigurationTest.java (added) +++ james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/JMAPConfigurationTest.java Wed Jan 13 09:38:41 2016 @@ -0,0 +1,90 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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.apache.james.jmap; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.Optional; + +import org.junit.Test; + +public class JMAPConfigurationTest { + + @Test + public void buildShouldThrowWhenKeystoreIsNull() { + assertThatThrownBy(() -> JMAPConfiguration.builder() + .keystore(null) + .build()) + .isInstanceOf(IllegalStateException.class) + .hasMessage("'keystore' is mandatory"); + } + + @Test + public void buildShouldThrowWhenKeystoreIsEmpty() { + assertThatThrownBy(() -> JMAPConfiguration.builder() + .keystore("") + .build()) + .isInstanceOf(IllegalStateException.class) + .hasMessage("'keystore' is mandatory"); + } + + @Test + public void buildShouldThrowWhenSecretIsNull() { + assertThatThrownBy(() -> JMAPConfiguration.builder() + .keystore("keystore") + .secret(null) + .build()) + .isInstanceOf(IllegalStateException.class) + .hasMessage("'secret' is mandatory"); + } + + @Test + public void buildShouldThrowWhenSecretIsEmpty() { + assertThatThrownBy(() -> JMAPConfiguration.builder() + .keystore("keystore") + .secret("") + .build()) + .isInstanceOf(IllegalStateException.class) + .hasMessage("'secret' is mandatory"); + } + + @Test + public void buildShouldThrowWhenJwtPublicKeyPemIsNull() { + assertThatThrownBy(() -> JMAPConfiguration.builder() + .keystore("keystore") + .secret("secret") + .jwtPublicKeyPem(null) + .build()) + .isInstanceOf(NullPointerException.class); + } + + @Test + public void buildShouldWork() { + JMAPConfiguration expectedJMAPConfiguration = new JMAPConfiguration("keystore", "secret", Optional.of("file://conf/jwt_publickey")); + + JMAPConfiguration jmapConfiguration = JMAPConfiguration.builder() + .keystore("keystore") + .secret("secret") + .jwtPublicKeyPem(Optional.of("file://conf/jwt_publickey")) + .build(); + assertThat(jmapConfiguration).isEqualToComparingFieldByField(expectedJMAPConfiguration); + } +} Modified: james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerProvider.java URL: http://svn.apache.org/viewvc/james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerProvider.java?rev=1724377&r1=1724376&r2=1724377&view=diff ============================================================================== --- james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerProvider.java (original) +++ james/project/trunk/server/protocols/jmap/src/test/java/org/apache/james/jmap/crypto/JamesSignatureHandlerProvider.java Wed Jan 13 09:38:41 2016 @@ -46,7 +46,11 @@ public class JamesSignatureHandlerProvid return null; } }; - JamesSignatureHandler signatureHandler = new JamesSignatureHandler(fileSystem, new JMAPConfiguration("keystore", "james72laBalle")); + JamesSignatureHandler signatureHandler = new JamesSignatureHandler(fileSystem, + JMAPConfiguration.builder() + .keystore("keystore") + .secret("james72laBalle") + .build()); signatureHandler.init(); return signatureHandler; } --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org