use of keywhiz.api.model.Secret in project keywhiz by square.
the class SecretResource method deleteSecretSeries.
/**
* Delete a secret series
*
* @param name Secret series name
*
* responseMessage 204 Secret series deleted
* responseMessage 404 Secret series not found
*/
@Timed
@ExceptionMetered
@DELETE
@Path("{name}")
public Response deleteSecretSeries(@Auth AutomationClient automationClient, @PathParam("name") String name) {
Secret secret = secretController.getSecretByName(name).orElseThrow(() -> new NotFoundException("Secret series not found."));
// Get the groups for this secret so they can be restored manually if necessary
Set<String> groups = aclDAO.getGroupsFor(secret).stream().map(Group::getName).collect(toSet());
secretDAO.deleteSecretsByName(name);
// Record the deletion in the audit log
Map<String, String> extraInfo = new HashMap<>();
extraInfo.put("groups", groups.toString());
extraInfo.put("current version", secret.getVersion().toString());
auditLog.recordEvent(new Event(Instant.now(), EventTag.SECRET_DELETE, automationClient.getName(), name, extraInfo));
return Response.noContent().build();
}
use of keywhiz.api.model.Secret in project keywhiz by square.
the class SecretResource method backfillExpiration.
/**
* Backfill expiration for this secret.
*/
@Timed
@ExceptionMetered
@Path("{name}/backfill-expiration")
@POST
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public boolean backfillExpiration(@Auth AutomationClient automationClient, @PathParam("name") String name, List<String> passwords) {
Optional<Secret> secretOptional = secretController.getSecretByName(name);
if (!secretOptional.isPresent()) {
throw new NotFoundException("No such secret: " + name);
}
Secret secret = secretOptional.get();
Optional<Instant> existingExpiry = Optional.empty();
if (secret.getExpiry() > 0) {
existingExpiry = Optional.of(Instant.ofEpochMilli(secret.getExpiry() * 1000));
}
String secretName = secret.getName();
byte[] secretContent = Base64.getDecoder().decode(secret.getSecret());
// Always try empty password
passwords.add("");
Instant expiry = null;
if (secretName.endsWith(".crt") || secretName.endsWith(".pem") || secretName.endsWith(".key")) {
expiry = ExpirationExtractor.expirationFromEncodedCertificateChain(secretContent);
} else if (secretName.endsWith(".gpg") || secretName.endsWith(".pgp")) {
expiry = ExpirationExtractor.expirationFromOpenPGP(secretContent);
} else if (secretName.endsWith(".p12") || secretName.endsWith(".pfx")) {
while (expiry == null && !passwords.isEmpty()) {
String password = passwords.remove(0);
expiry = ExpirationExtractor.expirationFromKeystore("PKCS12", password, secretContent);
}
} else if (secretName.endsWith(".jceks")) {
while (expiry == null && !passwords.isEmpty()) {
String password = passwords.remove(0);
expiry = ExpirationExtractor.expirationFromKeystore("JCEKS", password, secretContent);
}
} else if (secretName.endsWith(".jks")) {
while (expiry == null && !passwords.isEmpty()) {
String password = passwords.remove(0);
expiry = ExpirationExtractor.expirationFromKeystore("JKS", password, secretContent);
}
}
if (expiry != null) {
if (existingExpiry.isPresent()) {
long offset = existingExpiry.get().until(expiry, HOURS);
if (offset > 24 || offset < -24) {
logger.warn("Extracted expiration of secret {} differs from actual by more than {} hours (extracted = {}, database = {}).", secretName, offset, expiry, existingExpiry.get());
}
// Do not overwrite existing expiry, we just want to check for differences and warn.
return true;
}
logger.info("Found expiry for secret {}: {}", secretName, expiry.getEpochSecond());
boolean success = secretDAO.setExpiration(name, expiry);
if (success) {
Map<String, String> extraInfo = new HashMap<>();
extraInfo.put("backfilled expiry", Long.toString(expiry.getEpochSecond()));
auditLog.recordEvent(new Event(Instant.now(), EventTag.SECRET_BACKFILLEXPIRY, automationClient.getName(), name, extraInfo));
}
return success;
}
logger.info("Unable to determine expiry for secret {}", secretName);
return false;
}
use of keywhiz.api.model.Secret in project keywhiz by square.
the class SecretResource method modifySecretGroups.
/**
* Modify the groups a secret is assigned to
*
* @param name Secret series name
* @param request JSON request to modify groups
*
* responseMessage 201 Group membership changed
* responseMessage 404 Secret series not found
*/
@Timed
@ExceptionMetered
@PUT
@Path("{name}/groups")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Iterable<String> modifySecretGroups(@Auth AutomationClient automationClient, @PathParam("name") String name, @Valid ModifyGroupsRequestV2 request) {
// TODO: Use latest version instead of non-versioned
Secret secret = secretController.getSecretByName(name).orElseThrow(NotFoundException::new);
String user = automationClient.getName();
long secretId = secret.getId();
Set<String> oldGroups = aclDAO.getGroupsFor(secret).stream().map(Group::getName).collect(toSet());
Set<String> groupsToAdd = Sets.difference(request.addGroups(), oldGroups);
Set<String> groupsToRemove = Sets.intersection(request.removeGroups(), oldGroups);
// TODO: should optimize AclDAO to use names and return only name column
groupsToGroupIds(groupsToAdd).forEach((maybeGroupId) -> maybeGroupId.ifPresent((groupId) -> aclDAO.findAndAllowAccess(secretId, groupId, auditLog, user, new HashMap<>())));
groupsToGroupIds(groupsToRemove).forEach((maybeGroupId) -> maybeGroupId.ifPresent((groupId) -> aclDAO.findAndRevokeAccess(secretId, groupId, auditLog, user, new HashMap<>())));
return aclDAO.getGroupsFor(secret).stream().map(Group::getName).collect(toSet());
}
use of keywhiz.api.model.Secret in project keywhiz by square.
the class SecretTransformerTest method transformsOwner.
@Test
public void transformsOwner() {
String ownerName = "foo";
SecretSeries series = validSeries().toBuilder().owner(ownerName).build();
SecretContent content = validContent();
SecretSeriesAndContent seriesAndContent = SecretSeriesAndContent.of(series, content);
Secret secret = transformer.transform(seriesAndContent);
assertEquals(ownerName, secret.getOwner());
}
Aggregations