Search in sources :

Example 51 with ExceptionMetered

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());
}
Also used : Group(keywhiz.api.model.Group) SanitizedSecret(keywhiz.api.model.SanitizedSecret) NotFoundException(javax.ws.rs.NotFoundException) Path(javax.ws.rs.Path) Produces(javax.ws.rs.Produces) Timed(com.codahale.metrics.annotation.Timed) GET(javax.ws.rs.GET) ExceptionMetered(com.codahale.metrics.annotation.ExceptionMetered)

Example 52 with ExceptionMetered

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();
}
Also used : NotFoundException(javax.ws.rs.NotFoundException) SecretSeriesAndContent(keywhiz.api.model.SecretSeriesAndContent) UriBuilder(javax.ws.rs.core.UriBuilder) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Timed(com.codahale.metrics.annotation.Timed) ExceptionMetered(com.codahale.metrics.annotation.ExceptionMetered)

Example 53 with ExceptionMetered

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();
}
Also used : Secret(keywhiz.api.model.Secret) SanitizedSecret(keywhiz.api.model.SanitizedSecret) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Event(keywhiz.log.Event) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Produces(javax.ws.rs.Produces) Timed(com.codahale.metrics.annotation.Timed) ExceptionMetered(com.codahale.metrics.annotation.ExceptionMetered)

Example 54 with ExceptionMetered

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();
}
Also used : Secret(keywhiz.api.model.Secret) SanitizedSecret(keywhiz.api.model.SanitizedSecret) HashMap(java.util.HashMap) NotFoundException(javax.ws.rs.NotFoundException) Event(keywhiz.log.Event) Path(javax.ws.rs.Path) DELETE(javax.ws.rs.DELETE) Timed(com.codahale.metrics.annotation.Timed) ExceptionMetered(com.codahale.metrics.annotation.ExceptionMetered)

Example 55 with ExceptionMetered

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;
}
Also used : Secret(keywhiz.api.model.Secret) SanitizedSecret(keywhiz.api.model.SanitizedSecret) HashMap(java.util.HashMap) Instant(java.time.Instant) NotFoundException(javax.ws.rs.NotFoundException) Event(keywhiz.log.Event) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) Timed(com.codahale.metrics.annotation.Timed) ExceptionMetered(com.codahale.metrics.annotation.ExceptionMetered)

Aggregations

ExceptionMetered (com.codahale.metrics.annotation.ExceptionMetered)68 Timed (com.codahale.metrics.annotation.Timed)66 Path (javax.ws.rs.Path)44 Event (keywhiz.log.Event)38 POST (javax.ws.rs.POST)36 HashMap (java.util.HashMap)34 NotFoundException (javax.ws.rs.NotFoundException)32 Consumes (javax.ws.rs.Consumes)28 Produces (javax.ws.rs.Produces)25 SanitizedSecret (keywhiz.api.model.SanitizedSecret)21 DELETE (javax.ws.rs.DELETE)19 GET (javax.ws.rs.GET)19 Group (keywhiz.api.model.Group)18 Response (javax.ws.rs.core.Response)16 ConflictException (keywhiz.service.exceptions.ConflictException)16 Secret (keywhiz.api.model.Secret)15 URI (java.net.URI)13 AutomationClient (keywhiz.api.model.AutomationClient)13 Client (keywhiz.api.model.Client)12 PUT (javax.ws.rs.PUT)9