All Downloads are FREE. Search and download functionalities are using the official Maven repository.

keywhiz.service.resources.SecretDeliveryResource Maven / Gradle / Ivy

There is a newer version: 0.10.1
Show newest version
/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package keywhiz.service.resources;

import com.google.common.annotations.VisibleForTesting;
import io.dropwizard.auth.Auth;
import java.text.ParseException;
import java.util.Optional;
import javax.inject.Inject;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.GET;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import keywhiz.api.SecretDeliveryResponse;
import keywhiz.api.model.Client;
import keywhiz.api.model.SanitizedSecret;
import keywhiz.api.model.Secret;
import keywhiz.service.config.Readonly;
import keywhiz.service.daos.AclDAO;
import keywhiz.service.daos.AclDAO.AclDAOFactory;
import keywhiz.service.daos.ClientDAO;
import keywhiz.service.daos.ClientDAO.ClientDAOFactory;
import keywhiz.service.daos.SecretController;
import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static java.lang.String.format;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static keywhiz.api.model.Secret.splitNameAndVersion;

/**
 * @parentEndpointName secret
 *
 * @resourceDescription Retrieve Secret by name
 */
@Path("/secret/{secretName}")
@Produces(APPLICATION_JSON)
public class SecretDeliveryResource {
  private static final Logger logger = LoggerFactory.getLogger(SecretDeliveryResource.class);

  private final SecretController secretController;
  private final AclDAO aclDAO;
  private final ClientDAO clientDAO;

  @Inject public SecretDeliveryResource(@Readonly SecretController secretController,
      AclDAOFactory aclDAOFactory, ClientDAOFactory clientDAOFactory) {
    this.secretController = secretController;
    this.aclDAO = aclDAOFactory.readonly();
    this.clientDAO = clientDAOFactory.readonly();
  }

  @VisibleForTesting SecretDeliveryResource(SecretController secretController, AclDAO aclDAO,
      ClientDAO clientDAO) {
    this.secretController = secretController;
    this.aclDAO = aclDAO;
    this.clientDAO = clientDAO;
  }

  /**
   * Retrieve Secret by name
   *
   * @excludeParams client
   * @param secretName the name of the Secret to retrieve
   *
   * @description Returns a single Secret if found
   * @responseMessage 200 Found and retrieved Secret with given name
   * @responseMessage 403 Secret is not assigned to Client
   * @responseMessage 404 Secret with given name not found
   * @responseMessage 500 Secret response could not be generated for given Secret
   */
  @GET
  public SecretDeliveryResponse getSecret(@NotEmpty @PathParam("secretName") String secretName,
                                          @Auth Client client) {
    String[] parts;
    try {
      parts = splitNameAndVersion(secretName);
    } catch (ParseException e) {
      throw new BadRequestException(format("Invalid secret name '%s'", secretName));
    }
    String name = parts[0];
    String version = parts[1];

    Optional sanitizedSecret = aclDAO.getSanitizedSecretFor(client, name, version);
    Optional secret = secretController.getSecretByNameAndVersion(name, version);

    if (!sanitizedSecret.isPresent()) {
      boolean clientExists = clientDAO.getClient(client.getName()).isPresent();
      boolean secretExists = secret.isPresent();

      if (clientExists && secretExists) {
        throw new ForbiddenException(format("Access denied: %s at '%s' by '%s'", client.getName(),
                "/secret/" + secretName, client));
      } else {
        if (clientExists) {
          logger.info("Client {} requested unknown secret {}", client.getName(), secretName);
        }
        throw new NotFoundException();
      }
    }

    logger.info("Client {} granted access to {}.", client.getName(), secretName);
    try {
      return SecretDeliveryResponse.fromSecret(secret.get());
    } catch (IllegalArgumentException e) {
      logger.error("Failed creating response for secret {}: {}", secretName, e);
      throw new InternalServerErrorException();
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy