Skip to content
Permalink
Browse files
Introduced TestKeyRotation and made changes to get it working.
  • Loading branch information
mifosio-04-04-2018 committed Apr 12, 2017
1 parent ed548e2 commit 026e53d651fe1dc613b0ddd796b938587c082afe
Showing 8 changed files with 127 additions and 15 deletions.
@@ -124,4 +124,9 @@ public interface IdentityManager {
produces = {MediaType.APPLICATION_JSON_VALUE})
@ThrowsException(status = HttpStatus.CONFLICT, exception = TenantAlreadyInitializedException.class)
String initialize(@RequestParam("password") String password);

@RequestMapping(value = "/signatures", method = RequestMethod.POST,
consumes = {MediaType.APPLICATION_JSON_VALUE},
produces = {MediaType.ALL_VALUE})
String createSignatureSet();
}
@@ -54,7 +54,7 @@
classes = {AbstractComponentTest.TestConfiguration.class})
@TestPropertySource(properties = {"cassandra.cl.read = LOCAL_QUORUM", "cassandra.cl.write = LOCAL_QUORUM", "cassandra.cl.delete = LOCAL_QUORUM", "identity.token.refresh.secureCookie = false", "identity.passwordExpiresInDays = 93"})
public class AbstractComponentTest {
private static final String APP_NAME = "identity-v1";
static final String APP_NAME = "identity-v1";
@Configuration
@EnableApiFactory
@EnableEventRecording
@@ -0,0 +1,71 @@
import io.mifos.anubis.api.v1.client.Anubis;
import io.mifos.anubis.api.v1.domain.ApplicationSignatureSet;
import io.mifos.anubis.api.v1.domain.Signature;
import io.mifos.core.api.context.AutoSeshat;
import io.mifos.core.api.util.NotFoundException;
import org.junit.Assert;
import org.junit.Test;

import java.util.List;

/**
* @author Myrle Krantz
*/
public class TestKeyRotation extends AbstractComponentTest {
@Test
public void testKeyRotation()
{
final Anubis anubis = tenantApplicationSecurityEnvironment.getAnubis();

final String systemToken = tenantApplicationSecurityEnvironment.getSystemSecurityEnvironment().systemToken(APP_NAME);

try (final AutoSeshat ignored1 = new AutoSeshat(systemToken)) {
//Create a signature set then test that it is listed.
final String timestamp = getTestSubject().createSignatureSet();
{
final List<String> signatureSets = anubis.getAllSignatureSets();
Assert.assertTrue(signatureSets.contains(timestamp));
}

//For identity, application signature and identity manager signature should be identical.
final ApplicationSignatureSet signatureSet = anubis.getSignatureSet(timestamp);
Assert.assertEquals(signatureSet.getApplicationSignature(), signatureSet.getIdentityManagerSignature());

final Signature applicationSignature = anubis.getApplicationSignature(timestamp);
Assert.assertEquals(signatureSet.getApplicationSignature(), applicationSignature);

//Create a second signature set and test that it and the previous signature set are listed.
final String timestamp2 = getTestSubject().createSignatureSet();
{
final List<String> signatureSets = anubis.getAllSignatureSets();
Assert.assertTrue(signatureSets.contains(timestamp));
Assert.assertTrue(signatureSets.contains(timestamp2));
}

//Get the newly created signature set, and test that its contents are correct.
final ApplicationSignatureSet signatureSet2 = anubis.getSignatureSet(timestamp2);
Assert.assertEquals(signatureSet2.getApplicationSignature(), signatureSet2.getIdentityManagerSignature());

//Delete one of the signature sets and test that it is no longer listed.
anubis.deleteSignatureSet(timestamp);
{
final List<String> signatureSets = anubis.getAllSignatureSets();
Assert.assertFalse(signatureSets.contains(timestamp));
}

//Getting the newly deleted signature set should fail.
try {
anubis.getSignatureSet(timestamp);
Assert.fail("Not found exception should be thrown.");
} catch (final NotFoundException ignored) {
}

//Getting the newly deleted application signature set should likewise fail.
try {
anubis.getApplicationSignature(timestamp);
Assert.fail("Not found exception should be thrown.");
} catch (final NotFoundException ignored) {
}
}
}
}
@@ -24,12 +24,16 @@
/**
* @author Myrle Krantz
*/
@SuppressWarnings("WeakerAccess")
@Table(name = Signatures.TABLE_NAME)
public class PrivateSignatureEntity {
@PartitionKey
@Column(name = Signatures.KEY_TIMESTAMP_COLUMN)
private String keyTimestamp;

@Column(name = Signatures.VALID_COLUMN)
private Boolean valid;

@Column(name = Signatures.PRIVATE_KEY_MOD_COLUMN)
private BigInteger privateKeyMod;
@Column(name = Signatures.PRIVATE_KEY_EXP_COLUMN)
@@ -43,6 +47,14 @@ public void setKeyTimestamp(String keyTimestamp) {
this.keyTimestamp = keyTimestamp;
}

public Boolean getValid() {
return valid;
}

public void setValid(Boolean valid) {
this.valid = valid;
}

public BigInteger getPrivateKeyMod() {
return privateKeyMod;
}
@@ -24,26 +24,23 @@
/**
* @author Myrle Krantz
*/
@SuppressWarnings("unused")
@SuppressWarnings({"unused", "WeakerAccess"})
@Table(name = Signatures.TABLE_NAME)
public class SignatureEntity {
@PartitionKey
@Column(name = Signatures.KEY_TIMESTAMP_COLUMN)
private String keyTimestamp;

@Column(name = Signatures.VALID_COLUMN)
private Boolean valid;

@Column(name = Signatures.PUBLIC_KEY_MOD_COLUMN)
private BigInteger publicKeyMod;
@Column(name = Signatures.PUBLIC_KEY_EXP_COLUMN)
private BigInteger publicKeyExp;

public SignatureEntity() { }

public SignatureEntity(final String keyTimestamp, final BigInteger publicKeyMod, final BigInteger publicKeyExp) {
this.keyTimestamp = keyTimestamp;
this.publicKeyMod = publicKeyMod;
this.publicKeyExp = publicKeyExp;
}

public String getKeyTimestamp() {
return keyTimestamp;
}
@@ -52,6 +49,14 @@ public void setKeyTimestamp(String keyTimestamp) {
this.keyTimestamp = keyTimestamp;
}

public Boolean getValid() {
return valid;
}

public void setValid(Boolean valid) {
this.valid = valid;
}

public BigInteger getPublicKeyMod() {
return publicKeyMod;
}
@@ -43,7 +43,7 @@ public class Signatures {
static final String TABLE_NAME = "isis_signatures";
private static final String INDEX_NAME = "isis_signatures_valid_index";
static final String KEY_TIMESTAMP_COLUMN = "key_timestamp";
private static final String VALID_COLUMN = "valid";
static final String VALID_COLUMN = "valid";
static final String PRIVATE_KEY_MOD_COLUMN = "private_key_mod";
static final String PRIVATE_KEY_EXP_COLUMN = "private_key_exp";
static final String PUBLIC_KEY_MOD_COLUMN = "public_key_mod";
@@ -110,7 +110,8 @@ public Optional<SignatureEntity> getSignature(final String keyTimestamp) {
final Mapper<SignatureEntity> signatureEntityMapper
= tenantAwareCassandraMapperProvider.getMapper(SignatureEntity.class);

return Optional.ofNullable(signatureEntityMapper.get(keyTimestamp));
final Optional<SignatureEntity> ret = Optional.ofNullable(signatureEntityMapper.get(keyTimestamp));
return ret.filter(SignatureEntity::getValid);
}

/**
@@ -130,7 +131,8 @@ private Optional<PrivateSignatureEntity> getPrivateSignatureEntity(final String
final Mapper<PrivateSignatureEntity> privateSignatureEntityMapper
= tenantAwareCassandraMapperProvider.getMapper(PrivateSignatureEntity.class);

return Optional.ofNullable(privateSignatureEntityMapper.get(keyTimestamp));
final Optional<PrivateSignatureEntity> ret = Optional.ofNullable(privateSignatureEntityMapper.get(keyTimestamp));
return ret.filter(PrivateSignatureEntity::getValid);
}

public List<String> getAllKeyTimestamps() {
@@ -19,6 +19,7 @@
import io.mifos.anubis.api.v1.domain.ApplicationSignatureSet;
import io.mifos.anubis.api.v1.domain.Signature;
import io.mifos.anubis.config.TenantSignatureRepository;
import io.mifos.core.lang.security.RsaKeyPairFactory;
import io.mifos.identity.internal.repository.SignatureEntity;
import io.mifos.identity.internal.repository.Signatures;
import io.mifos.identity.internal.repository.Tenants;
@@ -83,4 +84,10 @@ public boolean tenantAlreadyProvisioned() {
return false;
}
}

public String createSignatureSet() {
final RsaKeyPairFactory.KeyPairHolder keys = RsaKeyPairFactory.createKeyPair();
signatures.add(keys);
return keys.getTimestamp();
}
}
@@ -30,7 +30,7 @@
*/
@SuppressWarnings("unused")
@RestController
@RequestMapping("/initialize")
@RequestMapping()
public class InitializeRestController {
private final TenantService tenantService;
private final Provisioner provisioner;
@@ -44,9 +44,10 @@ public class InitializeRestController {
this.provisioner = provisioner;
}

@RequestMapping(method = RequestMethod.POST,
consumes = {MediaType.ALL_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE})
@RequestMapping(value = "/initialize",
method = RequestMethod.POST,
consumes = {MediaType.ALL_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE})
@Permittable(AcceptedTokenType.SYSTEM)
public @ResponseBody ResponseEntity<String> initializeTenant(
@RequestParam("password") final String adminPassword)
@@ -62,4 +63,13 @@ public class InitializeRestController {
return new ResponseEntity<>(signatureTimestamp,
HttpStatus.OK);
}

@RequestMapping(value = "/signatures",
method = RequestMethod.POST,
consumes = {MediaType.ALL_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE})
@Permittable(AcceptedTokenType.SYSTEM)
public @ResponseBody ResponseEntity<String> createSignatureSet() {
return ResponseEntity.ok(tenantService.createSignatureSet());
}
}

0 comments on commit 026e53d

Please sign in to comment.