Merge branch 'develop' of https://github.com/mifosio/provisioner into develop
diff --git a/api/src/main/java/io/mifos/provisioner/api/v1/domain/DatabaseConnectionInfo.java b/api/src/main/java/io/mifos/provisioner/api/v1/domain/DatabaseConnectionInfo.java
index 762ad32..3e375bf 100644
--- a/api/src/main/java/io/mifos/provisioner/api/v1/domain/DatabaseConnectionInfo.java
+++ b/api/src/main/java/io/mifos/provisioner/api/v1/domain/DatabaseConnectionInfo.java
@@ -17,6 +17,7 @@
 
 import javax.annotation.Nonnull;
 import javax.validation.constraints.NotNull;
+import java.util.Objects;
 
 @SuppressWarnings({"unused", "WeakerAccess"})
 public final class DatabaseConnectionInfo {
@@ -90,4 +91,34 @@
   public void setPassword(@Nonnull final String password) {
     this.password = password;
   }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    DatabaseConnectionInfo that = (DatabaseConnectionInfo) o;
+    return Objects.equals(driverClass, that.driverClass) &&
+            Objects.equals(databaseName, that.databaseName) &&
+            Objects.equals(host, that.host) &&
+            Objects.equals(port, that.port) &&
+            Objects.equals(user, that.user) &&
+            Objects.equals(password, that.password);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(driverClass, databaseName, host, port, user, password);
+  }
+
+  @Override
+  public String toString() {
+    return "DatabaseConnectionInfo{" +
+            "driverClass='" + driverClass + '\'' +
+            ", databaseName='" + databaseName + '\'' +
+            ", host='" + host + '\'' +
+            ", port='" + port + '\'' +
+            ", user='" + user + '\'' +
+            ", password='" + password + '\'' +
+            '}';
+  }
 }
diff --git a/api/src/main/java/io/mifos/provisioner/api/v1/domain/Tenant.java b/api/src/main/java/io/mifos/provisioner/api/v1/domain/Tenant.java
index da7a1ad..fc186c7 100644
--- a/api/src/main/java/io/mifos/provisioner/api/v1/domain/Tenant.java
+++ b/api/src/main/java/io/mifos/provisioner/api/v1/domain/Tenant.java
@@ -16,6 +16,7 @@
 package io.mifos.provisioner.api.v1.domain;
 
 import javax.validation.constraints.NotNull;
+import java.util.Objects;
 
 @SuppressWarnings("unused")
 public final class Tenant {
@@ -73,4 +74,32 @@
   public void setDatabaseConnectionInfo(DatabaseConnectionInfo databaseConnectionInfo) {
     this.databaseConnectionInfo = databaseConnectionInfo;
   }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) return true;
+    if (o == null || getClass() != o.getClass()) return false;
+    Tenant tenant = (Tenant) o;
+    return Objects.equals(identifier, tenant.identifier) &&
+            Objects.equals(name, tenant.name) &&
+            Objects.equals(description, tenant.description) &&
+            Objects.equals(cassandraConnectionInfo, tenant.cassandraConnectionInfo) &&
+            Objects.equals(databaseConnectionInfo, tenant.databaseConnectionInfo);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(identifier, name, description, cassandraConnectionInfo, databaseConnectionInfo);
+  }
+
+  @Override
+  public String toString() {
+    return "Tenant{" +
+            "identifier='" + identifier + '\'' +
+            ", name='" + name + '\'' +
+            ", description='" + description + '\'' +
+            ", cassandraConnectionInfo=" + cassandraConnectionInfo +
+            ", databaseConnectionInfo=" + databaseConnectionInfo +
+            '}';
+  }
 }
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 3896bf8..6375a2c 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
@@ -16,6 +16,7 @@
 package io.mifos.provisioner.tenant;
 
 import io.mifos.anubis.api.v1.client.Anubis;
+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;
@@ -25,6 +26,7 @@
 import io.mifos.core.api.util.ApiConstants;
 import io.mifos.core.api.util.ApiFactory;
 import io.mifos.core.lang.AutoTenantContext;
+import io.mifos.core.lang.security.RsaKeyPairFactory;
 import io.mifos.core.test.env.TestEnvironment;
 import io.mifos.identity.api.v1.client.IdentityManager;
 import io.mifos.identity.api.v1.domain.PermittableGroup;
@@ -107,7 +109,7 @@
   private static ProvisionerMariaDBInitializer mariaDBInitializer = new ProvisionerMariaDBInitializer();
   private static ProvisionerCassandraInitializer cassandraInitializer = new ProvisionerCassandraInitializer();
   private static SystemSecurityEnvironment systemSecurityEnvironment
-          = new SystemSecurityEnvironment(testEnvironment.getSystemPublicKey(), testEnvironment.getSystemPrivateKey());
+          = new SystemSecurityEnvironment(testEnvironment.getSystemKeyTimestamp(), testEnvironment.getSystemPublicKey(), testEnvironment.getSystemPrivateKey());
 
   @ClassRule
   public static TestRule orderClassRules = RuleChain
@@ -168,27 +170,34 @@
     }
   }
 
-  private class VerifyIsisInitializeContext implements Answer<Signature> {
+  private class VerifyIsisInitializeContext implements Answer<ApplicationSignatureSet> {
 
+    private final String keyTimestamp;
     private final BigInteger modulus;
     private final BigInteger exponent;
 
     private boolean validSecurityContext = false;
 
-    VerifyIsisInitializeContext(final BigInteger modulus, final BigInteger exponent) {
+    VerifyIsisInitializeContext(final String keyTimestamp, final BigInteger modulus, final BigInteger exponent) {
+      this.keyTimestamp = keyTimestamp;
       this.modulus = modulus;
       this.exponent = exponent;
     }
 
     @Override
-    public Signature answer(final InvocationOnMock invocation) throws Throwable {
+    public ApplicationSignatureSet answer(final InvocationOnMock invocation) throws Throwable {
       validSecurityContext = systemSecurityEnvironment.isValidSystemSecurityContext("identity", "1", Fixture.TENANT_IDENTIFIER);
 
       final Signature fakeSignature = new Signature();
       fakeSignature.setPublicKeyMod(modulus);
       fakeSignature.setPublicKeyExp(exponent);
 
-      return fakeSignature;
+      final ApplicationSignatureSet ret = new ApplicationSignatureSet();
+      ret.setTimestamp(keyTimestamp);
+      ret.setApplicationSignature(fakeSignature);
+      ret.setIdentityManagerSignature(fakeSignature);
+
+      return ret;
     }
 
     boolean isValidSecurityContext() {
@@ -216,6 +225,32 @@
     }
   }
 
+  private class VerifyCreateSignatureSetContext implements Answer<ApplicationSignatureSet> {
+
+    private boolean validSecurityContext = false;
+    final private String target;
+
+    private VerifyCreateSignatureSetContext(final String target) {
+      this.target = target;
+    }
+
+    @Override
+    public ApplicationSignatureSet answer(final InvocationOnMock invocation) throws Throwable {
+      final String timestamp = invocation.getArgumentAt(0, String.class);
+      final Signature identityManagerSignature = invocation.getArgumentAt(1, Signature.class);
+      validSecurityContext = systemSecurityEnvironment.isValidSystemSecurityContext(target, "1", Fixture.TENANT_IDENTIFIER);
+      final RsaKeyPairFactory.KeyPairHolder keys = RsaKeyPairFactory.createKeyPair();
+      return new ApplicationSignatureSet(
+              timestamp,
+              new Signature(keys.getPublicKeyMod(), keys.getPublicKeyExp()),
+              identityManagerSignature);
+    }
+
+    boolean isValidSecurityContext() {
+      return validSecurityContext;
+    }
+  }
+
 
   private class VerifyAnubisPermittablesContext implements Answer<List<PermittableEndpoint>> {
 
@@ -265,6 +300,7 @@
     final VerifyIsisInitializeContext verifyInitializeContextAndReturnSignature;
     try (final AutoTenantContext ignored = new AutoTenantContext(Fixture.TENANT_IDENTIFIER)) {
       verifyInitializeContextAndReturnSignature = new VerifyIsisInitializeContext(
+              systemSecurityEnvironment.tenantKeyTimestamp(),
               systemSecurityEnvironment.tenantPublicKey().getModulus(),
               systemSecurityEnvironment.tenantPublicKey().getPublicExponent());
     }
@@ -282,7 +318,7 @@
       Assert.assertNotNull(identityServiceAdminInitialization.getAdminPassword());
     }
 
-    verify(applicationCallContextProviderSpy).getApplicationCallContext(Fixture.TENANT_IDENTIFIER, "identity-v1");
+    verify(applicationCallContextProviderSpy, atMost(2)).getApplicationCallContext(Fixture.TENANT_IDENTIFIER, "identity-v1");
 
 
     //Create horus application.
@@ -309,12 +345,15 @@
     final PermittableEndpoint mPermittableEndpoint = new PermittableEndpoint("/m/n", "GET", "m");
 
     final VerifyAnubisInitializeContext verifyAnubisInitializeContext;
+    final VerifyCreateSignatureSetContext verifyCreateSignatureSetContext;
     final VerifyAnubisPermittablesContext verifyAnubisPermittablesContext;
     try (final AutoTenantContext ignored = new AutoTenantContext(Fixture.TENANT_IDENTIFIER)) {
       verifyAnubisInitializeContext = new VerifyAnubisInitializeContext("office");
+      verifyCreateSignatureSetContext = new VerifyCreateSignatureSetContext("office");
       verifyAnubisPermittablesContext = new VerifyAnubisPermittablesContext(Arrays.asList(xxPermittableEndpoint, xxPermittableEndpoint, xyPermittableEndpoint, xyGetPermittableEndpoint, mPermittableEndpoint));
     }
-    doAnswer(verifyAnubisInitializeContext).when(anubisMock).initialize(anyObject(), anyObject());
+    doAnswer(verifyAnubisInitializeContext).when(anubisMock).initializeResources();
+    doAnswer(verifyCreateSignatureSetContext).when(anubisMock).createSignatureSet(anyString(), anyObject());
     doAnswer(verifyAnubisPermittablesContext).when(anubisMock).getPermittableEndpoints();
 
     {
@@ -330,6 +369,7 @@
     verify(identityServiceMock).createPermittableGroup(new PermittableGroup("m", Collections.singletonList(mPermittableEndpoint)));
 
     Assert.assertTrue(verifyAnubisInitializeContext.isValidSecurityContext());
+    Assert.assertTrue(verifyCreateSignatureSetContext.isValidSecurityContext());
     Assert.assertTrue(verifyAnubisPermittablesContext.isValidSecurityContext());
   }
 }
diff --git a/component-test/src/main/java/io/mifos/provisioner/tenant/TestTenants.java b/component-test/src/main/java/io/mifos/provisioner/tenant/TestTenants.java
index 270e5be..73d8af8 100644
--- a/component-test/src/main/java/io/mifos/provisioner/tenant/TestTenants.java
+++ b/component-test/src/main/java/io/mifos/provisioner/tenant/TestTenants.java
@@ -79,6 +79,7 @@
     provisioner.createTenant(tenant);
     final Tenant foundTenant = provisioner.getTenant(tenant.getIdentifier());
     Assert.assertNotNull(foundTenant);
+    Assert.assertEquals(tenant, foundTenant);
   }
 
   @Test(expected = NotFoundException.class)
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 037f533..b2264aa 100644
--- a/service/src/main/java/io/mifos/provisioner/config/ProvisionerServiceConfig.java
+++ b/service/src/main/java/io/mifos/provisioner/config/ProvisionerServiceConfig.java
@@ -16,14 +16,10 @@
 package io.mifos.provisioner.config;
 
 import io.mifos.anubis.config.EnableAnubis;
-import io.mifos.anubis.config.TenantSignatureProvider;
-import io.mifos.anubis.repository.TenantAuthorizationDataRepository;
 import io.mifos.anubis.token.SystemAccessTokenSerializer;
 import io.mifos.core.api.util.ApiFactory;
 import io.mifos.core.async.config.EnableAsync;
 import io.mifos.core.cassandra.config.EnableCassandra;
-import io.mifos.core.cassandra.core.CassandraSessionProvider;
-import io.mifos.core.lang.ApplicationName;
 import io.mifos.core.lang.config.EnableApplicationName;
 import io.mifos.core.lang.config.EnableServiceException;
 import io.mifos.core.mariadb.config.EnableMariaDB;
@@ -50,7 +46,7 @@
 })
 @EnableCrypto
 @EnableAsync
-@EnableAnubis(storeTenantKeysAtInitialization = false)
+@EnableAnubis(provideSignatureRestController = false)
 @EnableMariaDB
 @EnableCassandra
 @EnableServiceException
@@ -70,6 +66,7 @@
   public TokenProvider tokenProvider(final Environment environment,
                                      @SuppressWarnings("SpringJavaAutowiringInspection") final SystemAccessTokenSerializer tokenSerializer) {
     return new TokenProvider(
+        environment.getProperty("system.publicKey.timestamp"),
         new BigInteger(environment.getProperty("system.privateKey.modulus")),
         new BigInteger(environment.getProperty("system.privateKey.exponent")), tokenSerializer);
   }
@@ -78,20 +75,4 @@
   public ApiFactory apiFactory(@Qualifier(ProvisionerConstants.LOGGER_NAME) final Logger logger) {
     return new ApiFactory(logger);
   }
-
-  @Bean
-  public TenantSignatureProvider tenantSignatureProvider()
-  {
-    return tenant -> {
-      throw new IllegalArgumentException("no io.mifos.provisioner.tenant signatures here.");
-    };
-  }
-
-  @Bean
-  public TenantAuthorizationDataRepository tenantAuthorizationDataRepository(
-          final ApplicationName applicationName,
-          final CassandraSessionProvider cassandraSessionProvider)
-  {
-    return new TenantAuthorizationDataRepository(applicationName, cassandraSessionProvider);
-  }
 }
diff --git a/service/src/main/java/io/mifos/provisioner/internal/service/TenantApplicationService.java b/service/src/main/java/io/mifos/provisioner/internal/service/TenantApplicationService.java
index 222c4e4..6ac79ff 100644
--- a/service/src/main/java/io/mifos/provisioner/internal/service/TenantApplicationService.java
+++ b/service/src/main/java/io/mifos/provisioner/internal/service/TenantApplicationService.java
@@ -18,18 +18,16 @@
 import com.datastax.driver.core.ResultSet;
 import com.datastax.driver.mapping.Mapper;
 import com.datastax.driver.mapping.Result;
-
-import io.mifos.anubis.api.v1.TokenConstants;
+import io.mifos.anubis.api.v1.domain.ApplicationSignatureSet;
 import io.mifos.anubis.api.v1.domain.Signature;
-import io.mifos.anubis.repository.TenantAuthorizationDataRepository;
+import io.mifos.anubis.config.TenantSignatureRepository;
 import io.mifos.core.cassandra.core.CassandraSessionProvider;
 import io.mifos.core.lang.AutoTenantContext;
 import io.mifos.core.lang.ServiceException;
 import io.mifos.provisioner.internal.repository.ApplicationEntity;
-import io.mifos.provisioner.internal.repository.TenantCassandraRepository;
 import io.mifos.provisioner.internal.repository.TenantApplicationEntity;
+import io.mifos.provisioner.internal.repository.TenantCassandraRepository;
 import io.mifos.provisioner.internal.repository.TenantEntity;
-
 import io.mifos.provisioner.internal.service.applications.AnubisInitializer;
 import io.mifos.provisioner.internal.service.applications.IdentityServiceInitializer;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -38,7 +36,10 @@
 import org.springframework.util.Assert;
 
 import javax.annotation.Nonnull;
-import java.util.*;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 @Component
@@ -47,20 +48,20 @@
   private final CassandraSessionProvider cassandraSessionProvider;
   private final AnubisInitializer anubisInitializer;
   private final IdentityServiceInitializer identityServiceInitializer;
-  private final TenantAuthorizationDataRepository tenantAuthorizationDataRepository;
+  private final TenantSignatureRepository tenantSignatureRepository;
   private final TenantCassandraRepository tenantCassandraRepository;
 
   @Autowired
   public TenantApplicationService(final CassandraSessionProvider cassandraSessionProvider,
                                   final AnubisInitializer anubisInitializer,
                                   final IdentityServiceInitializer identityServiceInitializer,
-                                  final TenantAuthorizationDataRepository tenantAuthorizationDataRepository,
+                                  @SuppressWarnings("SpringJavaAutowiringInspection") final TenantSignatureRepository tenantSignatureRepository,
                                   final TenantCassandraRepository tenantCassandraRepository) {
     super();
     this.cassandraSessionProvider = cassandraSessionProvider;
     this.anubisInitializer = anubisInitializer;
     this.identityServiceInitializer = identityServiceInitializer;
-    this.tenantAuthorizationDataRepository = tenantAuthorizationDataRepository;
+    this.tenantSignatureRepository = tenantSignatureRepository;
     this.tenantCassandraRepository = tenantCassandraRepository;
   }
 
@@ -80,7 +81,7 @@
 
       initializeIsis(x, applicationNameToUriPairs);
 
-      getIsisSignature(x).ifPresent(y -> initializeAnubis(x, y, applicationNameToUriPairs));
+      getLatestIdentityManagerSignatureSet(x).ifPresent(y -> initializeAnubis(x, y.getTimestamp(), y.getIdentityManagerSignature(), applicationNameToUriPairs));
     });
 
     tenantEntity.orElseThrow(
@@ -127,9 +128,9 @@
     }
   }
 
-  private Optional<Signature> getIsisSignature(final @Nonnull TenantEntity tenantEntity) {
+  private Optional<ApplicationSignatureSet> getLatestIdentityManagerSignatureSet(final @Nonnull TenantEntity tenantEntity) {
     try (final AutoTenantContext ignored = new AutoTenantContext(tenantEntity.getIdentifier())) {
-      return tenantAuthorizationDataRepository.getSignature(TokenConstants.VERSION);
+      return tenantSignatureRepository.getLatestSignatureSet();
     }
   }
 
@@ -146,6 +147,7 @@
 
   private void initializeAnubis(
           final @Nonnull TenantEntity tenantEntity,
+          final @Nonnull String keyTimestamp,
           final @Nonnull Signature identityServiceTenantSignature,
           final @Nonnull Set<ApplicationNameToUriPair> applicationNameToUriPairs) {
     applicationNameToUriPairs.forEach(applicationNameUriPair ->
@@ -153,6 +155,7 @@
                     tenantEntity.getIdentifier(),
                     applicationNameUriPair.name,
                     applicationNameUriPair.uri,
+                    keyTimestamp,
                     identityServiceTenantSignature)
     );
   }
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 7409f00..aa499a7 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
@@ -15,20 +15,20 @@
  */
 package io.mifos.provisioner.internal.service;
 
-import io.mifos.anubis.api.v1.domain.Signature;
+import io.mifos.anubis.api.v1.domain.ApplicationSignatureSet;
 import io.mifos.anubis.repository.TenantAuthorizationDataRepository;
 import io.mifos.core.lang.AutoTenantContext;
 import io.mifos.core.lang.ServiceException;
-import io.mifos.provisioner.internal.repository.TenantCassandraRepository;
-import io.mifos.provisioner.internal.util.DataSourceUtils;
-import io.mifos.provisioner.internal.util.DataStoreOption;
 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.internal.repository.TenantCassandraRepository;
 import io.mifos.provisioner.internal.repository.TenantDAO;
 import io.mifos.provisioner.internal.repository.TenantEntity;
 import io.mifos.provisioner.internal.service.applications.IdentityServiceInitializer;
+import io.mifos.provisioner.internal.util.DataSourceUtils;
+import io.mifos.provisioner.internal.util.DataStoreOption;
 import org.slf4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -60,7 +60,7 @@
   public TenantService(@Qualifier(ProvisionerConstants.LOGGER_NAME) final Logger logger,
                        final Environment environment,
                        final TenantApplicationService tenantApplicationService,
-                       final TenantAuthorizationDataRepository tenantAuthorizationDataRepository,
+                       @SuppressWarnings("SpringJavaAutowiringInspection") final TenantAuthorizationDataRepository tenantAuthorizationDataRepository,
                        final TenantCassandraRepository tenantCassandraRepository,
                        final IdentityServiceInitializer identityServiceInitializer) {
     super();
@@ -110,10 +110,10 @@
     });
 
     IdentityServiceInitializer.IdentityServiceInitializationResult identityServiceInitializationResult = identityServiceInitializer.initializeIsis(tenantIdentifier, identityManagerAppName, identityManagerUri);
-    final Signature identityServiceTenantSignature = identityServiceInitializationResult.getSignature();
+    final ApplicationSignatureSet identityServiceTenantSignatureSet = identityServiceInitializationResult.getSignatureSet();
 
     try (final AutoTenantContext ignored = new AutoTenantContext(tenantIdentifier)) {
-      tenantAuthorizationDataRepository.provisionTenant(identityServiceTenantSignature.getPublicKeyMod(), identityServiceTenantSignature.getPublicKeyExp());
+      tenantAuthorizationDataRepository.createSignatureSet(identityServiceTenantSignatureSet.getTimestamp(), identityServiceTenantSignatureSet.getIdentityManagerSignature());
     }
 
     return identityServiceInitializationResult.getAdminPassword();
diff --git a/service/src/main/java/io/mifos/provisioner/internal/service/applications/AnubisInitializer.java b/service/src/main/java/io/mifos/provisioner/internal/service/applications/AnubisInitializer.java
index c3f31de..c30876e 100644
--- a/service/src/main/java/io/mifos/provisioner/internal/service/applications/AnubisInitializer.java
+++ b/service/src/main/java/io/mifos/provisioner/internal/service/applications/AnubisInitializer.java
@@ -46,12 +46,14 @@
   public void initializeAnubis(final @Nonnull String tenantIdentifier,
                                final @Nonnull String applicationName,
                                final @Nonnull String uri,
+                               final @Nonnull String keyTimestamp,
                                final @Nonnull Signature signature) {
     try (final AutoCloseable ignored
                  = this.applicationCallContextProvider.getApplicationCallContext(tenantIdentifier, applicationName))
     {
       final Anubis anubis = this.applicationCallContextProvider.getApplication(Anubis.class, uri);
-      anubis.initialize(signature.getPublicKeyMod(), signature.getPublicKeyExp());
+      anubis.createSignatureSet(keyTimestamp, signature);
+      anubis.initializeResources();
       logger.info("Anubis initialization for io.mifos.provisioner.tenant '{}' and application '{}' succeeded with signature '{}'.",
               tenantIdentifier, applicationName, signature);
 
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 c1f72fe..4ffb7d8 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
@@ -17,8 +17,8 @@
 
 
 import io.mifos.anubis.api.v1.client.Anubis;
+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.identity.api.v1.client.IdentityManager;
 import io.mifos.identity.api.v1.client.PermittableGroupAlreadyExistsException;
 import io.mifos.identity.api.v1.client.TenantAlreadyInitializedException;
@@ -51,22 +51,22 @@
   private String domain;
 
   public class IdentityServiceInitializationResult {
-    private final Signature signature;
+    private final ApplicationSignatureSet signatureSet;
     @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
     private final Optional<String> adminPassword;
 
-    private IdentityServiceInitializationResult(final Signature signature, final String adminPassword) {
-      this.signature = signature;
+    private IdentityServiceInitializationResult(final ApplicationSignatureSet signatureSet, final String adminPassword) {
+      this.signatureSet = signatureSet;
       this.adminPassword = Optional.of(adminPassword);
     }
 
-    private IdentityServiceInitializationResult(final Signature signature) {
-      this.signature = signature;
+    private IdentityServiceInitializationResult(final ApplicationSignatureSet signatureSet) {
+      this.signatureSet = signatureSet;
       this.adminPassword = Optional.empty();
     }
 
-    public Signature getSignature() {
-      return signature;
+    public ApplicationSignatureSet getSignatureSet() {
+      return signatureSet;
     }
 
     public Optional<String> getAdminPassword() {
@@ -103,16 +103,17 @@
         final byte[] hash = this.hashGenerator.hash(encodedPassword, salt, ProvisionerConstants.ITERATION_COUNT, ProvisionerConstants.HASH_LENGTH);
         final String encodedPasswordHash = Base64Utils.encodeToString(hash);
 
-        final Signature signature = identityService.initialize(encodedPasswordHash);
-        logger.info("Isis initialization for io.mifos.provisioner.tenant '{}' succeeded with signature '{}'.", tenantIdentifier, signature);
+        final ApplicationSignatureSet signatureSet = identityService.initialize(encodedPasswordHash);
+        logger.info("Isis initialization for io.mifos.provisioner.tenant '{}' succeeded with signature set '{}'.", tenantIdentifier, signatureSet);
 
-        return new IdentityServiceInitializationResult(signature, encodedPasswordHash);
+        return new IdentityServiceInitializationResult(signatureSet, encodedPasswordHash);
       } catch (final TenantAlreadyInitializedException aiex) {
-        final Signature signature = identityService.getSignature();
-        logger.info("Isis initialization for io.mifos.provisioner.tenant '{}' failed because it was already initialized.  Pre-existing signature '{}'.",
-                tenantIdentifier, signature);
+        final Anubis identityManagerAnubisApi = applicationCallContextProvider.getApplication(Anubis.class, identityManagerUri);
+        final ApplicationSignatureSet signatureSet = identityManagerAnubisApi.getLatestSignatureSet();
+        logger.info("Isis initialization for io.mifos.provisioner.tenant '{}' failed because it was already initialized.  Pre-existing signature set '{}'.",
+                tenantIdentifier, signatureSet);
 
-        return new IdentityServiceInitializationResult(signature);
+        return new IdentityServiceInitializationResult(signatureSet);
       }
     } catch (final Exception e) {
       throw new IllegalStateException(e);
diff --git a/service/src/main/java/io/mifos/provisioner/internal/util/TokenProvider.java b/service/src/main/java/io/mifos/provisioner/internal/util/TokenProvider.java
index a1081b7..fc3d6ea 100644
--- a/service/src/main/java/io/mifos/provisioner/internal/util/TokenProvider.java
+++ b/service/src/main/java/io/mifos/provisioner/internal/util/TokenProvider.java
@@ -26,10 +26,12 @@
 import java.util.concurrent.TimeUnit;
 
 public class TokenProvider {
+  private final String keyTimestamp;
   private PrivateKey privateKey;
   private final SystemAccessTokenSerializer tokenSerializer;
 
   public TokenProvider(
+      final String keyTimestamp,
       final BigInteger privateKeyModulus,
       final BigInteger privateKeyExponent,
       final SystemAccessTokenSerializer tokenSerializer) {
@@ -37,6 +39,7 @@
     this.tokenSerializer = tokenSerializer;
 
     try {
+      this.keyTimestamp = keyTimestamp;
       final KeyFactory keyFactory = KeyFactory.getInstance("RSA");
 
       final RSAPrivateKeySpec rsaPrivateKeySpec
@@ -48,8 +51,13 @@
     }
   }
 
-  public TokenSerializationResult createToken(final String subject, final String audience, final long ttl, final TimeUnit timeUnit) {
+  public TokenSerializationResult createToken(
+          final String subject,
+          final String audience,
+          final long ttl,
+          final TimeUnit timeUnit) {
     SystemAccessTokenSerializer.Specification specification = new SystemAccessTokenSerializer.Specification();
+    specification.setKeyTimestamp(keyTimestamp);
     specification.setTenant(subject);
     specification.setTargetApplicationName(audience);
     specification.setSecondsToLive(timeUnit.toSeconds(ttl));