Search in sources :

Example 1 with Group

use of keywhiz.api.model.Group in project keywhiz by square.

the class AutomationGroupResource method getGroupByName.

/**
 * Retrieve Group by a specified name, or all Groups if no name given
 *
 * @param automationClient the client with automation access performing this operation
 * @param name the name of the Group to retrieve, if provided
 * @return details on the specified group, or an all groups if no name specified
 *
 * optionalParams name
 * description Returns a single Group or a set of all Groups
 * responseMessage 200 Found and retrieved Group(s)
 * responseMessage 404 Group with given name not found (if name provided)
 */
@Timed
@ExceptionMetered
@GET
public Response getGroupByName(@Auth AutomationClient automationClient, @QueryParam("name") Optional<String> name) {
    if (name.isPresent()) {
        Group group = groupDAO.getGroup(name.get()).orElseThrow(NotFoundException::new);
        ImmutableList<Client> clients = ImmutableList.copyOf(aclDAO.getClientsFor(group));
        ImmutableList<SanitizedSecret> sanitizedSecrets = ImmutableList.copyOf(aclDAO.getSanitizedSecretsFor(group));
        return Response.ok().entity(GroupDetailResponse.fromGroup(group, sanitizedSecrets, clients)).build();
    }
    ImmutableList<SanitizedSecret> emptySecrets = ImmutableList.of();
    ImmutableList<Client> emptyClients = ImmutableList.of();
    List<GroupDetailResponse> groups = groupDAO.getGroups().stream().map((g) -> GroupDetailResponse.fromGroup(g, emptySecrets, emptyClients)).collect(toList());
    return Response.ok().entity(groups).build();
}
Also used : PathParam(javax.ws.rs.PathParam) AclDAO(keywhiz.service.daos.AclDAO) Produces(javax.ws.rs.Produces) GET(javax.ws.rs.GET) Event(keywhiz.log.Event) Strings.nullToEmpty(com.google.common.base.Strings.nullToEmpty) Path(javax.ws.rs.Path) LoggerFactory(org.slf4j.LoggerFactory) Auth(io.dropwizard.auth.Auth) GroupDAOFactory(keywhiz.service.daos.GroupDAO.GroupDAOFactory) HashMap(java.util.HashMap) Inject(javax.inject.Inject) Valid(javax.validation.Valid) AutomationClient(keywhiz.api.model.AutomationClient) GroupResource(keywhiz.service.resources.automation.v2.GroupResource) QueryParam(javax.ws.rs.QueryParam) ImmutableList(com.google.common.collect.ImmutableList) Consumes(javax.ws.rs.Consumes) Map(java.util.Map) ExceptionMetered(com.codahale.metrics.annotation.ExceptionMetered) Client(keywhiz.api.model.Client) APPLICATION_JSON(javax.ws.rs.core.MediaType.APPLICATION_JSON) GroupDAO(keywhiz.service.daos.GroupDAO) DELETE(javax.ws.rs.DELETE) AuditLog(keywhiz.log.AuditLog) Group(keywhiz.api.model.Group) POST(javax.ws.rs.POST) Logger(org.slf4j.Logger) AclDAOFactory(keywhiz.service.daos.AclDAO.AclDAOFactory) LongParam(io.dropwizard.jersey.params.LongParam) ConflictException(keywhiz.service.exceptions.ConflictException) Instant(java.time.Instant) NotFoundException(javax.ws.rs.NotFoundException) Timed(com.codahale.metrics.annotation.Timed) CreateGroupRequest(keywhiz.api.CreateGroupRequest) EventTag(keywhiz.log.EventTag) List(java.util.List) Collectors.toList(java.util.stream.Collectors.toList) Response(javax.ws.rs.core.Response) Optional(java.util.Optional) SanitizedSecret(keywhiz.api.model.SanitizedSecret) VisibleForTesting(com.google.common.annotations.VisibleForTesting) GroupDetailResponse(keywhiz.api.GroupDetailResponse) Group(keywhiz.api.model.Group) SanitizedSecret(keywhiz.api.model.SanitizedSecret) GroupDetailResponse(keywhiz.api.GroupDetailResponse) NotFoundException(javax.ws.rs.NotFoundException) AutomationClient(keywhiz.api.model.AutomationClient) Client(keywhiz.api.model.Client) Timed(com.codahale.metrics.annotation.Timed) GET(javax.ws.rs.GET) ExceptionMetered(com.codahale.metrics.annotation.ExceptionMetered)

Example 2 with Group

use of keywhiz.api.model.Group in project keywhiz by square.

the class AutomationGroupResource method createGroup.

/**
 * Create Group
 *
 * @param automationClient the client with automation access performing this operation
 * @param groupRequest the JSON group request used to formulate the Group
 * @return details on the newly-created group
 *
 * description Creates a Group with the name from a valid group request
 * responseMessage 200 Successfully created Group
 * responseMessage 409 Group with given name already exists
 */
@Timed
@ExceptionMetered
@POST
@Consumes(APPLICATION_JSON)
public Group createGroup(@Auth AutomationClient automationClient, @Valid CreateGroupRequest groupRequest) {
    Optional<Group> group = groupDAO.getGroup(groupRequest.name);
    if (group.isPresent()) {
        logger.info("Automation ({}) - Group {} already exists", automationClient.getName(), groupRequest.name);
        throw new ConflictException("Group name already exists.");
    }
    long id = groupDAO.createGroup(groupRequest.name, automationClient.getName(), nullToEmpty(groupRequest.description), groupRequest.metadata);
    Map<String, String> extraInfo = new HashMap<>();
    extraInfo.put("deprecated", "true");
    if (groupRequest.description != null) {
        extraInfo.put("description", groupRequest.description);
    }
    if (groupRequest.metadata != null) {
        extraInfo.put("metadata", groupRequest.metadata.toString());
    }
    auditLog.recordEvent(new Event(Instant.now(), EventTag.GROUP_CREATE, automationClient.getName(), groupRequest.name, extraInfo));
    return groupDAO.getGroupById(id).get();
}
Also used : Group(keywhiz.api.model.Group) ConflictException(keywhiz.service.exceptions.ConflictException) HashMap(java.util.HashMap) Event(keywhiz.log.Event) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Timed(com.codahale.metrics.annotation.Timed) ExceptionMetered(com.codahale.metrics.annotation.ExceptionMetered)

Example 3 with Group

use of keywhiz.api.model.Group in project keywhiz by square.

the class AutomationSecretResource method readSecrets.

/**
 * Retrieve secret by a specified name, or all secrets if no name given
 * Note that retrieving all secrets could be an expensive query
 *
 * @param automationClient the client with automation access performing this operation
 * @param name the name of the secret to retrieve, if provided
 * @return details on the specified secret, or all secrets if no name given
 *
 * description Returns a single secret or a set of all secrets
 * responseMessage 200 Found and retrieved secret(s)
 * responseMessage 404 Secret with given name not found (if name provided)
 */
@Timed
@ExceptionMetered
@GET
public ImmutableList<AutomationSecretResponse> readSecrets(@Auth AutomationClient automationClient, @QueryParam("name") String name) {
    ImmutableList.Builder<AutomationSecretResponse> responseBuilder = ImmutableList.builder();
    if (name != null) {
        Optional<Secret> optionalSecret = secretController.getSecretByName(name);
        if (!optionalSecret.isPresent()) {
            throw new NotFoundException("Secret not found.");
        }
        Secret secret = optionalSecret.get();
        ImmutableList<Group> groups = ImmutableList.copyOf(aclDAO.getGroupsFor(secret));
        responseBuilder.add(AutomationSecretResponse.fromSecret(secret, groups));
    } else {
        List<SanitizedSecret> secrets = secretController.getSanitizedSecrets(null, null);
        for (SanitizedSecret sanitizedSecret : secrets) {
            Secret secret = secretController.getSecretById(sanitizedSecret.id()).orElseThrow(() -> new IllegalStateException(format("Cannot find record related to %s", sanitizedSecret)));
            ImmutableList<Group> groups = ImmutableList.copyOf(aclDAO.getGroupsFor(secret));
            responseBuilder.add(AutomationSecretResponse.fromSecret(secret, groups));
        }
    }
    return responseBuilder.build();
}
Also used : Secret(keywhiz.api.model.Secret) SanitizedSecret(keywhiz.api.model.SanitizedSecret) Group(keywhiz.api.model.Group) SanitizedSecret(keywhiz.api.model.SanitizedSecret) ImmutableList(com.google.common.collect.ImmutableList) AutomationSecretResponse(keywhiz.api.AutomationSecretResponse) NotFoundException(javax.ws.rs.NotFoundException) Timed(com.codahale.metrics.annotation.Timed) GET(javax.ws.rs.GET) ExceptionMetered(com.codahale.metrics.annotation.ExceptionMetered)

Example 4 with Group

use of keywhiz.api.model.Group in project keywhiz by square.

the class BackupResource method backup.

/**
 * Backup all secrets for a given group. Returns an encrypted encrypted to
 * the backup key in the main configuration file. Only accessible to automation clients.
 *
 * @param name Group name
 *
 * @return Encrypted archive
 */
@Timed
@ExceptionMetered
@GET
@Path("{key}/group/{group}")
@Produces(APPLICATION_OCTET_STREAM)
public byte[] backup(@Auth AutomationClient automationClient, @PathParam("group") String name, @PathParam("key") String key) {
    if (config.getBackupExportKey(key) == null) {
        throw new NotFoundException("Unknown key: " + key);
    }
    Optional<Group> groupOptional = groupDAO.getGroup(name);
    if (!groupOptional.isPresent()) {
        throw new NotFoundException("Unknown group: " + name);
    }
    Group group = groupOptional.get();
    // SecretDeliveryResponse is the same data a client receives when requesting a secret,
    // so it should have all the relevant information we need (including content, checksum).
    List<SecretDeliveryResponse> secrets = secretController.getSecretsForGroup(group).stream().map(SecretDeliveryResponse::fromSecret).collect(toList());
    String serialized;
    try {
        serialized = objectMapper.writeValueAsString(secrets);
    } catch (JsonProcessingException e) {
        // This should never happen
        logger.error("Unable to backup secrets", e);
        throw new InternalServerErrorException("Unable to backup secrets, check logs for details");
    }
    // Record all checksums of backed up/exported secrets so we can uniquely identify which
    // particular contents were returned in the response from inspection of the audit log.
    Map<String, String> auditInfo = secrets.stream().collect(toMap(SecretDeliveryResponse::getName, SecretDeliveryResponse::getChecksum));
    // Record audit event
    auditLog.recordEvent(new Event(now(), GROUP_BACKUP, automationClient.getName(), group.getName(), auditInfo));
    // Perform encryption & return encrypted data
    try {
        Key exportKey = new Key(config.getBackupExportKey(key));
        Encryptor encryptor = new Encryptor(exportKey);
        encryptor.setEncryptionAlgorithm(AES256);
        encryptor.setSigningAlgorithm(Unsigned);
        encryptor.setCompressionAlgorithm(ZIP);
        ByteArrayInputStream plaintext = new ByteArrayInputStream(serialized.getBytes(UTF_8));
        ByteArrayOutputStream ciphertext = new ByteArrayOutputStream();
        encryptor.encrypt(plaintext, ciphertext, new FileMetadata(format("%s.json", group), UTF8));
        return ciphertext.toByteArray();
    } catch (PGPException | IOException e) {
        logger.error("Unable to backup secrets", e);
        throw new InternalServerErrorException("Unable to backup secrets, check logs for details");
    }
}
Also used : Group(keywhiz.api.model.Group) FileMetadata(org.c02e.jpgpj.FileMetadata) NotFoundException(javax.ws.rs.NotFoundException) Encryptor(org.c02e.jpgpj.Encryptor) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) SecretDeliveryResponse(keywhiz.api.SecretDeliveryResponse) PGPException(org.bouncycastle.openpgp.PGPException) ByteArrayInputStream(java.io.ByteArrayInputStream) InternalServerErrorException(javax.ws.rs.InternalServerErrorException) Event(keywhiz.log.Event) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) Key(org.c02e.jpgpj.Key) 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 5 with Group

use of keywhiz.api.model.Group in project keywhiz by square.

the class GroupsResource method deleteGroup.

/**
 * Delete Group by ID
 *
 * @param user the admin user performing this operation
 * @param groupId the ID of the Group to be deleted
 * @return 200 if the deletion succeeded, 404 if the group was not found
 *
 * description Deletes a single Group if found.
 * Used by Keywhiz CLI and the web ui.
 * responseMessage 200 Found and deleted Group with given ID
 * responseMessage 404 Group with given ID not Found
 */
@Path("{groupId}")
@Timed
@ExceptionMetered
@DELETE
public Response deleteGroup(@Auth User user, @PathParam("groupId") LongParam groupId) {
    logger.info("User '{}' deleting group id={}.", user, groupId);
    Optional<Group> group = groupDAO.getGroupById(groupId.get());
    if (!group.isPresent()) {
        throw new NotFoundException("Group not found.");
    }
    groupDAO.deleteGroup(group.get());
    auditLog.recordEvent(new Event(Instant.now(), EventTag.GROUP_DELETE, user.getName(), group.get().getName()));
    return Response.noContent().build();
}
Also used : Group(keywhiz.api.model.Group) 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)

Aggregations

Group (keywhiz.api.model.Group)46 Client (keywhiz.api.model.Client)18 SanitizedSecret (keywhiz.api.model.SanitizedSecret)18 ExceptionMetered (com.codahale.metrics.annotation.ExceptionMetered)16 Timed (com.codahale.metrics.annotation.Timed)16 NotFoundException (javax.ws.rs.NotFoundException)16 Test (org.junit.Test)16 Event (keywhiz.log.Event)15 Path (javax.ws.rs.Path)13 GET (javax.ws.rs.GET)11 Response (javax.ws.rs.core.Response)9 AutomationClient (keywhiz.api.model.AutomationClient)9 IOException (java.io.IOException)8 HashMap (java.util.HashMap)8 DELETE (javax.ws.rs.DELETE)8 Produces (javax.ws.rs.Produces)8 Consumes (javax.ws.rs.Consumes)7 POST (javax.ws.rs.POST)7 ConflictException (keywhiz.service.exceptions.ConflictException)7 ImmutableList (com.google.common.collect.ImmutableList)6