Skip to content
This repository has been archived by the owner on Jan 12, 2024. It is now read-only.

Commit

Permalink
Feature/data key rotation (#196)
Browse files Browse the repository at this point in the history
* Add job to rotate data keys
  • Loading branch information
mayitbeegh authored Jul 3, 2019
1 parent 74cd270 commit 63d65a9
Show file tree
Hide file tree
Showing 19 changed files with 565 additions and 16 deletions.
4 changes: 4 additions & 0 deletions gradle/check.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ jacocoTestReport {
}
}

dependencyCheck {
failOnError = false
}

// To generate an HTML report instead of XML
tasks.withType(SpotBugsTask) {
reports.xml.enabled = false
Expand Down
2 changes: 1 addition & 1 deletion gradle/dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def logbackVersion = '1.1.7'
// Request version 4 for full java 8 support
def guiceVersion = '4.2.2'
def awsSdkVersion = '1.11.160'
def groovyVersion = '2.3.9'
def groovyVersion = '2.5.7'

dependencies {
compile (
Expand Down
18 changes: 17 additions & 1 deletion src/main/java/com/nike/cerberus/dao/SecureDataDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import com.nike.cerberus.domain.SecureDataType;
import com.nike.cerberus.mapper.SecureDataMapper;
import com.nike.cerberus.record.DataKeyInfo;
import com.nike.cerberus.record.SecureDataRecord;

import javax.inject.Inject;
Expand Down Expand Up @@ -54,6 +55,7 @@ public void writeSecureData(String sdbId, String path, byte[] encryptedPayload,
.setCreatedTs(createdTs)
.setLastUpdatedBy(lastUpdatedBy)
.setLastUpdatedTs(lastUpdatedTs)
.setLastRotatedTs(lastUpdatedTs) // This is intentional
);
}

Expand All @@ -66,7 +68,8 @@ public void updateSecureData(String sdbId,
String createdBy,
OffsetDateTime createdTs,
String lastUpdatedBy,
OffsetDateTime lastUpdatedTs) {
OffsetDateTime lastUpdatedTs,
OffsetDateTime lastRotatedTs) {

secureDataMapper.updateSecureData(new SecureDataRecord()
.setId(path.hashCode())
Expand All @@ -80,14 +83,23 @@ public void updateSecureData(String sdbId,
.setCreatedTs(createdTs)
.setLastUpdatedTs(lastUpdatedTs)
.setLastUpdatedBy(lastUpdatedBy)
.setLastRotatedTs(lastRotatedTs)

);
}

public int updateSecureData(SecureDataRecord secureDataRecord) {
return secureDataMapper.updateSecureData(secureDataRecord);
}

public Optional<SecureDataRecord> readSecureDataByPath(String sdbId, String path) {
return Optional.ofNullable(secureDataMapper.readSecureDataByPath(sdbId, path));
}

public Optional<SecureDataRecord> readSecureDataByIdLocking(String id) {
return Optional.ofNullable(secureDataMapper.readSecureDataByIdLocking(id));
}

public Optional<SecureDataRecord> readSecureDataByPathAndType(String sdbId, String path, SecureDataType type) {
return Optional.ofNullable(secureDataMapper.readSecureDataByPathAndType(sdbId, path, type));
}
Expand Down Expand Up @@ -136,4 +148,8 @@ public int getSumTopLevelKeyValuePairs() {
Integer val = secureDataMapper.getSumTopLevelKeyValuePairs();
return val == null ? 0 : val;
}

public List<DataKeyInfo> getOldestDataKeyInfo(OffsetDateTime dateTime, int limit) {
return secureDataMapper.getOldestDataKeyInfo(dateTime, limit);
}
}
8 changes: 8 additions & 0 deletions src/main/java/com/nike/cerberus/dao/SecureDataVersionDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ public void writeSecureDataVersion(String sdbId,
);
}

public int updateSecureDataVersion(SecureDataVersionRecord secureDataVersionRecord) {
return secureDataVersionMapper.updateSecureDataVersion(secureDataVersionRecord);
}

public Integer getTotalNumVersionsForPath(String path) {
return secureDataVersionMapper.getTotalNumVersionsForPath(path);
}
Expand All @@ -78,6 +82,10 @@ public Optional<SecureDataVersionRecord> readSecureDataVersionById(String id) {
return Optional.ofNullable(secureDataVersionMapper.readSecureDataVersionById(id));
}

public Optional<SecureDataVersionRecord> readSecureDataVersionByIdLocking(String id) {
return Optional.ofNullable(secureDataVersionMapper.readSecureDataVersionByIdLocking(id));
}

public String[] getVersionPathsByPartialPath(String partialPath) {
return secureDataVersionMapper.getVersionPathsByPartialPath(partialPath);
}
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/com/nike/cerberus/domain/Source.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2019 Nike, Inc.
*
* 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 com.nike.cerberus.domain;

/**
* Enum used to distinguish between objects, files, and other types of secrets in the database.
*/
public enum Source {
SECURE_DATA,
SECURE_DATA_VERSION
}
52 changes: 52 additions & 0 deletions src/main/java/com/nike/cerberus/jobs/DataKeyRotationJob.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2017 Nike, Inc.
*
* 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 com.nike.cerberus.jobs;


import com.nike.cerberus.service.SecureDataService;

import javax.inject.Inject;
import javax.inject.Named;

public class DataKeyRotationJob extends LockingJob {

private final SecureDataService secureDataService;
private final int numberOfDataKeyToRotatePerJobRun;
private final int dataKeyRotationPauseTimeInMillis;
private final int dataKeyRotationIntervalInDays;

@Inject
public DataKeyRotationJob(SecureDataService secureDataService,
@Named("cms.jobs.DataKeyRotationJob.numberOfDataKeyToRotatePerJobRun")
int numberOfDataKeyToRotatePerJobRun,
@Named("cms.jobs.DataKeyRotationJob.dataKeyRotationPauseTimeInMillis")
int dataKeyRotationPauseTimeInMillis,
@Named("cms.jobs.DataKeyRotationJob.dataKeyRotationIntervalInDays")
int dataKeyRotationIntervalInDays) {

this.secureDataService = secureDataService;
this.numberOfDataKeyToRotatePerJobRun = numberOfDataKeyToRotatePerJobRun;
this.dataKeyRotationPauseTimeInMillis = dataKeyRotationPauseTimeInMillis;
this.dataKeyRotationIntervalInDays = dataKeyRotationIntervalInDays;
}


@Override
protected void executeLockableCode() {
secureDataService.rotateDataKeys(numberOfDataKeyToRotatePerJobRun, dataKeyRotationPauseTimeInMillis, dataKeyRotationIntervalInDays);
}
}
7 changes: 7 additions & 0 deletions src/main/java/com/nike/cerberus/mapper/SecureDataMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
package com.nike.cerberus.mapper;

import com.nike.cerberus.domain.SecureDataType;
import com.nike.cerberus.record.DataKeyInfo;
import com.nike.cerberus.record.SecureDataRecord;
import org.apache.ibatis.annotations.Param;

import java.time.OffsetDateTime;
import java.util.List;
import java.util.Set;

Expand All @@ -31,6 +33,8 @@ public interface SecureDataMapper {

SecureDataRecord readSecureDataByPath(@Param("sdbId") String sdbId, @Param("path") String path);

SecureDataRecord readSecureDataByIdLocking(@Param("id") String id);

SecureDataRecord readSecureDataByPathAndType(@Param("sdbId") String sdbId, @Param("path") String path, @Param("type") SecureDataType type);

SecureDataRecord readMetadataByPathAndType(@Param("sdbId") String sdbId, @Param("path") String path, @Param("type") SecureDataType type);
Expand Down Expand Up @@ -60,4 +64,7 @@ int deleteAllSecretsThatStartWithGivenPartialPath(@Param("sdbId") String sdbId,
int deleteSecret(@Param("sdbId") String sdbId, @Param("path") String path);

Integer getSumTopLevelKeyValuePairs();

List<DataKeyInfo> getOldestDataKeyInfo(@Param("datetime") OffsetDateTime dateTime,
@Param("limit") int limit);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@
import com.nike.cerberus.record.SecureDataVersionRecord;
import org.apache.ibatis.annotations.Param;

import java.time.OffsetDateTime;
import java.util.List;
import java.util.Set;

public interface SecureDataVersionMapper {

int writeSecureDataVersion(@Param("record") SecureDataVersionRecord record);

int updateSecureDataVersion(@Param("record") SecureDataVersionRecord record);

Integer getTotalNumVersionsForPath(String path);

List<SecureDataVersionRecord> listSecureDataVersionsByPath(@Param("path") String path,
Expand All @@ -35,6 +38,8 @@ List<SecureDataVersionRecord> listSecureDataVersionsByPath(@Param("path") String

SecureDataVersionRecord readSecureDataVersionById(@Param("id") String id);

SecureDataVersionRecord readSecureDataVersionByIdLocking(@Param("id") String id);

String[] getVersionPathsByPartialPath(@Param("partialPath") String partialPath);

Set<String> getVersionPathsBySdbId(@Param("sdbId") String sdbId);
Expand Down
55 changes: 55 additions & 0 deletions src/main/java/com/nike/cerberus/record/DataKeyInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2017 Nike, Inc.
*
* 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 com.nike.cerberus.record;

import com.nike.cerberus.domain.Source;

import java.time.OffsetDateTime;

public class DataKeyInfo {

private String id;
private Source source;
private OffsetDateTime lastRotatedTs;

public String getId() {
return id;
}

public DataKeyInfo setId(String id) {
this.id = id;
return this;
}

public Source getSource() {
return source;
}

public DataKeyInfo setSource(Source source) {
this.source = source;
return this;
}

public OffsetDateTime getLastRotatedTs() {
return lastRotatedTs;
}

public DataKeyInfo setLastRotatedTs(OffsetDateTime lastRotatedTs) {
this.lastRotatedTs = lastRotatedTs;
return this;
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/nike/cerberus/record/SecureDataRecord.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class SecureDataRecord {
private String createdBy;
private OffsetDateTime lastUpdatedTs;
private String lastUpdatedBy;
private OffsetDateTime lastRotatedTs;

public Integer getId() {
return id;
Expand Down Expand Up @@ -137,4 +138,13 @@ public SecureDataRecord setLastUpdatedBy(String lastUpdatedBy) {
this.lastUpdatedBy = lastUpdatedBy;
return this;
}

public OffsetDateTime getLastRotatedTs() {
return lastRotatedTs;
}

public SecureDataRecord setLastRotatedTs(OffsetDateTime lastRotatedTs) {
this.lastRotatedTs = lastRotatedTs;
return this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class SecureDataVersionRecord {
private OffsetDateTime versionCreatedTs;
private String actionPrincipal;
private OffsetDateTime actionTs;
private OffsetDateTime lastRotatedTs;

public String getId() {
return id;
Expand Down Expand Up @@ -144,4 +145,13 @@ public enum SecretsAction {
UPDATE,
DELETE
}

public OffsetDateTime getLastRotatedTs() {
return lastRotatedTs;
}

public SecureDataVersionRecord setLastRotatedTs(OffsetDateTime lastRotatedTs) {
this.lastRotatedTs = lastRotatedTs;
return this;
}
}
22 changes: 22 additions & 0 deletions src/main/java/com/nike/cerberus/service/EncryptionService.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,28 @@ private String decrypt(ParsedCiphertext parsedCiphertext, String sdbPath) {
return new String(awsCrypto.decryptData(decryptProvider, parsedCiphertext).getResult(), StandardCharsets.UTF_8);
}

/**
* Re-encrypt (i.e. decrypt then encrypt) String ciphertext
* @param encryptedPayload encryptedPayload
* @param sdbPath the current SDB path
* @return re-encrypted ciphertext
*/
public String reencrypt(String encryptedPayload, String sdbPath) {
String plaintext = decrypt(encryptedPayload, sdbPath);
return encrypt(plaintext, sdbPath);
}

/**
* Re-encrypt (i.e. decrypt then encrypt) byte array ciphertext
* @param encryptedPayload encryptedPayload
* @param sdbPath the current SDB path
* @return re-encrypted ciphertext
*/
public byte[] reencrypt(byte[] encryptedPayload, String sdbPath) {
byte[] plaintextBytes = decrypt(encryptedPayload, sdbPath);
return encrypt(plaintextBytes, sdbPath);
}

/**
* Decrypt the encryptedPayload.
*
Expand Down
Loading

0 comments on commit 63d65a9

Please sign in to comment.