use of com.codahale.metrics.annotation.ExceptionMetered in project keywhiz by square.
the class SecretResource method secretListingExpiringForGroup.
/**
* Retrieve listing of secrets expiring soon in a group
*
* @param time timestamp for farthest expiry to include
* @param name Group name
* responseMessage 200 List of secrets expiring soon in group
*/
@Timed
@ExceptionMetered
@Path("expiring/{time}/{name}")
@GET
@Produces(APPLICATION_JSON)
public Iterable<String> secretListingExpiringForGroup(@Auth AutomationClient automationClient, @PathParam("time") Long time, @PathParam("name") String name) {
Group group = groupDAO.getGroup(name).orElseThrow(NotFoundException::new);
List<SanitizedSecret> secrets = secretControllerReadOnly.getSanitizedSecrets(time, group);
return secrets.stream().map(SanitizedSecret::name).collect(toSet());
}
use of com.codahale.metrics.annotation.ExceptionMetered in project keywhiz by square.
the class SecretResource method renameSecret.
@Timed
@ExceptionMetered
@Path("{oldName}/rename/{newName}")
@POST
@Consumes(APPLICATION_JSON)
public Response renameSecret(@Auth AutomationClient automationClient, @PathParam("oldName") String oldName, @PathParam("newName") String newName) {
SecretSeriesAndContent secret = secretDAO.getSecretByName(oldName).orElseThrow(NotFoundException::new);
secretDAO.renameSecretById(secret.series().id(), newName, automationClient.getName());
UriBuilder uriBuilder = UriBuilder.fromResource(SecretResource.class).path(newName);
return Response.created(uriBuilder.build()).build();
}
use of com.codahale.metrics.annotation.ExceptionMetered in project keywhiz by square.
the class SecretResource method secretContents.
/**
* Retrieve contents for a set of secret series. Throws an exception
* for unexpected errors (i. e. empty secret names or errors connecting to
* the database); returns a response containing the contents of found
* secrets and a list of any missing secrets.
*
* responseMessage 200 Secret series information retrieved
*/
@Timed
@ExceptionMetered
@POST
@Path("request/contents")
@Produces(APPLICATION_JSON)
public SecretContentsResponseV2 secretContents(@Auth AutomationClient automationClient, @Valid SecretContentsRequestV2 request) {
HashMap<String, String> successSecrets = new HashMap<>();
ArrayList<String> missingSecrets = new ArrayList<>();
// Get the contents for each secret, recording any errors
for (String secretName : request.secrets()) {
// Get the secret, if present
Optional<Secret> secret = secretController.getSecretByName(secretName);
if (!secret.isPresent()) {
missingSecrets.add(secretName);
} else {
successSecrets.put(secretName, secret.get().getSecret());
}
}
// Record the read in the audit log, tracking which secrets were found and not found
Map<String, String> extraInfo = new HashMap<>();
extraInfo.put("success_secrets", successSecrets.keySet().toString());
extraInfo.put("missing_secrets", missingSecrets.toString());
auditLog.recordEvent(new Event(Instant.now(), EventTag.SECRET_READCONTENT, automationClient.getName(), request.secrets().toString(), extraInfo));
return SecretContentsResponseV2.builder().successSecrets(successSecrets).missingSecrets(missingSecrets).build();
}
use of com.codahale.metrics.annotation.ExceptionMetered 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 com.codahale.metrics.annotation.ExceptionMetered 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;
}
Aggregations