Merge pull request #13 from myrle-krantz/develop
Improved configuration validation
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 @@
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 @@
@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 @@
.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.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.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 @@
* @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 @@
.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 @@
[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/config/KeysValid.java b/service/src/main/java/io/mifos/provisioner/config/KeysValid.java
new file mode 100644
index 0000000..9a582e3
--- /dev/null
+++ b/service/src/main/java/io/mifos/provisioner/config/KeysValid.java
@@ -0,0 +1,38 @@
+/*
+ * 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.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.*;
+
+/**
+ * @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.";
+
+ Class<?>[] groups() default {};
+
+ Class<? extends Payload>[] payload() default {};
+}
diff --git a/service/src/main/java/io/mifos/provisioner/config/ProvisionerProperties.java b/service/src/main/java/io/mifos/provisioner/config/ProvisionerProperties.java
new file mode 100644
index 0000000..c007e6b
--- /dev/null
+++ b/service/src/main/java/io/mifos/provisioner/config/ProvisionerProperties.java
@@ -0,0 +1,38 @@
+/*
+ * 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 io.mifos.provisioner.internal.util.DataStoreOption;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import javax.validation.Valid;
+
+/**
+ * @author Myrle Krantz
+ */
+@ConfigurationProperties(prefix = "provisioner")
+public class ProvisionerProperties {
+ @Valid
+ private DataStoreOption dataStoreOption = DataStoreOption.ALL;
+
+ public DataStoreOption getDataStoreOption() {
+ return 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.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 @@
@EnableCassandra
@EnableServiceException
@EnableApplicationName
-@EnableConfigurationProperties({ProvisionerActiveMQProperties.class})
+@EnableConfigurationProperties({ProvisionerActiveMQProperties.class, ProvisionerProperties.class, SystemProperties.class})
public class ProvisionerServiceConfig extends WebMvcConfigurerAdapter {
public ProvisionerServiceConfig() {
@@ -73,15 +69,15 @@
}
@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 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 @@
@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 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.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 @@
private final TenantAuthorizationDataRepository tenantAuthorizationDataRepository;
private final TenantCassandraRepository tenantCassandraRepository;
private final IdentityServiceInitializer identityServiceInitializer;
+ private final ProvisionerProperties provisionerProperties;
@Autowired
@@ -62,7 +64,8 @@
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 @@
this.tenantAuthorizationDataRepository = tenantAuthorizationDataRepository;
this.tenantCassandraRepository = tenantCassandraRepository;
this.identityServiceInitializer = identityServiceInitializer;
+ this.provisionerProperties = provisionerProperties;
}
public void create(final Tenant tenant) {
@@ -78,8 +82,7 @@
}
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 @@
}
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 @@
}
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 @@
}
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 @@
}
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 @@
}
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 @@
}
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 @@
}
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 @@
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.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 @@
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 @@
@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 @@
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 @@
host: localhost
port: 3306
user: root
- password: mysql
-
-system:
- domain: mifos.io
- dataStoreOption: ALL # possible values ALL, CASSANDRA, RDBMS
- token:
- ttl: 60
- publicKey:
- modulus: 18127979232651385577366788312577367809882840493309321947218444859734692803519322053118166861938127116063250592470870009582066787630638146674578444578864162263848522570791848618846268461050665448704495233021189752693589550011013299642312910333176350540133789870795905610030842272086304844975800905158104573387446873659409802855678797448220593733004510515015951396676579423158731638742125820984712730134997911206145523653040544527593404472473700394782702820939632486955986794980759384390018112339579933792560176712866026367677322796321647134284719444328549297157384676116482642453484323266505460321391509718183529003027
- exponent: 65537
- privateKey:
- modulus: 21809400075083175962379439196636583774179615274445790777150424827246273931119109792802133084303807180138431535925399383578649396318773218549617349819790628104138404726662789219140029410886208143215123139141187664102456961514206129348474466709463496369346914088323798703048475755436555987223468203468553348311906047130177940096755897503185024960411862964691833266166883793657798456516931118758087021056538684569379725109236404256856114833181540549166096374949146511824467497157749867316091008771844300966541141405006700507801915029195150283858166375276566250188795476921959861592976559593357049441618590308131364265579
- exponent: 21396420147817994135788156653294258057961953456608733445346349614608945003207871633398018657985528578576690938460098551452963083231027402228759282909093462083764634791118157615298645513257238487818477460888075469599334311877525631209690927438724155249149780860015975119569171569823898008064453844549096023361509733785035971862734131323630295291168257391386295075723232870733702843606330265150935365874469583098879545352195378799348081884841607217548991402200557247623180340819881037965267728865652559122765679109621265487390005859372586004312679150166716877896425042632003598727801328367204703595952127984368962313153
+ 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.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 @@
//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 @@
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 @@
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 @@
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));