absl::StatusOr ObjectLoader::BuildState()

in kmsp11/object_loader.cc [204:284]


absl::StatusOr<ObjectStoreState> ObjectLoader::BuildState(
    const KmsClient& client) {
  // In the initial implementation of Provider::LoopRefresh, there is no danger
  // of overlapping calls to BuildState. That said, holding the mutex for the
  // duration of BuildState seems like a pretty cheap way to guard against an
  // unintentional change that causes BuildState calls to overlap.
  absl::MutexLock lock(&cache_mutex_);
  ObjectStoreState result;

  kms_v1::ListCryptoKeysRequest req;
  req.set_parent(key_ring_name_);
  CryptoKeysRange keys = client.ListCryptoKeys(req);

  for (CryptoKeysRange::iterator it = keys.begin(); it != keys.end(); it++) {
    ASSIGN_OR_RETURN(kms_v1::CryptoKey key, *it);
    if (!IsLoadable(key)) {
      continue;
    }

    kms_v1::ListCryptoKeyVersionsRequest req;
    req.set_parent(key.name());
    CryptoKeyVersionsRange v = client.ListCryptoKeyVersions(req);

    for (CryptoKeyVersionsRange::iterator it = v.begin(); it != v.end(); it++) {
      ASSIGN_OR_RETURN(kms_v1::CryptoKeyVersion ckv, *it);
      if (!IsLoadable(ckv)) {
        continue;
      }

      Key* cached_key = cache_.Get(ckv.name());
      if (cached_key) {
        *result.add_keys() = *cached_key;
        continue;
      }

      if (key.purpose() == kms_v1::CryptoKey::MAC ||
          key.purpose() == kms_v1::CryptoKey::RAW_ENCRYPT_DECRYPT) {
        *result.add_keys() = *cache_.StoreSecretKey(ckv);
      } else {
        kms_v1::GetPublicKeyRequest pub_req;
        pub_req.set_name(ckv.name());

        ASSIGN_OR_RETURN(kms_v1::PublicKey pub_resp,
                         client.GetPublicKey(pub_req));
        ASSIGN_OR_RETURN(bssl::UniquePtr<EVP_PKEY> pub,
                         ParseX509PublicKeyPem(pub_resp.pem()));
        ASSIGN_OR_RETURN(std::string public_key_der,
                         MarshalX509PublicKeyDer(pub.get()));

        std::string cert_der;
        if (auto it = user_certs_.find(public_key_der);
            it != user_certs_.end()) {
          cert_der = it->second;
        } else if (cert_authority_) {
          ASSIGN_OR_RETURN(bssl::UniquePtr<X509> cert,
                           cert_authority_->GenerateCert(ckv, pub.get()));
          ASSIGN_OR_RETURN(cert_der, MarshalX509CertificateDer(cert.get()));
        }

        *result.add_keys() = *cache_.Store(ckv, public_key_der, cert_der);
      }
    }
  }

  // Compute the unused user certificates by copying all of them, then removing
  // the ones that were actually used.
  absl::flat_hash_set<std::string> unused_user_certs;
  for (const auto& [spki, cert] : user_certs_) {
    unused_user_certs.emplace(cert);
  }
  for (const Key& key : result.keys()) {
    unused_user_certs.erase(key.certificate().x509_der());
  }
  if (unused_user_certs.size() > 0) {
    LOG(INFO) << "INFO: one or more provided certificates could not be matched "
                 "to a KMS key.";
  }

  cache_.EvictUnused(result);
  return result;
}