static bool set_jwt_public_signing_keys()

in src/node/jwt.h [132:275]


  static bool set_jwt_public_signing_keys(
    kv::Tx& tx,
    const ProposalId& proposal_id,
    std::string issuer,
    const JwtIssuerMetadata& issuer_metadata,
    const JsonWebKeySet& jwks)
  {
    auto keys = tx.rw<JwtPublicSigningKeys>(Tables::JWT_PUBLIC_SIGNING_KEYS);
    auto key_issuer =
      tx.rw<JwtPublicSigningKeyIssuer>(Tables::JWT_PUBLIC_SIGNING_KEY_ISSUER);

    auto log_prefix = proposal_id.empty() ?
      "JWT key auto-refresh" :
      fmt::format("Proposal {}", proposal_id);

    // add keys
    if (jwks.keys.empty())
    {
      LOG_FAIL_FMT("{}: JWKS has no keys", log_prefix, proposal_id);
      return false;
    }
    std::map<std::string, std::vector<uint8_t>> new_keys;
    for (auto& jwk : jwks.keys)
    {
      if (keys->has(jwk.kid) && key_issuer->get(jwk.kid).value() != issuer)
      {
        LOG_FAIL_FMT(
          "{}: key id {} already added for different issuer",
          log_prefix,
          jwk.kid);
        return false;
      }
      if (jwk.x5c.empty())
      {
        LOG_FAIL_FMT("{}: JWKS is invalid (empty x5c)", log_prefix);
        return false;
      }

      auto& der_base64 = jwk.x5c[0];
      ccf::Cert der;
      try
      {
        der = crypto::raw_from_b64(der_base64);
      }
      catch (const std::invalid_argument& e)
      {
        LOG_FAIL_FMT(
          "{}: Could not parse x5c of key id {}: {}",
          log_prefix,
          jwk.kid,
          e.what());
        return false;
      }

      std::map<std::string, std::vector<uint8_t>> claims;
      bool has_key_policy_sgx_claims = issuer_metadata.key_policy.has_value() &&
        issuer_metadata.key_policy.value().sgx_claims.has_value() &&
        !issuer_metadata.key_policy.value().sgx_claims.value().empty();
      if (
        issuer_metadata.key_filter == JwtIssuerKeyFilter::SGX ||
        has_key_policy_sgx_claims)
      {
        oe_verify_attestation_certificate_with_evidence(
          der.data(),
          der.size(),
          oe_verify_attestation_certificate_with_evidence_cb,
          &claims);
      }

      if (
        issuer_metadata.key_filter == JwtIssuerKeyFilter::SGX && claims.empty())
      {
        LOG_INFO_FMT(
          "{}: Skipping JWT signing key with kid {} (not OE "
          "attested)",
          log_prefix,
          jwk.kid);
        continue;
      }

      if (has_key_policy_sgx_claims)
      {
        for (auto& [claim_name, expected_claim_val_hex] :
             issuer_metadata.key_policy.value().sgx_claims.value())
        {
          if (claims.find(claim_name) == claims.end())
          {
            LOG_FAIL_FMT(
              "{}: JWKS kid {} is missing the {} SGX claim",
              log_prefix,
              jwk.kid,
              claim_name);
            return false;
          }
          auto& actual_claim_val = claims[claim_name];
          auto actual_claim_val_hex = ds::to_hex(actual_claim_val);
          if (expected_claim_val_hex != actual_claim_val_hex)
          {
            LOG_FAIL_FMT(
              "{}: JWKS kid {} has a mismatching {} SGX claim: {} != {}",
              log_prefix,
              jwk.kid,
              claim_name,
              expected_claim_val_hex,
              actual_claim_val_hex);
            return false;
          }
        }
      }
      else
      {
        try
        {
          crypto::check_is_cert(der);
        }
        catch (std::invalid_argument& exc)
        {
          LOG_FAIL_FMT(
            "{}: JWKS kid {} has an invalid X.509 certificate: {}",
            log_prefix,
            jwk.kid,
            exc.what());
          return false;
        }
      }
      LOG_INFO_FMT(
        "{}: Storing JWT signing key with kid {}", log_prefix, jwk.kid);
      new_keys.emplace(jwk.kid, der);
    }
    if (new_keys.empty())
    {
      LOG_FAIL_FMT("{}: no keys left after applying filter", log_prefix);
      return false;
    }

    remove_jwt_public_signing_keys(tx, issuer);
    for (auto& [kid, der] : new_keys)
    {
      keys->put(kid, der);
      key_issuer->put(kid, issuer);
    }

    return true;
  }