Search in sources :

Example 31 with Secret

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();
}
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 32 with Secret

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;
}
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)

Example 33 with Secret

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());
}
Also used : Secret(keywhiz.api.model.Secret) SanitizedSecret(keywhiz.api.model.SanitizedSecret) Secret(keywhiz.api.model.Secret) Produces(javax.ws.rs.Produces) Event(keywhiz.log.Event) Path(javax.ws.rs.Path) LoggerFactory(org.slf4j.LoggerFactory) GroupDAOFactory(keywhiz.service.daos.GroupDAO.GroupDAOFactory) Valid(javax.validation.Valid) QueryParam(javax.ws.rs.QueryParam) Consumes(javax.ws.rs.Consumes) Map(java.util.Map) DefaultValue(javax.ws.rs.DefaultValue) ExceptionMetered(com.codahale.metrics.annotation.ExceptionMetered) ModifyGroupsRequestV2(keywhiz.api.automation.v2.ModifyGroupsRequestV2) BadRequestException(javax.ws.rs.BadRequestException) UriBuilder(javax.ws.rs.core.UriBuilder) APPLICATION_JSON(javax.ws.rs.core.MediaType.APPLICATION_JSON) ContentCryptographer(keywhiz.service.crypto.ContentCryptographer) GroupDAO(keywhiz.service.daos.GroupDAO) Collectors.toSet(java.util.stream.Collectors.toSet) DELETE(javax.ws.rs.DELETE) Group(keywhiz.api.model.Group) CreateSecretRequestV2(keywhiz.api.automation.v2.CreateSecretRequestV2) HOURS(java.time.temporal.ChronoUnit.HOURS) Set(java.util.Set) ConflictException(keywhiz.service.exceptions.ConflictException) Instant(java.time.Instant) Sets(com.google.common.collect.Sets) NotFoundException(javax.ws.rs.NotFoundException) String.format(java.lang.String.format) Timed(com.codahale.metrics.annotation.Timed) Base64(java.util.Base64) List(java.util.List) Stream(java.util.stream.Stream) Response(javax.ws.rs.core.Response) Optional(java.util.Optional) SanitizedSecret(keywhiz.api.model.SanitizedSecret) SecretDAOFactory(keywhiz.service.daos.SecretDAO.SecretDAOFactory) SecretContent(keywhiz.api.model.SecretContent) PathParam(javax.ws.rs.PathParam) SecretDetailResponseV2(keywhiz.api.automation.v2.SecretDetailResponseV2) AclDAO(keywhiz.service.daos.AclDAO) SanitizedSecretWithGroups(keywhiz.api.model.SanitizedSecretWithGroups) GET(javax.ws.rs.GET) Auth(io.dropwizard.auth.Auth) PartialUpdateSecretRequestV2(keywhiz.api.automation.v2.PartialUpdateSecretRequestV2) HashMap(java.util.HashMap) SecretSeriesDAO(keywhiz.service.daos.SecretSeriesDAO) ArrayList(java.util.ArrayList) Inject(javax.inject.Inject) AutomationClient(keywhiz.api.model.AutomationClient) ImmutableList(com.google.common.collect.ImmutableList) SecretDAO(keywhiz.service.daos.SecretDAO) SecretBuilder(keywhiz.service.daos.SecretController.SecretBuilder) AuditLog(keywhiz.log.AuditLog) SanitizedSecretWithGroupsListAndCursor(keywhiz.api.model.SanitizedSecretWithGroupsListAndCursor) DataAccessException(org.jooq.exception.DataAccessException) POST(javax.ws.rs.POST) Logger(org.slf4j.Logger) SecretSeriesDAOFactory(keywhiz.service.daos.SecretSeriesDAO.SecretSeriesDAOFactory) Readonly(keywhiz.service.config.Readonly) UTF_8(java.nio.charset.StandardCharsets.UTF_8) SecretRetrievalCursor(keywhiz.api.model.SecretRetrievalCursor) AclDAOFactory(keywhiz.service.daos.AclDAO.AclDAOFactory) SetSecretVersionRequestV2(keywhiz.api.automation.v2.SetSecretVersionRequestV2) SecretController(keywhiz.service.daos.SecretController) SecretContentsResponseV2(keywhiz.api.automation.v2.SecretContentsResponseV2) SecretContentsRequestV2(keywhiz.api.automation.v2.SecretContentsRequestV2) EventTag(keywhiz.log.EventTag) Collectors.toList(java.util.stream.Collectors.toList) CreateOrUpdateSecretRequestV2(keywhiz.api.automation.v2.CreateOrUpdateSecretRequestV2) SecretSeriesAndContent(keywhiz.api.model.SecretSeriesAndContent) PUT(javax.ws.rs.PUT) NotFoundException(javax.ws.rs.NotFoundException) Path(javax.ws.rs.Path) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) Timed(com.codahale.metrics.annotation.Timed) ExceptionMetered(com.codahale.metrics.annotation.ExceptionMetered) PUT(javax.ws.rs.PUT)

Example 34 with Secret

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());
}
Also used : Secret(keywhiz.api.model.Secret) SecretSeries(keywhiz.api.model.SecretSeries) SecretContent(keywhiz.api.model.SecretContent) SecretSeriesAndContent(keywhiz.api.model.SecretSeriesAndContent) Test(org.junit.Test)

Aggregations

Secret (keywhiz.api.model.Secret)34 SanitizedSecret (keywhiz.api.model.SanitizedSecret)21 ExceptionMetered (com.codahale.metrics.annotation.ExceptionMetered)15 Timed (com.codahale.metrics.annotation.Timed)15 Test (org.junit.Test)14 HashMap (java.util.HashMap)12 Event (keywhiz.log.Event)12 NotFoundException (javax.ws.rs.NotFoundException)10 POST (javax.ws.rs.POST)10 Path (javax.ws.rs.Path)9 Consumes (javax.ws.rs.Consumes)8 Group (keywhiz.api.model.Group)6 ConflictException (keywhiz.service.exceptions.ConflictException)6 Response (javax.ws.rs.core.Response)5 SecretController (keywhiz.service.daos.SecretController)5 DataAccessException (org.jooq.exception.DataAccessException)5 ArrayList (java.util.ArrayList)4 DELETE (javax.ws.rs.DELETE)4 GET (javax.ws.rs.GET)4 SecretDetailResponse (keywhiz.api.SecretDetailResponse)4