Skip to content
This repository has been archived by the owner on Nov 22, 2023. It is now read-only.

Commit

Permalink
Adding dedicated and efficient DAO method to support listing expired …
Browse files Browse the repository at this point in the history
…secret names (#1185)
  • Loading branch information
mmontgomery-square committed Jan 17, 2023
1 parent 17ac31e commit 0a426fc
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 7 deletions.
11 changes: 11 additions & 0 deletions server/src/main/java/keywhiz/service/daos/SecretSeriesDAO.java
Expand Up @@ -277,6 +277,17 @@ public List<SecretSeries> getMultipleSecretSeriesByName(List<String> names) {
return dslContext.fetch(SECRETS, SECRETS.NAME.in(names).and(SECRETS.CURRENT.isNotNull())).map(secretSeriesMapper::map);
}

public List<String> listExpiringSecretNames(Instant notAfterInclusive) {
List<String> expiringSecretNames = dslContext
.select()
.from(SECRETS)
.where(SECRETS.CURRENT.isNotNull())
.and(SECRETS.EXPIRY.greaterOrEqual(Instant.now().getEpochSecond()))
.and(SECRETS.EXPIRY.lessThan(notAfterInclusive.getEpochSecond()))
.fetch(SECRETS.NAME);
return ImmutableList.copyOf(expiringSecretNames);
}

public ImmutableList<SecretSeries> getSecretSeries(@Nullable Long expireMaxTime,
@Nullable Group group, @Nullable Long expireMinTime, @Nullable String minName,
@Nullable Integer limit) {
Expand Down
Expand Up @@ -363,22 +363,20 @@ public Iterable<SanitizedSecret> secretListingV2(@Auth AutomationClient automati
/**
* Retrieve listing of secrets expiring soon
*
* @param time timestamp for farthest expiry to include
* @param notAfterInclusiveUnixEpochSeconds timestamp for farthest expiry to include
*
* responseMessage 200 List of secrets expiring soon
* responseMessage 200 List of secret names expiring soon
*/
@Timed @ExceptionMetered
@Path("expiring/{time}")
@GET
@Produces(APPLICATION_JSON)
@LogArguments
public Iterable<String> secretListingExpiring(@Auth AutomationClient automationClient, @PathParam("time") Long time) {
public Iterable<String> listExpiringSecretNames(@Auth AutomationClient automationClient, @PathParam("time") Long notAfterInclusiveUnixEpochSeconds) {
permissionCheck.checkAllowedForTargetTypeOrThrow(automationClient, Action.READ, Secret.class);

List<SanitizedSecret> secrets = secretControllerReadOnly.getSanitizedSecrets(time, null);
return secrets.stream()
.map(SanitizedSecret::name)
.collect(toList());
Instant notAfterInclusive = Instant.ofEpochSecond(notAfterInclusiveUnixEpochSeconds);
return secretSeriesDAO.listExpiringSecretNames(notAfterInclusive);
}

/**
Expand Down
50 changes: 50 additions & 0 deletions server/src/test/java/keywhiz/service/daos/SecretSeriesDAOTest.java
Expand Up @@ -56,6 +56,56 @@ public class SecretSeriesDAOTest {
@Inject @Readwrite SecretContentDAO secretContentDAO;
@Inject @Readwrite GroupDAO groupDAO;

@Test
public void listExpiringSecretNamesIncludesAllExpiringSecrets() {
long expiration1 = randomExpiration();
long expiration2 = randomExpiration();

String secretSeriesName1 = createSecretSeriesAndContentWithExpiration(expiration1);
String secretSeriesName2 = createSecretSeriesAndContentWithExpiration(expiration2);

long notAfter = Math.max(expiration1, expiration2) + 1;

List<String> expiringSecretNames = secretSeriesDAO.listExpiringSecretNames(Instant.ofEpochSecond(notAfter));
assertThat(expiringSecretNames).containsExactlyInAnyOrder(secretSeriesName1, secretSeriesName2);
}

@Test
public void listExpiringSecretNamesDoesNotIncludeSecretsExpiringOnNotAfter() {
long expiration1 = randomExpiration();
long expiration2 = expiration1 + 1;

String secretSeriesName1 = createSecretSeriesAndContentWithExpiration(expiration1);
String secretSeriesName2 = createSecretSeriesAndContentWithExpiration(expiration2);

long notAfter = expiration2;

List<String> expiringSecretNames = secretSeriesDAO.listExpiringSecretNames(Instant.ofEpochSecond(notAfter));
assertThat(expiringSecretNames).containsExactlyInAnyOrder(secretSeriesName1);
}

@Test
public void listExpiringSecretNamesDoesNotIncludeSecretsExpiringAfterNotAfter() {
long expiration1 = randomExpiration();
long expiration2 = expiration1 + 2;

String secretSeriesName1 = createSecretSeriesAndContentWithExpiration(expiration1);
String secretSeriesName2 = createSecretSeriesAndContentWithExpiration(expiration2);

long notAfter = expiration1 + 1;

List<String> expiringSecretNames = secretSeriesDAO.listExpiringSecretNames(Instant.ofEpochSecond(notAfter));
assertThat(expiringSecretNames).containsExactlyInAnyOrder(secretSeriesName1);
}

private String createSecretSeriesAndContentWithExpiration(long expiration) {
String secretSeriesName = randomName();
long secretSeriesId = createSecretSeries(secretSeriesName);
long secretContentId = createSecretContent(secretSeriesId);
secretSeriesDAO.setExpiration(secretContentId, Instant.ofEpochSecond(expiration));
return secretSeriesName;
}

@Test
public void setCurrentVersionUpdatesSecretSeriesExpiry() {
long secretSeriesId = createRandomSecretSeries();
Expand Down

0 comments on commit 0a426fc

Please sign in to comment.