Example #1
0
Future<AuthenticationResult> BasicAuthenticatorProcess::authenticate(
    const Request& request)
{
  AuthenticationResult unauthorized;
  unauthorized.unauthorized =
    Unauthorized(vector<string>({"Basic realm=\"" + realm_ + "\""}));

  Option<string> credentials = request.headers.get("Authorization");

  if (credentials.isNone()) {
    return unauthorized;
  }

  vector<string> components = strings::split(credentials.get(), " ");

  if (components.size() != 2 || components[0] != "Basic") {
    return unauthorized;
  }

  Try<string> decoded = base64::decode(components[1]);

  if (decoded.isError()) {
    return unauthorized;
  }

  vector<string> credential = strings::split(decoded.get(), ":");

  if (credential.size() != 2 ||
      !credentials_.contains(credential[0]) ||
      credentials_.at(credential[0]) != credential[1]) {
    return unauthorized;
  }

  AuthenticationResult authenticated;
  authenticated.principal = credential[0];
  return authenticated;
}
Example #2
0
Future<http::Response> ResourceProviderManagerProcess::api(
    const http::Request& request,
    const Option<Principal>& principal)
{
  if (request.method != "POST") {
    return MethodNotAllowed({"POST"}, request.method);
  }

  v1::resource_provider::Call v1Call;

  // TODO(anand): Content type values are case-insensitive.
  Option<string> contentType = request.headers.get("Content-Type");

  if (contentType.isNone()) {
    return BadRequest("Expecting 'Content-Type' to be present");
  }

  if (contentType.get() == APPLICATION_PROTOBUF) {
    if (!v1Call.ParseFromString(request.body)) {
      return BadRequest("Failed to parse body into Call protobuf");
    }
  } else if (contentType.get() == APPLICATION_JSON) {
    Try<JSON::Value> value = JSON::parse(request.body);
    if (value.isError()) {
      return BadRequest("Failed to parse body into JSON: " + value.error());
    }

    Try<v1::resource_provider::Call> parse =
      ::protobuf::parse<v1::resource_provider::Call>(value.get());

    if (parse.isError()) {
      return BadRequest("Failed to convert JSON into Call protobuf: " +
                        parse.error());
    }

    v1Call = parse.get();
  } else {
    return UnsupportedMediaType(
        string("Expecting 'Content-Type' of ") +
        APPLICATION_JSON + " or " + APPLICATION_PROTOBUF);
  }

  Call call = devolve(v1Call);

  Option<Error> error = validate(call);
  if (error.isSome()) {
    return BadRequest(
        "Failed to validate resource_provider::Call: " + error->message);
  }

  ContentType acceptType;
  if (request.acceptsMediaType(APPLICATION_JSON)) {
    acceptType = ContentType::JSON;
  } else if (request.acceptsMediaType(APPLICATION_PROTOBUF)) {
    acceptType = ContentType::PROTOBUF;
  } else {
    return NotAcceptable(
        string("Expecting 'Accept' to allow ") +
        "'" + APPLICATION_PROTOBUF + "' or '" + APPLICATION_JSON + "'");
  }

  switch(call.type()) {
    case Call::UNKNOWN: {
      return NotImplemented();
    }

    case Call::SUBSCRIBE: {
      Pipe pipe;
      OK ok;

      ok.headers["Content-Type"] = stringify(acceptType);
      ok.type = http::Response::PIPE;
      ok.reader = pipe.reader();

      HttpConnection http(pipe.writer(), acceptType);
      subscribe(http, call.subscribe());

      return ok;
    }

    case Call::UPDATE: {
      if (!resourceProviders.contains(call.resource_provider_id())) {
        return BadRequest("Resource provider cannot be found");
      }

      auto resourceProvider = resourceProviders.at(call.resource_provider_id());

      update(&resourceProvider, call.update());
      return Accepted();
    }
  }

  UNREACHABLE();
}