/*
 *
 * Copyright 2019 gRPC authors.
 *
 * 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.
 *
 */

#include "upb/upb.hpp"

#include <grpc/grpc_security.h>
#include <grpc/support/log.h>
#include <grpcpp/security/alts_context.h>
#include <grpcpp/security/alts_util.h>

#include "src/core/lib/gprpp/memory.h"
#include "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h"
#include "src/cpp/common/secure_auth_context.h"
#include "src/proto/grpc/gcp/altscontext.upb.h"

namespace grpc {
namespace experimental {

std::unique_ptr<AltsContext> GetAltsContextFromAuthContext(
    const std::shared_ptr<const AuthContext>& auth_context) {
  if (auth_context == nullptr) {
    gpr_log(GPR_ERROR, "auth_context is nullptr.");
    return nullptr;
  }
  std::vector<string_ref> ctx_vector =
      auth_context->FindPropertyValues(TSI_ALTS_CONTEXT);
  if (ctx_vector.size() != 1) {
    gpr_log(GPR_ERROR, "contains zero or more than one ALTS context.");
    return nullptr;
  }
  upb::Arena context_arena;
  grpc_gcp_AltsContext* ctx = grpc_gcp_AltsContext_parse(
      ctx_vector[0].data(), ctx_vector[0].size(), context_arena.ptr());
  if (ctx == nullptr) {
    gpr_log(GPR_ERROR, "fails to parse ALTS context.");
    return nullptr;
  }
  if (grpc_gcp_AltsContext_security_level(ctx) < GRPC_SECURITY_MIN ||
      grpc_gcp_AltsContext_security_level(ctx) > GRPC_SECURITY_MAX) {
    gpr_log(GPR_ERROR, "security_level is invalid.");
    return nullptr;
  }
  return absl::make_unique<AltsContext>(AltsContext(ctx));
}

grpc::Status AltsClientAuthzCheck(
    const std::shared_ptr<const AuthContext>& auth_context,
    const std::vector<std::string>& expected_service_accounts) {
  std::unique_ptr<AltsContext> alts_ctx =
      GetAltsContextFromAuthContext(auth_context);
  if (alts_ctx == nullptr) {
    return grpc::Status(grpc::StatusCode::PERMISSION_DENIED,
                        "fails to parse ALTS context.");
  }
  if (std::find(expected_service_accounts.begin(),
                expected_service_accounts.end(),
                alts_ctx->peer_service_account()) !=
      expected_service_accounts.end()) {
    return grpc::Status::OK;
  }
  return grpc::Status(
      grpc::StatusCode::PERMISSION_DENIED,
      "client " + alts_ctx->peer_service_account() + " is not authorized.");
}

}  // namespace experimental
}  // namespace grpc
