fineract-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From my...@apache.org
Subject [fineract-cn-provisioner] 42/50: Improved configuration validation, and configuration defaults by adding two @ConfigurationProperties annotated classes to assist in reading configuration properties and programming validation for those classes. After this change the provisioner will not start unless there are public and private keys set and those keys match each other.
Date Mon, 22 Jan 2018 15:16:40 GMT
This is an automated email from the ASF dual-hosted git repository.

myrle pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract-cn-provisioner.git

commit eb369d5e586eabdf78eefa155f3e8b9e17a2f50c
Author: Myrle Krantz <myrle@apache.org>
AuthorDate: Wed Jul 19 09:12:22 2017 +0200

    Improved configuration validation, and configuration defaults by adding two @ConfigurationProperties
annotated classes to assist in reading configuration properties and programming validation
for those classes. After this change the provisioner will not start unless there are public
and private keys set and those keys match each other.
---
 .../io/mifos/provisioner/AbstractServiceTest.java  |   8 +-
 .../tenant/TestTenantApplicationAssignment.java    |  25 ++--
 component-test/src/main/resources/application.yaml |  26 ++++
 service/build.gradle                               |   4 +
 .../mifos/provisioner/config/CheckKeysValid.java   |  60 +++++++++
 .../DataStoreOption.java => config/KeysValid.java} |  28 +++--
 .../ProvisionerProperties.java}                    |  26 ++--
 .../config/ProvisionerServiceConfig.java           |  14 +--
 .../mifos/provisioner/config/SystemProperties.java | 135 +++++++++++++++++++++
 .../internal/service/AuthenticationService.java    |   8 +-
 .../internal/service/TenantService.java            |  36 +++---
 .../applications/IdentityServiceInitializer.java   |  18 +--
 .../provisioner/internal/util/DataStoreOption.java |   4 -
 service/src/main/resources/application.yaml        |  14 +--
 .../provisioner/config/SystemPropertiesTest.java   |  54 +++++++++
 .../IdentityServiceInitializerTest.java            |  13 +-
 16 files changed, 368 insertions(+), 105 deletions(-)

diff --git a/component-test/src/main/java/io/mifos/provisioner/AbstractServiceTest.java b/component-test/src/main/java/io/mifos/provisioner/AbstractServiceTest.java
index f47ca69..2aac655 100644
--- a/component-test/src/main/java/io/mifos/provisioner/AbstractServiceTest.java
+++ b/component-test/src/main/java/io/mifos/provisioner/AbstractServiceTest.java
@@ -17,7 +17,6 @@ package io.mifos.provisioner;
 
 import io.mifos.core.test.env.TestEnvironment;
 import io.mifos.provisioner.api.v1.client.Provisioner;
-import io.mifos.provisioner.config.ProvisionerActiveMQProperties;
 import io.mifos.provisioner.config.ProvisionerServiceConfig;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
@@ -37,11 +36,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
 @RunWith(SpringJUnit4ClassRunner.class)
 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
-        classes = {AbstractServiceTest.TestConfiguration.class},
-        properties = {
-                ProvisionerActiveMQProperties.ACTIVEMQ_BROKER_URL_PROP + "=" + ProvisionerActiveMQProperties.ACTIVEMQ_BROKER_URL_DEFAULT,
-                ProvisionerActiveMQProperties.ACTIVEMQ_CONCURRENCY_PROP + "=" + ProvisionerActiveMQProperties.ACTIVEMQ_CONCURRENCY_DEFAULT}
-)
+        classes = {AbstractServiceTest.TestConfiguration.class})
 public class AbstractServiceTest {
   private static final String APP_NAME = "provisioner-v1";
   private static final String CLIENT_ID = "sillyRabbit";
@@ -72,6 +67,7 @@ public class AbstractServiceTest {
           .around(mariaDBInitializer)
           .around(cassandraInitializer);
 
+  @SuppressWarnings("SpringAutowiredFieldsWarningInspection")
   @Autowired
   protected Provisioner provisioner;
 
diff --git a/component-test/src/main/java/io/mifos/provisioner/tenant/TestTenantApplicationAssignment.java
b/component-test/src/main/java/io/mifos/provisioner/tenant/TestTenantApplicationAssignment.java
index a72bb38..b0e6411 100644
--- a/component-test/src/main/java/io/mifos/provisioner/tenant/TestTenantApplicationAssignment.java
+++ b/component-test/src/main/java/io/mifos/provisioner/tenant/TestTenantApplicationAssignment.java
@@ -21,7 +21,6 @@ import io.mifos.anubis.api.v1.domain.AllowedOperation;
 import io.mifos.anubis.api.v1.domain.ApplicationSignatureSet;
 import io.mifos.anubis.api.v1.domain.PermittableEndpoint;
 import io.mifos.anubis.api.v1.domain.Signature;
-import io.mifos.anubis.provider.SystemRsaKeyProvider;
 import io.mifos.anubis.test.v1.SystemSecurityEnvironment;
 import io.mifos.core.api.context.AutoSeshat;
 import io.mifos.core.api.util.ApiConstants;
@@ -40,7 +39,6 @@ import io.mifos.provisioner.ProvisionerCassandraInitializer;
 import io.mifos.provisioner.ProvisionerMariaDBInitializer;
 import io.mifos.provisioner.api.v1.client.Provisioner;
 import io.mifos.provisioner.api.v1.domain.*;
-import io.mifos.provisioner.config.ProvisionerActiveMQProperties;
 import io.mifos.provisioner.config.ProvisionerConstants;
 import io.mifos.provisioner.config.ProvisionerServiceConfig;
 import io.mifos.provisioner.internal.listener.IdentityListener;
@@ -77,11 +75,7 @@ import static org.mockito.Mockito.*;
  * @author Myrle Krantz
  */
 @RunWith(SpringJUnit4ClassRunner.class)
-@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT,
-        properties = {
-                ProvisionerActiveMQProperties.ACTIVEMQ_BROKER_URL_PROP + "=" + ProvisionerActiveMQProperties.ACTIVEMQ_BROKER_URL_DEFAULT,
-                ProvisionerActiveMQProperties.ACTIVEMQ_CONCURRENCY_PROP + "=" + ProvisionerActiveMQProperties.ACTIVEMQ_CONCURRENCY_DEFAULT}
-)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
 public class TestTenantApplicationAssignment {
   private static final String APP_NAME = "provisioner-v1";
   private static final String CLIENT_ID = "sillyRabbit";
@@ -128,24 +122,21 @@ public class TestTenantApplicationAssignment {
           .around(mariaDBInitializer)
           .around(cassandraInitializer);
 
+  @SuppressWarnings("SpringAutowiredFieldsWarningInspection")
   @Autowired
   private Provisioner provisioner;
 
+  @SuppressWarnings("SpringAutowiredFieldsWarningInspection")
   @Autowired
-  @Qualifier("tokenProviderSpy")
-  protected TokenProvider tokenProviderSpy;
+  private ApplicationCallContextProvider applicationCallContextProviderSpy;
 
+  @SuppressWarnings("SpringAutowiredFieldsWarningInspection")
   @Autowired
-  protected ApplicationCallContextProvider applicationCallContextProviderSpy;
+  private IdentityListener identityListener;
 
+  @SuppressWarnings("SpringAutowiredFieldsWarningInspection")
   @Autowired
-  protected SystemRsaKeyProvider systemRsaKeyProvider;
-
-  @Autowired
-  protected IdentityListener identityListener;
-
-  @Autowired
-  protected Gson gson;
+  private Gson gson;
 
   private AutoSeshat autoSeshat;
 
diff --git a/component-test/src/main/resources/application.yaml b/component-test/src/main/resources/application.yaml
new file mode 100644
index 0000000..3685c6b
--- /dev/null
+++ b/component-test/src/main/resources/application.yaml
@@ -0,0 +1,26 @@
+#
+# Copyright 2017 The Mifos Initiative.
+#
+# 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.
+#
+
+system:
+  domain: mifos.io
+  dataStoreOption: ALL # possible values ALL, CASSANDRA, RDBMS
+  token:
+    ttl: 60
+
+
+activemq:
+  brokerUrl: vm://localhost?broker.persistent=false
+  concurrency: 3-10
\ No newline at end of file
diff --git a/service/build.gradle b/service/build.gradle
index 2bd249e..373a0df 100644
--- a/service/build.gradle
+++ b/service/build.gradle
@@ -47,6 +47,10 @@ dependencies {
             [group: 'org.hibernate', name: 'hibernate-validator', version: versions.validator],
             [group: 'io.mifos.tools', name: 'crypto', version: versions.frameworkcrypto],
     )
+
+    testCompile(
+            [group: 'io.mifos.core', name: 'test', version: versions.frameworktest],
+    )
 }
 
 publishToMavenLocal.dependsOn bootRepackage
diff --git a/service/src/main/java/io/mifos/provisioner/config/CheckKeysValid.java b/service/src/main/java/io/mifos/provisioner/config/CheckKeysValid.java
new file mode 100644
index 0000000..6228e08
--- /dev/null
+++ b/service/src/main/java/io/mifos/provisioner/config/CheckKeysValid.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * 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 io.mifos.provisioner.config;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.RSAPrivateKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+
+/**
+ * @author Myrle Krantz
+ */
+public class CheckKeysValid implements ConstraintValidator<KeysValid, SystemProperties>
{
+
+  @Override
+  public void initialize(KeysValid constraintAnnotation) {
+  }
+
+  @Override
+  public boolean isValid(final SystemProperties value, final ConstraintValidatorContext context)
{
+    if (value.getPrivateKey().getModulus() == null || value.getPrivateKey().getExponent()
== null ||
+        value.getPublicKey().getModulus() == null ||value.getPublicKey().getExponent() ==
null)
+      return false;
+
+    try {
+      final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+      final RSAPrivateKeySpec rsaPrivateKeySpec
+          = new RSAPrivateKeySpec(value.getPrivateKey().getModulus(), value.getPrivateKey().getExponent());
+      final PrivateKey privateKey = keyFactory.generatePrivate(rsaPrivateKeySpec);
+
+      final RSAPublicKeySpec rsaPublicKeySpec
+          = new RSAPublicKeySpec(value.getPublicKey().getModulus(), value.getPublicKey().getExponent());
+      final PublicKey publicKey = keyFactory.generatePublic(rsaPublicKeySpec);
+
+      final Signature signature = Signature.getInstance("NONEwithRSA");
+      signature.initSign(privateKey);
+      final byte[] signed = signature.sign();
+
+      signature.initVerify(publicKey);
+      return signature.verify(signed);
+    } catch (final NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException
| SignatureException e) {
+      return false;
+    }
+  }
+}
diff --git a/service/src/main/java/io/mifos/provisioner/internal/util/DataStoreOption.java
b/service/src/main/java/io/mifos/provisioner/config/KeysValid.java
similarity index 53%
copy from service/src/main/java/io/mifos/provisioner/internal/util/DataStoreOption.java
copy to service/src/main/java/io/mifos/provisioner/config/KeysValid.java
index e399e87..9a582e3 100644
--- a/service/src/main/java/io/mifos/provisioner/internal/util/DataStoreOption.java
+++ b/service/src/main/java/io/mifos/provisioner/config/KeysValid.java
@@ -13,18 +13,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.provisioner.internal.util;
+package io.mifos.provisioner.config;
 
-public enum DataStoreOption {
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.*;
 
-  ALL,
-  CASSANDRA,
-  RDBMS;
+/**
+ * @author Myrle Krantz
+ */
+@SuppressWarnings("unused")
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Constraint(
+    validatedBy = {CheckKeysValid.class}
+)
+public @interface KeysValid {
+  String message() default "Public and private keys must be valid and matching.";
 
-  public static final String PROPERTY_NAME = "provisioner.dataStoreOption";
-  public static final String PROPERTY_DEFAULT_VALUE = "ALL";
+  Class<?>[] groups() default {};
 
-  public boolean isEnabled(final DataStoreOption dataStoreOption) {
-    return this == ALL || this == dataStoreOption;
-  }
+  Class<? extends Payload>[] payload() default {};
 }
diff --git a/service/src/main/java/io/mifos/provisioner/internal/util/DataStoreOption.java
b/service/src/main/java/io/mifos/provisioner/config/ProvisionerProperties.java
similarity index 51%
copy from service/src/main/java/io/mifos/provisioner/internal/util/DataStoreOption.java
copy to service/src/main/java/io/mifos/provisioner/config/ProvisionerProperties.java
index e399e87..c007e6b 100644
--- a/service/src/main/java/io/mifos/provisioner/internal/util/DataStoreOption.java
+++ b/service/src/main/java/io/mifos/provisioner/config/ProvisionerProperties.java
@@ -13,18 +13,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package io.mifos.provisioner.internal.util;
+package io.mifos.provisioner.config;
 
-public enum DataStoreOption {
+import io.mifos.provisioner.internal.util.DataStoreOption;
+import org.springframework.boot.context.properties.ConfigurationProperties;
 
-  ALL,
-  CASSANDRA,
-  RDBMS;
+import javax.validation.Valid;
 
-  public static final String PROPERTY_NAME = "provisioner.dataStoreOption";
-  public static final String PROPERTY_DEFAULT_VALUE = "ALL";
+/**
+ * @author Myrle Krantz
+ */
+@ConfigurationProperties(prefix = "provisioner")
+public class ProvisionerProperties {
+  @Valid
+  private DataStoreOption dataStoreOption = DataStoreOption.ALL;
+
+  public DataStoreOption getDataStoreOption() {
+    return dataStoreOption;
+  }
 
-  public boolean isEnabled(final DataStoreOption dataStoreOption) {
-    return this == ALL || this == dataStoreOption;
+  public void setDataStoreOption(DataStoreOption dataStoreOption) {
+    this.dataStoreOption = dataStoreOption;
   }
 }
diff --git a/service/src/main/java/io/mifos/provisioner/config/ProvisionerServiceConfig.java
b/service/src/main/java/io/mifos/provisioner/config/ProvisionerServiceConfig.java
index 05b849a..c07cc54 100644
--- a/service/src/main/java/io/mifos/provisioner/config/ProvisionerServiceConfig.java
+++ b/service/src/main/java/io/mifos/provisioner/config/ProvisionerServiceConfig.java
@@ -15,7 +15,6 @@
  */
 package io.mifos.provisioner.config;
 
-import io.mifos.anubis.config.AnubisConstants;
 import io.mifos.anubis.config.EnableAnubis;
 import io.mifos.anubis.token.SystemAccessTokenSerializer;
 import io.mifos.core.api.util.ApiFactory;
@@ -36,14 +35,11 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.core.env.Environment;
 import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
 import org.springframework.jms.config.JmsListenerContainerFactory;
 import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
 
-import java.math.BigInteger;
-
 @Configuration
 @EnableAutoConfiguration
 @ComponentScan({
@@ -60,7 +56,7 @@ import java.math.BigInteger;
 @EnableCassandra
 @EnableServiceException
 @EnableApplicationName
-@EnableConfigurationProperties({ProvisionerActiveMQProperties.class})
+@EnableConfigurationProperties({ProvisionerActiveMQProperties.class, ProvisionerProperties.class,
SystemProperties.class})
 public class ProvisionerServiceConfig extends WebMvcConfigurerAdapter {
 
   public ProvisionerServiceConfig() {
@@ -73,15 +69,15 @@ public class ProvisionerServiceConfig extends WebMvcConfigurerAdapter
{
   }
 
   @Bean(name = "tokenProvider")
-  public TokenProvider tokenProvider(final Environment environment,
+  public TokenProvider tokenProvider(final SystemProperties systemProperties,
                                      @SuppressWarnings("SpringJavaAutowiringInspection")
final SystemAccessTokenSerializer tokenSerializer,
                                      @Qualifier(ProvisionerConstants.LOGGER_NAME) final Logger
logger) {
-    final String timestamp = environment.getProperty(AnubisConstants.PUBLIC_KEY_TIMESTAMP_PROPERTY);
+    final String timestamp = systemProperties.getPublicKey().getTimestamp();
     logger.info("Provisioner key timestamp: " + timestamp);
 
     return new TokenProvider( timestamp,
-        new BigInteger(environment.getProperty("system.privateKey.modulus")),
-        new BigInteger(environment.getProperty("system.privateKey.exponent")), tokenSerializer);
+        systemProperties.getPrivateKey().getModulus(),
+        systemProperties.getPrivateKey().getExponent(), tokenSerializer);
   }
 
   @Bean
diff --git a/service/src/main/java/io/mifos/provisioner/config/SystemProperties.java b/service/src/main/java/io/mifos/provisioner/config/SystemProperties.java
new file mode 100644
index 0000000..9335127
--- /dev/null
+++ b/service/src/main/java/io/mifos/provisioner/config/SystemProperties.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2017 The Mifos Initiative.
+ *
+ * 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 io.mifos.provisioner.config;
+
+import org.hibernate.validator.constraints.NotEmpty;
+import org.hibernate.validator.constraints.Range;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import java.math.BigInteger;
+
+/**
+ * @author Myrle Krantz
+ */
+@KeysValid
+@ConfigurationProperties(prefix = "system")
+public class SystemProperties {
+  @NotEmpty
+  private String domain = "mifos.io";
+
+  @Valid
+  private final Token token = new Token();
+
+  @Valid
+  private final PublicKey publicKey = new PublicKey();
+
+  @Valid
+  private final PrivateKey privateKey = new PrivateKey();
+
+  public static class Token {
+    @Range(min = 1)
+    private int ttl = 60;
+
+    public int getTtl() {
+      return ttl;
+    }
+
+    public void setTtl(int ttl) {
+      this.ttl = ttl;
+    }
+  }
+
+  public static class PublicKey {
+    @NotEmpty
+    private String timestamp;
+
+    @NotNull
+    private BigInteger modulus;
+
+    @NotNull
+    private BigInteger exponent;
+
+    public String getTimestamp() {
+      return timestamp;
+    }
+
+    public void setTimestamp(String timestamp) {
+      this.timestamp = timestamp;
+    }
+
+    public BigInteger getModulus() {
+      return modulus;
+    }
+
+    public void setModulus(BigInteger modulus) {
+      this.modulus = modulus;
+    }
+
+    public BigInteger getExponent() {
+      return exponent;
+    }
+
+    public void setExponent(BigInteger exponent) {
+      this.exponent = exponent;
+    }
+  }
+
+  public static class PrivateKey {
+    @NotNull
+    private BigInteger modulus;
+
+    @NotNull
+    private BigInteger exponent;
+
+    public BigInteger getModulus() {
+      return modulus;
+    }
+
+    public void setModulus(BigInteger modulus) {
+      this.modulus = modulus;
+    }
+
+    public BigInteger getExponent() {
+      return exponent;
+    }
+
+    public void setExponent(BigInteger exponent) {
+      this.exponent = exponent;
+    }
+  }
+
+  public String getDomain() {
+    return domain;
+  }
+
+  public void setDomain(String domain) {
+    this.domain = domain;
+  }
+
+  public Token getToken() {
+    return token;
+  }
+
+  public PublicKey getPublicKey() {
+    return publicKey;
+  }
+
+  public PrivateKey getPrivateKey() {
+    return privateKey;
+  }
+}
diff --git a/service/src/main/java/io/mifos/provisioner/internal/service/AuthenticationService.java
b/service/src/main/java/io/mifos/provisioner/internal/service/AuthenticationService.java
index 465380e..7aa175c 100644
--- a/service/src/main/java/io/mifos/provisioner/internal/service/AuthenticationService.java
+++ b/service/src/main/java/io/mifos/provisioner/internal/service/AuthenticationService.java
@@ -27,6 +27,7 @@ import com.datastax.driver.mapping.MappingManager;
 import io.mifos.anubis.token.TokenSerializationResult;
 import io.mifos.core.cassandra.core.CassandraSessionProvider;
 import io.mifos.core.lang.ServiceException;
+import io.mifos.provisioner.config.SystemProperties;
 import io.mifos.provisioner.internal.repository.UserEntity;
 import io.mifos.provisioner.api.v1.domain.AuthenticationResponse;
 import io.mifos.provisioner.api.v1.domain.PasswordPolicy;
@@ -58,8 +59,7 @@ public class AuthenticationService {
 
   @Value("${spring.application.name}")
   private String applicationName;
-  @Value("${system.token.ttl}")
-  private Integer ttl;
+  private final Integer ttl;
   private final Logger logger;
   private final CassandraSessionProvider cassandraSessionProvider;
   private final HashGenerator hashGenerator;
@@ -70,8 +70,10 @@ public class AuthenticationService {
   public AuthenticationService(@Qualifier(ProvisionerConstants.LOGGER_NAME) final Logger
logger,
                                final CassandraSessionProvider cassandraSessionProvider,
                                final HashGenerator hashGenerator,
-                               final TokenProvider tokenProvider) {
+                               final TokenProvider tokenProvider,
+                               final SystemProperties systemProperties) {
     super();
+    this.ttl = systemProperties.getToken().getTtl();
     this.logger = logger;
     this.cassandraSessionProvider = cassandraSessionProvider;
     this.hashGenerator = hashGenerator;
diff --git a/service/src/main/java/io/mifos/provisioner/internal/service/TenantService.java
b/service/src/main/java/io/mifos/provisioner/internal/service/TenantService.java
index aa499a7..b648f39 100644
--- a/service/src/main/java/io/mifos/provisioner/internal/service/TenantService.java
+++ b/service/src/main/java/io/mifos/provisioner/internal/service/TenantService.java
@@ -23,6 +23,7 @@ import io.mifos.provisioner.api.v1.domain.CassandraConnectionInfo;
 import io.mifos.provisioner.api.v1.domain.DatabaseConnectionInfo;
 import io.mifos.provisioner.api.v1.domain.Tenant;
 import io.mifos.provisioner.config.ProvisionerConstants;
+import io.mifos.provisioner.config.ProvisionerProperties;
 import io.mifos.provisioner.internal.repository.TenantCassandraRepository;
 import io.mifos.provisioner.internal.repository.TenantDAO;
 import io.mifos.provisioner.internal.repository.TenantEntity;
@@ -54,6 +55,7 @@ public class TenantService {
   private final TenantAuthorizationDataRepository tenantAuthorizationDataRepository;
   private final TenantCassandraRepository tenantCassandraRepository;
   private final IdentityServiceInitializer identityServiceInitializer;
+  private final ProvisionerProperties provisionerProperties;
 
 
   @Autowired
@@ -62,7 +64,8 @@ public class TenantService {
                        final TenantApplicationService tenantApplicationService,
                        @SuppressWarnings("SpringJavaAutowiringInspection") final TenantAuthorizationDataRepository
tenantAuthorizationDataRepository,
                        final TenantCassandraRepository tenantCassandraRepository,
-                       final IdentityServiceInitializer identityServiceInitializer) {
+                       final IdentityServiceInitializer identityServiceInitializer,
+                       final ProvisionerProperties provisionerProperties) {
     super();
     this.logger = logger;
     this.environment = environment;
@@ -70,6 +73,7 @@ public class TenantService {
     this.tenantAuthorizationDataRepository = tenantAuthorizationDataRepository;
     this.tenantCassandraRepository = tenantCassandraRepository;
     this.identityServiceInitializer = identityServiceInitializer;
+    this.provisionerProperties = provisionerProperties;
   }
 
   public void create(final Tenant tenant) {
@@ -78,8 +82,7 @@ public class TenantService {
   }
 
   private void initializeKeyspace(final @Nonnull Tenant tenant) {
-    final DataStoreOption dataStoreOption = DataStoreOption.valueOf(
-            this.environment.getProperty(DataStoreOption.PROPERTY_NAME, DataStoreOption.PROPERTY_DEFAULT_VALUE));
+    final DataStoreOption dataStoreOption = provisionerProperties.getDataStoreOption();
     if (dataStoreOption.isEnabled(DataStoreOption.CASSANDRA)) {
       final CassandraConnectionInfo cassandraConnectionInfo = tenant.getCassandraConnectionInfo();
 
@@ -127,8 +130,7 @@ public class TenantService {
   }
 
   private void fetchAllCassandra(final @Nonnull List<Tenant> tenants) {
-    final DataStoreOption dataStoreOption = DataStoreOption.valueOf(
-            this.environment.getProperty(DataStoreOption.PROPERTY_NAME, DataStoreOption.PROPERTY_DEFAULT_VALUE));
+    final DataStoreOption dataStoreOption = provisionerProperties.getDataStoreOption();
     if (dataStoreOption.isEnabled(DataStoreOption.CASSANDRA)) {
       List<TenantEntity> tenantEntities = tenantCassandraRepository.fetchAll();
 
@@ -158,16 +160,13 @@ public class TenantService {
   }
 
   private void fetchAllDatabase(final ArrayList<Tenant> tenants) {
-    final DataStoreOption dataStoreOption = DataStoreOption.valueOf(
-        this.environment.getProperty(DataStoreOption.PROPERTY_NAME, DataStoreOption.PROPERTY_DEFAULT_VALUE));
+    final DataStoreOption dataStoreOption = provisionerProperties.getDataStoreOption();
     if (dataStoreOption.isEnabled(DataStoreOption.RDBMS)) {
       if (tenants.size() > 0) {
         try (final Connection connection = DataSourceUtils.createProvisionerConnection(this.environment))
{
           for (final Tenant tenant : tenants) {
             final Optional<TenantDAO> optionalTenantDAO = TenantDAO.find(connection,
tenant.getIdentifier());
-            if (optionalTenantDAO.isPresent()) {
-              tenant.setDatabaseConnectionInfo(optionalTenantDAO.get().map());
-            }
+            optionalTenantDAO.ifPresent(tenantDAO -> tenant.setDatabaseConnectionInfo(tenantDAO.map()));
           }
         } catch (final SQLException sqlex) {
           this.logger.error(sqlex.getMessage(), sqlex);
@@ -191,8 +190,7 @@ public class TenantService {
   }
 
   private Optional<Tenant> findCassandra(final String identifier) {
-    final DataStoreOption dataStoreOption = DataStoreOption.valueOf(
-        this.environment.getProperty(DataStoreOption.PROPERTY_NAME, DataStoreOption.PROPERTY_DEFAULT_VALUE));
+    final DataStoreOption dataStoreOption = provisionerProperties.getDataStoreOption();
     if (dataStoreOption.isEnabled(DataStoreOption.CASSANDRA)) {
       return tenantCassandraRepository.get(identifier).map(x -> {
                 final Tenant tenant = new Tenant();
@@ -208,8 +206,7 @@ public class TenantService {
   }
 
   private Tenant findInDatabase(final @Nonnull Tenant tenant, final @Nonnull String identifier)
{
-    final DataStoreOption dataStoreOption = DataStoreOption.valueOf(
-        this.environment.getProperty(DataStoreOption.PROPERTY_NAME, DataStoreOption.PROPERTY_DEFAULT_VALUE));
+    final DataStoreOption dataStoreOption = provisionerProperties.getDataStoreOption();
     if (dataStoreOption.isEnabled(DataStoreOption.RDBMS)) {
       try (final Connection connection = DataSourceUtils.createProvisionerConnection(this.environment))
{
         final Optional<TenantDAO> optionalTenantDAO = TenantDAO.find(connection, identifier);
@@ -226,8 +223,7 @@ public class TenantService {
   }
 
   private void initializeDatabase(final Tenant tenant) {
-    final DataStoreOption dataStoreOption = DataStoreOption.valueOf(
-        this.environment.getProperty(DataStoreOption.PROPERTY_NAME, DataStoreOption.PROPERTY_DEFAULT_VALUE));
+    final DataStoreOption dataStoreOption = provisionerProperties.getDataStoreOption();
     if (dataStoreOption.isEnabled(DataStoreOption.RDBMS)) {
 
       try (
@@ -274,8 +270,7 @@ public class TenantService {
   }
 
   private void deleteFromCassandra(final @Nonnull String identifier) {
-    final DataStoreOption dataStoreOption = DataStoreOption.valueOf(
-        this.environment.getProperty(DataStoreOption.PROPERTY_NAME, DataStoreOption.PROPERTY_DEFAULT_VALUE));
+    final DataStoreOption dataStoreOption = provisionerProperties.getDataStoreOption();
     if (dataStoreOption.isEnabled(DataStoreOption.CASSANDRA)) {
       final Optional<TenantEntity> tenantEntity = tenantCassandraRepository.get(identifier);
       tenantEntity.ifPresent(x ->
@@ -287,8 +282,7 @@ public class TenantService {
   }
 
   private void deleteDatabase(final String identifier) {
-    final DataStoreOption dataStoreOption = DataStoreOption.valueOf(
-        this.environment.getProperty(DataStoreOption.PROPERTY_NAME, DataStoreOption.PROPERTY_DEFAULT_VALUE));
+    final DataStoreOption dataStoreOption = provisionerProperties.getDataStoreOption();
     if (dataStoreOption.isEnabled(DataStoreOption.RDBMS)) {
 
       try (final Connection provisionerConnection = DataSourceUtils.createProvisionerConnection(this.environment))
{
@@ -321,4 +315,4 @@ public class TenantService {
     cassandraConnectionInfo.setReplicas(tenantEntity.getReplicas());
     return cassandraConnectionInfo;
   }
-}
+}
\ No newline at end of file
diff --git a/service/src/main/java/io/mifos/provisioner/internal/service/applications/IdentityServiceInitializer.java
b/service/src/main/java/io/mifos/provisioner/internal/service/applications/IdentityServiceInitializer.java
index 054cdf4..e955a82 100644
--- a/service/src/main/java/io/mifos/provisioner/internal/service/applications/IdentityServiceInitializer.java
+++ b/service/src/main/java/io/mifos/provisioner/internal/service/applications/IdentityServiceInitializer.java
@@ -33,13 +33,13 @@ import io.mifos.identity.api.v1.domain.PermittableGroup;
 import io.mifos.permittedfeignclient.api.v1.client.ApplicationPermissionRequirements;
 import io.mifos.permittedfeignclient.api.v1.domain.ApplicationPermission;
 import io.mifos.provisioner.config.ProvisionerConstants;
+import io.mifos.provisioner.config.SystemProperties;
 import io.mifos.provisioner.internal.listener.EventExpectation;
 import io.mifos.provisioner.internal.listener.IdentityListener;
 import io.mifos.tool.crypto.HashGenerator;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 import org.springframework.util.Base64Utils;
 
@@ -58,9 +58,7 @@ public class IdentityServiceInitializer {
   private final ApplicationCallContextProvider applicationCallContextProvider;
   private final HashGenerator hashGenerator;
   private final Logger logger;
-
-  @Value("${system.domain}")
-  private String domain;
+  private final SystemProperties systemProperties;
 
   public class IdentityServiceInitializationResult {
     private final ApplicationSignatureSet signatureSet;
@@ -83,14 +81,16 @@ public class IdentityServiceInitializer {
 
   @Autowired
   public IdentityServiceInitializer(
-          final IdentityListener identityListener,
-          final ApplicationCallContextProvider applicationCallContextProvider,
-          final HashGenerator hashGenerator,
-          @Qualifier(ProvisionerConstants.LOGGER_NAME) final Logger logger) {
+      final IdentityListener identityListener,
+      final ApplicationCallContextProvider applicationCallContextProvider,
+      final HashGenerator hashGenerator,
+      @Qualifier(ProvisionerConstants.LOGGER_NAME) final Logger logger,
+      final SystemProperties systemProperties) {
     this.identityListener = identityListener;
     this.applicationCallContextProvider = applicationCallContextProvider;
     this.hashGenerator = hashGenerator;
     this.logger = logger;
+    this.systemProperties = systemProperties;
   }
 
   public IdentityServiceInitializationResult initializeIsis(
@@ -108,7 +108,7 @@ public class IdentityServiceInitializer {
       final String nonRandomPassword = "ChangeThisPassword";
       this.logger.debug("Initial password for tenant super user '{}' is '{}'. This should
be changed immediately.", tenantIdentifier, nonRandomPassword);
 
-      final byte[] salt = Base64Utils.encode(("antony" + tenantIdentifier + this.domain).getBytes());
+      final byte[] salt = Base64Utils.encode(("antony" + tenantIdentifier + this.systemProperties.getDomain()).getBytes());
 
       final String encodedPassword = Base64Utils.encodeToString(nonRandomPassword.getBytes());
 
diff --git a/service/src/main/java/io/mifos/provisioner/internal/util/DataStoreOption.java
b/service/src/main/java/io/mifos/provisioner/internal/util/DataStoreOption.java
index e399e87..93be681 100644
--- a/service/src/main/java/io/mifos/provisioner/internal/util/DataStoreOption.java
+++ b/service/src/main/java/io/mifos/provisioner/internal/util/DataStoreOption.java
@@ -16,14 +16,10 @@
 package io.mifos.provisioner.internal.util;
 
 public enum DataStoreOption {
-
   ALL,
   CASSANDRA,
   RDBMS;
 
-  public static final String PROPERTY_NAME = "provisioner.dataStoreOption";
-  public static final String PROPERTY_DEFAULT_VALUE = "ALL";
-
   public boolean isEnabled(final DataStoreOption dataStoreOption) {
     return this == ALL || this == dataStoreOption;
   }
diff --git a/service/src/main/resources/application.yaml b/service/src/main/resources/application.yaml
index a81fb64..a7cb682 100644
--- a/service/src/main/resources/application.yaml
+++ b/service/src/main/resources/application.yaml
@@ -40,16 +40,4 @@ mariadb:
   host: localhost
   port: 3306
   user: root
-  password: mysql
-
-system:
-  domain: mifos.io
-  dataStoreOption: ALL # possible values ALL, CASSANDRA, RDBMS
-  token:
-    ttl: 60
-  publicKey:
-    modulus: 18127979232651385577366788312577367809882840493309321947218444859734692803519322053118166861938127116063250592470870009582066787630638146674578444578864162263848522570791848618846268461050665448704495233021189752693589550011013299642312910333176350540133789870795905610030842272086304844975800905158104573387446873659409802855678797448220593733004510515015951396676579423158731638742125820984712730134997911206145523653040544527593404472473700394782702820939632486955986794980759
[...]
-    exponent: 65537
-  privateKey:
-    modulus: 21809400075083175962379439196636583774179615274445790777150424827246273931119109792802133084303807180138431535925399383578649396318773218549617349819790628104138404726662789219140029410886208143215123139141187664102456961514206129348474466709463496369346914088323798703048475755436555987223468203468553348311906047130177940096755897503185024960411862964691833266166883793657798456516931118758087021056538684569379725109236404256856114833181540549166096374949146511824467497157749
[...]
-    exponent: 2139642014781799413578815665329425805796195345660873344534634961460894500320787163339801865798552857857669093846009855145296308323102740222875928290909346208376463479111815761529864551325723848781847746088807546959933431187752563120969092743872415524914978086001597511956917156982389800806445384454909602336150973378503597186273413132363029529116825739138629507572323287073370284360633026515093536587446958309887954535219537879934808188484160721754899140220055724762318034081988
[...]
+  password: mysql
\ No newline at end of file
diff --git a/service/src/test/java/io/mifos/provisioner/config/SystemPropertiesTest.java b/service/src/test/java/io/mifos/provisioner/config/SystemPropertiesTest.java
new file mode 100644
index 0000000..2850be5
--- /dev/null
+++ b/service/src/test/java/io/mifos/provisioner/config/SystemPropertiesTest.java
@@ -0,0 +1,54 @@
+package io.mifos.provisioner.config;
+
+import io.mifos.core.lang.security.RsaKeyPairFactory;
+import io.mifos.core.test.domain.ValidationTest;
+import io.mifos.core.test.domain.ValidationTestCase;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author Myrle Krantz
+ */
+public class SystemPropertiesTest extends ValidationTest<SystemProperties> {
+  private static final RsaKeyPairFactory.KeyPairHolder keyPairHolder = RsaKeyPairFactory.createKeyPair();
+
+  public SystemPropertiesTest(ValidationTestCase<SystemProperties> testCase) {
+    super(testCase);
+  }
+
+  @Override
+  protected SystemProperties createValidTestSubject() {
+    final SystemProperties ret = new SystemProperties();
+    ret.getPrivateKey().setModulus(keyPairHolder.getPrivateKeyMod());
+    ret.getPrivateKey().setExponent(keyPairHolder.getPrivateKeyExp());
+    ret.getPublicKey().setTimestamp(keyPairHolder.getTimestamp());
+    ret.getPublicKey().setModulus(keyPairHolder.getPublicKeyMod());
+    ret.getPublicKey().setExponent(keyPairHolder.getPublicKeyExp());
+    return ret;
+  }
+
+  @Parameterized.Parameters
+  public static Collection testCases() {
+    final Collection<ValidationTestCase> ret = new ArrayList<>();
+    ret.add(new ValidationTestCase<SystemProperties>("basicCase")
+        .adjustment(x -> {})
+        .valid(true));
+    ret.add(new ValidationTestCase<SystemProperties>("missing private modulus")
+        .adjustment(x -> x.getPrivateKey().setModulus(null))
+        .valid(false));
+    ret.add(new ValidationTestCase<SystemProperties>("mismatched keys")
+        .adjustment(x -> {
+          final RsaKeyPairFactory.KeyPairHolder keyPairHolder = RsaKeyPairFactory.createKeyPair();
+          x.getPrivateKey().setModulus(keyPairHolder.getPrivateKeyMod());
+          x.getPrivateKey().setExponent(keyPairHolder.getPrivateKeyExp());
+        })
+        .valid(false));
+    ret.add(new ValidationTestCase<SystemProperties>("missing timestamp")
+        .adjustment(x -> x.getPublicKey().setTimestamp(null))
+        .valid(false));
+    return ret;
+  }
+
+}
\ No newline at end of file
diff --git a/service/src/test/java/io/mifos/provisioner/internal/service/applications/IdentityServiceInitializerTest.java
b/service/src/test/java/io/mifos/provisioner/internal/service/applications/IdentityServiceInitializerTest.java
index 9644fbf..09cddf4 100644
--- a/service/src/test/java/io/mifos/provisioner/internal/service/applications/IdentityServiceInitializerTest.java
+++ b/service/src/test/java/io/mifos/provisioner/internal/service/applications/IdentityServiceInitializerTest.java
@@ -21,6 +21,7 @@ import io.mifos.core.lang.AutoTenantContext;
 import io.mifos.identity.api.v1.client.IdentityManager;
 import io.mifos.identity.api.v1.client.PermittableGroupAlreadyExistsException;
 import io.mifos.identity.api.v1.domain.PermittableGroup;
+import io.mifos.provisioner.config.SystemProperties;
 import io.mifos.provisioner.internal.listener.IdentityListener;
 import org.junit.Assert;
 import org.junit.Test;
@@ -67,7 +68,8 @@ public class IdentityServiceInitializerTest {
     //noinspection unchecked
     when(anubisMock.getPermittableEndpoints()).thenThrow(IllegalStateException.class);
 
-    final List<PermittableEndpoint> ret = new IdentityServiceInitializer(identityListenerMock,
applicationCallContextProviderMock, null, loggerMock)
+    final SystemProperties systemProperties = new SystemProperties();
+    final List<PermittableEndpoint> ret = new IdentityServiceInitializer(identityListenerMock,
applicationCallContextProviderMock, null, loggerMock, systemProperties)
             .getPermittables("blah");
 
     Assert.assertEquals(ret, Collections.emptyList());
@@ -100,7 +102,8 @@ public class IdentityServiceInitializerTest {
     doReturn(reorderedGroup1).when(identityServiceMock).getPermittableGroup(group1.getIdentifier());
 
     try (final AutoTenantContext ignored = new AutoTenantContext("blah")) {
-      new IdentityServiceInitializer(identityListenerMock, null, null, loggerMock).createOrFindPermittableGroup(identityServiceMock,
group1);
+      final SystemProperties systemProperties = new SystemProperties();
+      new IdentityServiceInitializer(identityListenerMock, null, null, loggerMock, systemProperties).createOrFindPermittableGroup(identityServiceMock,
group1);
     }
   }
 
@@ -114,7 +117,8 @@ public class IdentityServiceInitializerTest {
     doReturn(changedGroup1).when(identityServiceMock).getPermittableGroup(group1.getIdentifier());
 
     try (final AutoTenantContext ignored = new AutoTenantContext("blah")) {
-      new IdentityServiceInitializer(identityListenerMock, null, null, loggerMock).createOrFindPermittableGroup(identityServiceMock,
group1);
+      final SystemProperties systemProperties = new SystemProperties();
+      new IdentityServiceInitializer(identityListenerMock, null, null, loggerMock, systemProperties).createOrFindPermittableGroup(identityServiceMock,
group1);
     }
 
     verify(loggerMock).error(anyString(), anyString(), anyString());
@@ -130,7 +134,8 @@ public class IdentityServiceInitializerTest {
     doReturn(changedGroup1).when(identityServiceMock).getPermittableGroup(group1.getIdentifier());
 
     try (final AutoTenantContext ignored = new AutoTenantContext("blah")) {
-      new IdentityServiceInitializer(identityListenerMock, null, null, loggerMock).createOrFindPermittableGroup(identityServiceMock,
group1);
+      final SystemProperties systemProperties = new SystemProperties();
+      new IdentityServiceInitializer(identityListenerMock, null, null, loggerMock, systemProperties).createOrFindPermittableGroup(identityServiceMock,
group1);
     }
 
     verify(loggerMock).error(anyString(), anyString(), anyString(), isA(IllegalStateException.class));

-- 
To stop receiving notification emails like this one, please contact
myrle@apache.org.

Mime
View raw message