grpc 1.83.1 → 1.84.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Makefile +21 -17
- data/include/grpc/credentials.h +10 -0
- data/include/grpc/grpc_security_constants.h +2 -0
- data/include/grpc/impl/channel_arg_names.h +9 -0
- data/src/core/call/call_filters.h +4 -2
- data/src/core/call/client_call.cc +20 -8
- data/src/core/call/client_call.h +4 -0
- data/src/core/call/interception_chain.cc +2 -0
- data/src/core/call/interception_chain.h +14 -1
- data/src/core/call/metadata.cc +1 -3
- data/src/core/call/metadata_batch.h +13 -5
- data/src/core/call/server_call.cc +31 -14
- data/src/core/call/server_call.h +4 -0
- data/src/core/channelz/text_encode.cc +9 -4
- data/src/core/channelz/v2tov1/convert.cc +2 -2
- data/src/core/client_channel/backup_poller.cc +1 -2
- data/src/core/client_channel/client_channel.cc +6 -33
- data/src/core/client_channel/client_channel_filter.cc +22 -55
- data/src/core/client_channel/client_channel_filter.h +2 -2
- data/src/core/client_channel/client_channel_service_config.cc +3 -19
- data/src/core/client_channel/direct_channel.cc +7 -1
- data/src/core/client_channel/direct_channel.h +2 -2
- data/src/core/client_channel/load_balanced_call_destination.cc +5 -3
- data/src/core/client_channel/retry_filter_legacy_call_data.cc +5 -12
- data/src/core/client_channel/subchannel.cc +310 -1058
- data/src/core/client_channel/subchannel.h +44 -329
- data/src/core/client_channel/subchannel_metrics.cc +48 -0
- data/src/core/client_channel/subchannel_metrics.h +60 -0
- data/src/core/credentials/call/external/file_external_account_credentials.cc +1 -1
- data/src/core/credentials/call/external/url_external_account_credentials.cc +2 -3
- data/src/core/credentials/call/gcp_service_account_identity/gcp_service_account_identity_credentials.cc +8 -24
- data/src/core/credentials/call/gcp_service_account_identity/gcp_service_account_identity_credentials.h +3 -6
- data/src/core/credentials/call/gdch_service_account/gdch_service_account_credentials.cc +525 -0
- data/src/core/credentials/call/gdch_service_account/gdch_service_account_credentials.h +138 -0
- data/src/core/credentials/call/json_util.h +1 -0
- data/src/core/credentials/call/jwt/json_token.cc +10 -2
- data/src/core/credentials/call/jwt/jwt_verifier.cc +15 -1
- data/src/core/credentials/call/jwt_token_file/jwt_token_file_call_credentials.cc +1 -1
- data/src/core/credentials/call/oauth2/oauth2_credentials.cc +42 -79
- data/src/core/credentials/call/oauth2/oauth2_credentials.h +2 -5
- data/src/core/credentials/call/token_fetcher/token_fetcher_credentials.cc +52 -31
- data/src/core/credentials/call/token_fetcher/token_fetcher_credentials.h +21 -8
- data/src/core/credentials/transport/google_default/google_default_credentials.cc +3 -4
- data/src/core/credentials/transport/ssl/ssl_credentials.cc +59 -72
- data/src/core/credentials/transport/ssl/ssl_credentials.h +9 -8
- data/src/core/credentials/transport/ssl/ssl_security_connector.cc +12 -6
- data/src/core/credentials/transport/ssl/ssl_security_connector.h +4 -4
- data/src/core/credentials/transport/tls/grpc_tls_certificate_distributor.cc +29 -18
- data/src/core/credentials/transport/tls/grpc_tls_certificate_distributor.h +9 -6
- data/src/core/credentials/transport/tls/grpc_tls_certificate_provider.cc +45 -56
- data/src/core/credentials/transport/tls/grpc_tls_certificate_provider.h +5 -4
- data/src/core/credentials/transport/tls/grpc_tls_certificate_selector.h +26 -0
- data/src/core/credentials/transport/tls/grpc_tls_crl_provider.cc +1 -1
- data/src/core/credentials/transport/tls/load_system_roots.h +2 -6
- data/src/core/credentials/transport/tls/load_system_roots_fallback.cc +2 -4
- data/src/core/credentials/transport/tls/load_system_roots_supported.cc +13 -15
- data/src/core/credentials/transport/tls/load_system_roots_supported.h +3 -2
- data/src/core/credentials/transport/tls/load_system_roots_windows.cc +5 -8
- data/src/core/credentials/transport/tls/spiffe_utils.cc +1 -1
- data/src/core/credentials/transport/tls/ssl_utils.cc +39 -28
- data/src/core/credentials/transport/tls/ssl_utils.h +12 -49
- data/src/core/credentials/transport/tls/tls_security_connector.cc +48 -33
- data/src/core/credentials/transport/tls/tls_security_connector.h +31 -10
- data/src/core/ext/filters/channel_idle/legacy_channel_idle_filter.cc +15 -11
- data/src/core/ext/filters/http/http_filters_plugin.cc +20 -9
- data/src/core/ext/filters/rbac/rbac_filter.cc +43 -21
- data/src/core/ext/filters/rbac/rbac_filter.h +21 -3
- data/src/core/ext/filters/rbac/rbac_service_config_parser.cc +2 -2
- data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +1 -1
- data/src/core/ext/transport/chttp2/server/chttp2_server.cc +6 -20
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +32 -67
- data/src/core/ext/transport/chttp2/transport/flow_control.cc +2 -0
- data/src/core/ext/transport/chttp2/transport/flow_control.h +78 -4
- data/src/core/ext/transport/chttp2/transport/frame.h +2 -0
- data/src/core/ext/transport/chttp2/transport/frame_data.cc +3 -4
- data/src/core/ext/transport/chttp2/transport/goaway.h +7 -0
- data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +5 -3
- data/src/core/ext/transport/chttp2/transport/hpack_parser.h +3 -1
- data/src/core/ext/transport/chttp2/transport/http2_client_transport.cc +141 -130
- data/src/core/ext/transport/chttp2/transport/http2_client_transport.h +22 -22
- data/src/core/ext/transport/chttp2/transport/http2_server_transport.cc +402 -269
- data/src/core/ext/transport/chttp2/transport/http2_server_transport.h +80 -49
- data/src/core/ext/transport/chttp2/transport/http2_settings_promises.h +1 -2
- data/src/core/ext/transport/chttp2/transport/http2_status.h +38 -37
- data/src/core/ext/transport/chttp2/transport/http2_transport.cc +178 -5
- data/src/core/ext/transport/chttp2/transport/http2_transport.h +345 -5
- data/src/core/ext/transport/chttp2/transport/parsing.cc +5 -5
- data/src/core/ext/transport/chttp2/transport/ping_promise.cc +3 -2
- data/src/core/ext/transport/chttp2/transport/ping_promise.h +25 -5
- data/src/core/ext/transport/chttp2/transport/ping_rate_policy.cc +3 -4
- data/src/core/ext/transport/chttp2/transport/read_context.h +30 -3
- data/src/core/ext/transport/chttp2/transport/stream.h +65 -23
- data/src/core/ext/transport/chttp2/transport/writing.cc +0 -3
- data/src/core/ext/transport/inproc/inproc_transport.cc +1 -5
- data/src/core/ext/transport/inproc/legacy_inproc_transport.cc +4 -17
- data/src/core/ext/upb-gen/envoy/extensions/filters/http/ext_proc/v3/ext_proc.upb.h +1912 -0
- data/src/core/ext/upb-gen/envoy/extensions/filters/http/ext_proc/v3/ext_proc.upb_minitable.c +300 -0
- data/src/core/ext/upb-gen/envoy/extensions/filters/http/ext_proc/v3/ext_proc.upb_minitable.h +37 -0
- data/src/core/ext/upb-gen/envoy/extensions/filters/http/ext_proc/v3/processing_mode.upb.h +187 -0
- data/src/core/ext/upb-gen/envoy/extensions/filters/http/ext_proc/v3/processing_mode.upb_minitable.c +64 -0
- data/src/core/ext/upb-gen/envoy/extensions/filters/http/ext_proc/v3/processing_mode.upb_minitable.h +31 -0
- data/src/core/ext/upb-gen/envoy/service/ext_proc/v3/external_processor.upb.h +2362 -0
- data/src/core/ext/upb-gen/envoy/service/ext_proc/v3/external_processor.upb_minitable.c +556 -0
- data/src/core/ext/upb-gen/envoy/service/ext_proc/v3/external_processor.upb_minitable.h +47 -0
- data/src/core/ext/upb-gen/{src/proto/grpc/channelz → grpc/channelz/v1}/channelz.upb.h +5 -5
- data/src/core/ext/upb-gen/{src/proto/grpc/channelz → grpc/channelz/v1}/channelz.upb_minitable.c +3 -3
- data/src/core/ext/upb-gen/{src/proto/grpc/channelz → grpc/channelz/v1}/channelz.upb_minitable.h +5 -5
- data/src/core/ext/upbdefs-gen/envoy/extensions/filters/http/ext_proc/v3/ext_proc.upbdefs.c +453 -0
- data/src/core/ext/upbdefs-gen/envoy/extensions/filters/http/ext_proc/v3/ext_proc.upbdefs.h +67 -0
- data/src/core/ext/upbdefs-gen/envoy/extensions/filters/http/ext_proc/v3/processing_mode.upbdefs.c +142 -0
- data/src/core/ext/upbdefs-gen/envoy/extensions/filters/http/ext_proc/v3/processing_mode.upbdefs.h +37 -0
- data/src/core/ext/upbdefs-gen/grpc/channelz/v1/channelz.upbdefs.c +715 -0
- data/src/core/ext/upbdefs-gen/{src/proto/grpc/channelz → grpc/channelz/v1}/channelz.upbdefs.h +44 -44
- data/src/core/filter/auth/server_auth_filter.cc +2 -3
- data/src/core/filter/composite/composite_filter.cc +45 -33
- data/src/core/filter/composite/composite_filter.h +5 -4
- data/src/core/filter/ext_proc/ext_proc_filter.cc +224 -0
- data/src/core/filter/ext_proc/ext_proc_filter.h +155 -0
- data/src/core/filter/ext_proc/ext_proc_messages.cc +701 -0
- data/src/core/filter/ext_proc/ext_proc_messages.h +297 -0
- data/src/core/filter/filter_args.h +13 -2
- data/src/core/handshaker/http_connect/http_proxy_mapper.cc +30 -3
- data/src/core/handshaker/security/security_handshaker.cc +9 -6
- data/src/core/lib/channel/channel_stack.cc +3 -0
- data/src/core/lib/channel/channel_stack.h +2 -0
- data/src/core/lib/channel/channel_stack_builder_impl.cc +1 -2
- data/src/core/lib/channel/promise_based_filter.cc +132 -20
- data/src/core/lib/channel/promise_based_filter.h +42 -12
- data/src/core/lib/compression/compression_internal.cc +4 -5
- data/src/core/lib/debug/trace_flags.cc +8 -0
- data/src/core/lib/debug/trace_flags.h +3 -0
- data/src/core/lib/event_engine/ares_resolver.cc +54 -50
- data/src/core/lib/event_engine/ares_resolver.h +3 -2
- data/src/core/lib/event_engine/posix_engine/ev_epoll1_linux.cc +3 -3
- data/src/core/lib/event_engine/posix_engine/ev_poll_posix.cc +4 -10
- data/src/core/lib/event_engine/posix_engine/posix_endpoint.cc +74 -33
- data/src/core/lib/event_engine/posix_engine/posix_endpoint.h +4 -4
- data/src/core/lib/event_engine/posix_engine/posix_engine.cc +6 -2
- data/src/core/lib/event_engine/posix_engine/tcp_socket_utils.cc +3 -0
- data/src/core/lib/event_engine/posix_engine/tcp_socket_utils.h +3 -0
- data/src/core/lib/event_engine/windows/windows_endpoint.cc +1 -3
- data/src/core/lib/experiments/experiments.cc +60 -96
- data/src/core/lib/experiments/experiments.h +34 -50
- data/src/core/lib/iomgr/cfstream_handle.cc +2 -6
- data/src/core/lib/iomgr/endpoint_cfstream.cc +3 -10
- data/src/core/lib/iomgr/error.cc +2 -6
- data/src/core/lib/iomgr/error_cfstream.cc +1 -1
- data/src/core/lib/iomgr/ev_poll_posix.cc +5 -9
- data/src/core/lib/iomgr/event_engine_shims/closure.cc +1 -1
- data/src/core/lib/iomgr/event_engine_shims/endpoint.cc +1 -2
- data/src/core/lib/iomgr/event_engine_shims/tcp_client.cc +1 -2
- data/src/core/lib/iomgr/iomgr_posix.cc +0 -4
- data/src/core/lib/iomgr/iomgr_posix_cfstream.cc +0 -4
- data/src/core/lib/iomgr/iomgr_windows.cc +0 -4
- data/src/core/lib/iomgr/socket_factory_posix.h +1 -1
- data/src/core/lib/iomgr/socket_utils_posix.cc +3 -0
- data/src/core/lib/iomgr/socket_utils_posix.h +3 -0
- data/src/core/lib/iomgr/systemd_utils.cc +0 -1
- data/src/core/lib/iomgr/tcp_client.h +1 -1
- data/src/core/lib/iomgr/tcp_posix.cc +23 -15
- data/src/core/lib/iomgr/tcp_server.h +1 -1
- data/src/core/lib/iomgr/tcp_server_posix.cc +2 -3
- data/src/core/lib/iomgr/tcp_server_utils_posix.h +0 -1
- data/src/core/lib/iomgr/tcp_server_windows.cc +0 -1
- data/src/core/lib/iomgr/tcp_windows.cc +5 -10
- data/src/core/lib/iomgr/unix_sockets_posix.cc +2 -4
- data/src/core/lib/iomgr/unix_sockets_posix.h +3 -1
- data/src/core/lib/iomgr/vsock.h +3 -1
- data/src/core/lib/resource_quota/memory_quota.cc +1 -1
- data/src/core/lib/security/authorization/rbac_policy.cc +139 -56
- data/src/core/lib/security/authorization/rbac_policy.h +21 -3
- data/src/core/lib/surface/call.cc +3 -9
- data/src/core/lib/surface/call_utils.h +113 -0
- data/src/core/lib/surface/channel_create.cc +1 -1
- data/src/core/lib/surface/channel_create.h +0 -2
- data/src/core/lib/surface/channel_init.cc +77 -38
- data/src/core/lib/surface/channel_init.h +30 -16
- data/src/core/lib/surface/filter_stack_call.cc +5 -10
- data/src/core/lib/surface/init.cc +13 -27
- data/src/core/lib/surface/version.cc +1 -1
- data/src/core/lib/transport/error_utils.cc +0 -27
- data/src/core/lib/transport/error_utils.h +0 -16
- data/src/core/lib/transport/transport.h +7 -5
- data/src/core/load_balancing/pick_first/pick_first.cc +2 -0
- data/src/core/load_balancing/rls/rls.cc +28 -11
- data/src/core/load_balancing/weighted_round_robin/weighted_round_robin.cc +33 -42
- data/src/core/load_balancing/weighted_round_robin/weighted_round_robin.h +0 -2
- data/src/core/load_balancing/xds/cds.cc +3 -1
- data/src/core/load_balancing/xds/xds_cluster_impl.cc +0 -1
- data/src/core/mitigation_engine/mitigation.h +14 -5
- data/src/core/mitigation_engine/mitigation_engine.h +7 -3
- data/src/core/mitigation_engine/mitigation_provider.h +2 -1
- data/src/core/plugin_registry/grpc_plugin_registry.cc +39 -8
- data/src/core/resolver/dns/{event_engine/event_engine_client_channel_resolver.cc → dns_resolver.cc} +42 -41
- data/src/core/resolver/dns/{event_engine/event_engine_client_channel_resolver.h → dns_resolver.h} +8 -5
- data/src/core/resolver/dns/{event_engine/service_config_helper.cc → service_config_helper.cc} +1 -1
- data/src/core/resolver/dns/{event_engine/service_config_helper.h → service_config_helper.h} +3 -3
- data/src/core/resolver/endpoint_addresses.h +3 -0
- data/src/core/resolver/google_c2p/google_c2p_resolver.cc +2 -1
- data/src/core/resolver/xds/xds_resolver.cc +35 -9
- data/src/core/server/server.cc +2 -6
- data/src/core/server/server_config_selector.h +18 -3
- data/src/core/server/server_config_selector_filter.cc +178 -91
- data/src/core/server/server_config_selector_filter.h +58 -3
- data/src/core/server/xds_server_config_fetcher.cc +196 -129
- data/src/core/server/xds_server_config_fetcher.h +49 -0
- data/src/core/server/xds_server_config_fetcher_legacy.cc +41 -37
- data/src/core/telemetry/histogram.h +94 -14
- data/src/core/telemetry/instrument.cc +179 -74
- data/src/core/telemetry/instrument.h +78 -30
- data/src/core/telemetry/metrics.h +5 -0
- data/src/core/{resolver/dns/dns_resolver_plugin.h → telemetry/telemetry_label.h} +12 -8
- data/src/core/tsi/alts/crypt/aes_gcm.cc +10 -13
- data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +2 -2
- data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +3 -1
- data/src/core/tsi/ssl_telemetry_utils.cc +216 -259
- data/src/core/tsi/ssl_telemetry_utils.h +12 -2
- data/src/core/tsi/ssl_transport_security.cc +238 -80
- data/src/core/tsi/ssl_transport_security.h +63 -33
- data/src/core/tsi/tls_telemetry.cc +31 -0
- data/src/core/tsi/tls_telemetry.h +47 -0
- data/src/core/tsi/transport_security.cc +2 -2
- data/src/core/tsi/transport_security.h +1 -1
- data/src/core/tsi/transport_security_interface.h +1 -1
- data/src/core/{resolver/dns/native/dns_resolver.h → util/address_sorting_init.cc} +21 -8
- data/src/core/{resolver/dns/c_ares/grpc_ares_wrapper_posix.cc → util/address_sorting_init.h} +7 -8
- data/src/core/util/http_client/httpcli.cc +16 -53
- data/src/core/util/http_client/httpcli.h +0 -7
- data/src/core/util/http_client/httpcli_security_connector.cc +13 -8
- data/src/core/util/linux/cpu.cc +1 -1
- data/src/core/util/load_file.cc +3 -9
- data/src/core/util/load_file.h +3 -4
- data/src/core/util/matchers.h +8 -0
- data/src/core/util/posix/cpu.cc +1 -1
- data/src/core/util/status_helper.cc +0 -20
- data/src/core/util/status_helper.h +3 -14
- data/src/core/xds/grpc/xds_audit_logger_registry.cc +51 -31
- data/src/core/xds/grpc/xds_audit_logger_registry.h +17 -3
- data/src/core/xds/grpc/xds_bootstrap_grpc.cc +2 -10
- data/src/core/xds/grpc/xds_bootstrap_grpc.h +8 -6
- data/src/core/xds/grpc/xds_bootstrap_grpc_builder.cc +488 -0
- data/src/core/xds/grpc/xds_bootstrap_grpc_builder.h +97 -0
- data/src/core/xds/grpc/xds_certificate_provider.cc +7 -7
- data/src/core/xds/grpc/xds_client_grpc.cc +4 -8
- data/src/core/xds/grpc/xds_client_grpc.h +0 -4
- data/src/core/xds/grpc/xds_cluster.h +1 -0
- data/src/core/xds/grpc/xds_cluster_parser.cc +1 -5
- data/src/core/xds/grpc/xds_cluster_parser.h +0 -2
- data/src/core/xds/grpc/xds_cluster_specifier_plugin.cc +0 -2
- data/src/core/xds/grpc/xds_cluster_specifier_plugin.h +0 -2
- data/src/core/xds/grpc/xds_common_types.cc +0 -91
- data/src/core/xds/grpc/xds_common_types.h +1 -47
- data/src/core/xds/grpc/xds_common_types_parser.cc +84 -378
- data/src/core/xds/grpc/xds_common_types_parser.h +9 -11
- data/src/core/xds/grpc/xds_endpoint_parser.cc +0 -2
- data/src/core/xds/grpc/xds_grpc_service_parser.cc +177 -0
- data/src/core/{resolver/dns/c_ares/dns_resolver_ares.h → xds/grpc/xds_grpc_service_parser.h} +14 -9
- data/src/core/xds/grpc/xds_http_composite_filter.cc +26 -21
- data/src/core/xds/grpc/xds_http_composite_filter.h +4 -3
- data/src/core/xds/grpc/xds_http_ext_proc_filter.cc +418 -0
- data/src/core/xds/grpc/xds_http_ext_proc_filter.h +89 -0
- data/src/core/xds/grpc/xds_http_fault_filter.cc +9 -12
- data/src/core/xds/grpc/xds_http_fault_filter.h +1 -4
- data/src/core/xds/grpc/xds_http_filter.cc +2 -1
- data/src/core/xds/grpc/xds_http_filter.h +6 -5
- data/src/core/xds/grpc/xds_http_filter_registry.cc +10 -127
- data/src/core/xds/grpc/xds_http_filter_registry.h +7 -59
- data/src/core/xds/grpc/xds_http_gcp_authn_filter.cc +13 -14
- data/src/core/xds/grpc/xds_http_gcp_authn_filter.h +3 -2
- data/src/core/xds/grpc/xds_http_rbac_filter.cc +403 -25
- data/src/core/xds/grpc/xds_http_rbac_filter.h +1 -3
- data/src/core/xds/grpc/xds_http_stateful_session_filter.cc +8 -13
- data/src/core/xds/grpc/xds_http_stateful_session_filter.h +1 -4
- data/src/core/xds/grpc/xds_lb_policy_registry.cc +0 -292
- data/src/core/xds/grpc/xds_lb_policy_registry.h +7 -3
- data/src/core/xds/grpc/xds_listener.cc +2 -0
- data/src/core/xds/grpc/xds_listener.h +5 -0
- data/src/core/xds/grpc/xds_listener_parser.cc +16 -11
- data/src/core/xds/grpc/xds_matcher_parse.h +3 -1
- data/src/core/xds/grpc/xds_metadata_parser.cc +6 -1
- data/src/core/xds/grpc/xds_metadata_parser.h +2 -0
- data/src/core/xds/grpc/xds_route_config.cc +2 -0
- data/src/core/xds/grpc/xds_route_config.h +3 -1
- data/src/core/xds/grpc/xds_route_config_parser.cc +13 -79
- data/src/core/xds/grpc/xds_route_config_parser.h +0 -3
- data/src/core/xds/grpc/xds_routing.cc +116 -69
- data/src/core/xds/grpc/xds_routing.h +19 -8
- data/src/core/xds/grpc/xds_tls_context.cc +117 -0
- data/src/core/xds/grpc/xds_tls_context.h +76 -0
- data/src/core/xds/grpc/xds_tls_context_parser.cc +275 -0
- data/src/core/xds/grpc/xds_tls_context_parser.h +35 -0
- data/src/core/xds/grpc/xds_transport_grpc.cc +41 -38
- data/src/core/xds/grpc/xds_transport_grpc.h +4 -2
- data/src/ruby/ext/grpc/rb_call.c +26 -15
- data/src/ruby/ext/grpc/rb_completion_queue.c +6 -5
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
- data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +3 -0
- data/src/ruby/lib/grpc/version.rb +1 -1
- data/src/ruby/pb/test/client.rb +5 -4
- data/src/ruby/spec/call_spec.rb +14 -0
- data/src/ruby/spec/generic/server_interceptors_spec.rb +3 -6
- metadata +50 -35
- data/src/core/ext/upbdefs-gen/src/proto/grpc/channelz/channelz.upbdefs.c +0 -716
- data/src/core/lib/iomgr/resolve_address.cc +0 -59
- data/src/core/lib/iomgr/resolve_address.h +0 -125
- data/src/core/lib/iomgr/resolve_address_impl.h +0 -58
- data/src/core/lib/iomgr/resolve_address_posix.cc +0 -184
- data/src/core/lib/iomgr/resolve_address_posix.h +0 -78
- data/src/core/lib/iomgr/resolve_address_windows.cc +0 -169
- data/src/core/lib/iomgr/resolve_address_windows.h +0 -76
- data/src/core/resolver/dns/c_ares/dns_resolver_ares.cc +0 -781
- data/src/core/resolver/dns/c_ares/grpc_ares_ev_driver.h +0 -93
- data/src/core/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +0 -203
- data/src/core/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +0 -838
- data/src/core/resolver/dns/c_ares/grpc_ares_wrapper.cc +0 -1237
- data/src/core/resolver/dns/c_ares/grpc_ares_wrapper.h +0 -130
- data/src/core/resolver/dns/c_ares/grpc_ares_wrapper_windows.cc +0 -35
- data/src/core/resolver/dns/dns_resolver_plugin.cc +0 -64
- data/src/core/resolver/dns/native/dns_resolver.cc +0 -173
- data/src/core/util/json/json_util.cc +0 -101
- data/src/core/util/json/json_util.h +0 -163
|
@@ -0,0 +1,525 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 gRPC authors.
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
//
|
|
16
|
+
|
|
17
|
+
#include "src/core/credentials/call/gdch_service_account/gdch_service_account_credentials.h"
|
|
18
|
+
|
|
19
|
+
#include <grpc/credentials.h>
|
|
20
|
+
#include <grpc/support/alloc.h>
|
|
21
|
+
#include <grpc/support/string_util.h>
|
|
22
|
+
#include <openssl/bio.h>
|
|
23
|
+
#include <openssl/bn.h>
|
|
24
|
+
#include <openssl/crypto.h>
|
|
25
|
+
#include <openssl/ecdsa.h>
|
|
26
|
+
#include <openssl/err.h>
|
|
27
|
+
#include <openssl/evp.h>
|
|
28
|
+
#include <openssl/pem.h>
|
|
29
|
+
|
|
30
|
+
#include <array>
|
|
31
|
+
#include <memory>
|
|
32
|
+
#include <optional>
|
|
33
|
+
#include <string>
|
|
34
|
+
#include <utility>
|
|
35
|
+
|
|
36
|
+
#include "src/core/credentials/transport/transport_credentials.h"
|
|
37
|
+
#include "src/core/lib/iomgr/closure.h"
|
|
38
|
+
#include "src/core/lib/iomgr/exec_ctx.h"
|
|
39
|
+
#include "src/core/lib/slice/slice.h"
|
|
40
|
+
#include "src/core/util/http_client/httpcli.h"
|
|
41
|
+
#include "src/core/util/http_client/httpcli_ssl_credentials.h"
|
|
42
|
+
#include "src/core/util/http_client/parser.h"
|
|
43
|
+
#include "src/core/util/json/json.h"
|
|
44
|
+
#include "src/core/util/json/json_object_loader.h"
|
|
45
|
+
#include "src/core/util/json/json_reader.h"
|
|
46
|
+
#include "src/core/util/json/json_writer.h"
|
|
47
|
+
#include "src/core/util/ref_counted_ptr.h"
|
|
48
|
+
#include "src/core/util/status_helper.h"
|
|
49
|
+
#include "src/core/util/time.h"
|
|
50
|
+
#include "src/core/util/unique_type_name.h"
|
|
51
|
+
#include "src/core/util/uri.h"
|
|
52
|
+
#include "src/core/util/validation_errors.h"
|
|
53
|
+
#include "absl/log/log.h"
|
|
54
|
+
#include "absl/status/status.h"
|
|
55
|
+
#include "absl/status/statusor.h"
|
|
56
|
+
#include "absl/strings/escaping.h"
|
|
57
|
+
#include "absl/strings/str_cat.h"
|
|
58
|
+
#include "absl/strings/str_format.h"
|
|
59
|
+
#include "absl/strings/string_view.h"
|
|
60
|
+
|
|
61
|
+
namespace grpc_core {
|
|
62
|
+
namespace {
|
|
63
|
+
|
|
64
|
+
constexpr const char* kExpectedType = "gdch_service_account";
|
|
65
|
+
constexpr const char* kExpectedFormatVersion = "1";
|
|
66
|
+
constexpr Duration kTokenLifetime = Duration::Hours(1);
|
|
67
|
+
|
|
68
|
+
struct OpenSslDeleter {
|
|
69
|
+
void operator()(EVP_MD_CTX* ptr) {
|
|
70
|
+
// The name of the function to free an EVP_MD_CTX changed in OpenSSL 1.1.0.
|
|
71
|
+
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) // Older than version 1.1.0.
|
|
72
|
+
EVP_MD_CTX_destroy(ptr);
|
|
73
|
+
#else
|
|
74
|
+
EVP_MD_CTX_free(ptr);
|
|
75
|
+
#endif
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
void operator()(EVP_PKEY* ptr) { EVP_PKEY_free(ptr); }
|
|
79
|
+
void operator()(BIO* ptr) { BIO_free(ptr); }
|
|
80
|
+
void operator()(ECDSA_SIG* ptr) { ECDSA_SIG_free(ptr); }
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
std::unique_ptr<EVP_MD_CTX, OpenSslDeleter> GetDigestCtx() {
|
|
84
|
+
// The name of the function to create an EVP_MD_CTX changed in OpenSSL 1.1.0.
|
|
85
|
+
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) // Older than version 1.1.0.
|
|
86
|
+
return std::unique_ptr<EVP_MD_CTX, OpenSslDeleter>(EVP_MD_CTX_create());
|
|
87
|
+
#else
|
|
88
|
+
return std::unique_ptr<EVP_MD_CTX, OpenSslDeleter>(EVP_MD_CTX_new());
|
|
89
|
+
#endif
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
std::string CaptureSslErrors() {
|
|
93
|
+
std::string msg;
|
|
94
|
+
bool is_first = true;
|
|
95
|
+
while (unsigned long code = ERR_get_error()) {
|
|
96
|
+
// OpenSSL guarantees that 256 bytes is enough:
|
|
97
|
+
// https://www.openssl.org/docs/man1.1.1/man3/ERR_error_string_n.html
|
|
98
|
+
// https://www.openssl.org/docs/man1.0.2/man3/ERR_error_string_n.html
|
|
99
|
+
// we could not find a macro or constant to replace the 256 literal.
|
|
100
|
+
constexpr size_t kMaxOpenSslErrorLength = 256;
|
|
101
|
+
std::array<char, kMaxOpenSslErrorLength> buf{};
|
|
102
|
+
ERR_error_string_n(code, buf.data(), buf.size());
|
|
103
|
+
if (!is_first) StrAppend(msg, ", ");
|
|
104
|
+
StrAppend(msg, buf.data());
|
|
105
|
+
is_first = false;
|
|
106
|
+
}
|
|
107
|
+
return msg;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
|
111
|
+
void ECDSA_SIG_get0(const ECDSA_SIG* sig, const BIGNUM** pr,
|
|
112
|
+
const BIGNUM** ps) {
|
|
113
|
+
if (pr != nullptr) *pr = sig->r;
|
|
114
|
+
if (ps != nullptr) *ps = sig->s;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
int BN_bn2binpad(const BIGNUM* a, unsigned char* to, int len) {
|
|
118
|
+
int n = BN_num_bytes(a);
|
|
119
|
+
if (n > len) {
|
|
120
|
+
return -1; // Buffer too small
|
|
121
|
+
}
|
|
122
|
+
// Zero out the padding area
|
|
123
|
+
memset(to, 0, len - n);
|
|
124
|
+
// Write the number at the end of the buffer
|
|
125
|
+
BN_bn2bin(a, to + (len - n));
|
|
126
|
+
return len;
|
|
127
|
+
}
|
|
128
|
+
#endif
|
|
129
|
+
|
|
130
|
+
absl::StatusOr<std::string> DERToRawSignature(absl::string_view der_sig,
|
|
131
|
+
int coord_size) {
|
|
132
|
+
if (der_sig.empty()) {
|
|
133
|
+
return absl::InternalError("Input DER signature is empty");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const unsigned char* der_sig_ptr =
|
|
137
|
+
reinterpret_cast<const unsigned char*>(der_sig.data());
|
|
138
|
+
std::unique_ptr<ECDSA_SIG, OpenSslDeleter> ecdsa_sig(
|
|
139
|
+
d2i_ECDSA_SIG(nullptr, &der_sig_ptr, der_sig.size()));
|
|
140
|
+
|
|
141
|
+
if (ecdsa_sig == nullptr) {
|
|
142
|
+
char err_buf[256];
|
|
143
|
+
ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf));
|
|
144
|
+
return absl::InternalError(
|
|
145
|
+
absl::StrCat("Error parsing DER signature: ", err_buf));
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const BIGNUM* r;
|
|
149
|
+
const BIGNUM* s;
|
|
150
|
+
ECDSA_SIG_get0(ecdsa_sig.get(), &r, &s);
|
|
151
|
+
|
|
152
|
+
if (r == nullptr || s == nullptr) {
|
|
153
|
+
return absl::InternalError("Error: Could not get r or s from ECDSA_SIG");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
std::string raw_sig(2 * coord_size, '\0');
|
|
157
|
+
unsigned char* raw_sig_ptr = reinterpret_cast<unsigned char*>(raw_sig.data());
|
|
158
|
+
|
|
159
|
+
constexpr const char* kErrorMessage =
|
|
160
|
+
R"""(Error converting %s to binary (expected %d bytes, got %d): %s)""";
|
|
161
|
+
// Convert r to binary, padded to coord_size.
|
|
162
|
+
int r_len = BN_bn2binpad(r, &raw_sig_ptr[0], coord_size);
|
|
163
|
+
if (r_len != coord_size) {
|
|
164
|
+
char err_buf[256];
|
|
165
|
+
ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf));
|
|
166
|
+
std::string err_msg =
|
|
167
|
+
absl::StrFormat(kErrorMessage, "r", coord_size, r_len, err_buf);
|
|
168
|
+
return absl::InternalError(err_msg);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Convert s to binary, padded to coord_size.
|
|
172
|
+
int s_len = BN_bn2binpad(s, &raw_sig_ptr[coord_size], coord_size);
|
|
173
|
+
if (s_len != coord_size) {
|
|
174
|
+
char err_buf[256];
|
|
175
|
+
ERR_error_string_n(ERR_get_error(), err_buf, sizeof(err_buf));
|
|
176
|
+
std::string err_msg =
|
|
177
|
+
absl::StrFormat(kErrorMessage, "s", coord_size, s_len, err_buf);
|
|
178
|
+
return absl::InternalError(err_msg);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return raw_sig;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
struct Response {
|
|
185
|
+
static const JsonLoaderInterface* JsonLoader(const JsonArgs&) {
|
|
186
|
+
static const auto* loader =
|
|
187
|
+
JsonObjectLoader<Response>()
|
|
188
|
+
.Field("access_token", &Response::access_token)
|
|
189
|
+
.Finish();
|
|
190
|
+
return loader;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
std::string access_token;
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
struct Info {
|
|
197
|
+
static const JsonLoaderInterface* JsonLoader(const JsonArgs&) {
|
|
198
|
+
static const auto* loader =
|
|
199
|
+
JsonObjectLoader<Info>()
|
|
200
|
+
.Field("type", &Info::type)
|
|
201
|
+
.Field("format_version", &Info::format_version)
|
|
202
|
+
.Field("project", &Info::project_id)
|
|
203
|
+
.Field("private_key_id", &Info::private_key_id)
|
|
204
|
+
.Field("private_key", &Info::private_key)
|
|
205
|
+
.Field("name", &Info::service_identity_name)
|
|
206
|
+
.OptionalField("ca_cert_path", &Info::ca_cert_path)
|
|
207
|
+
.Field("token_uri", &Info::token_uri)
|
|
208
|
+
.Finish();
|
|
209
|
+
return loader;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
void JsonPostLoad(const Json&, const JsonArgs&, ValidationErrors* errors);
|
|
213
|
+
|
|
214
|
+
std::string type;
|
|
215
|
+
std::string format_version;
|
|
216
|
+
std::string project_id;
|
|
217
|
+
std::string private_key_id;
|
|
218
|
+
std::string private_key;
|
|
219
|
+
std::string service_identity_name;
|
|
220
|
+
std::optional<std::string> ca_cert_path;
|
|
221
|
+
std::string token_uri;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
void Info::JsonPostLoad(const Json& json, const JsonArgs& /*args*/,
|
|
225
|
+
ValidationErrors* errors) {
|
|
226
|
+
auto check_non_empty = [&](absl::string_view field_name,
|
|
227
|
+
absl::string_view field_value) {
|
|
228
|
+
ValidationErrors::ScopedField field(errors, absl::StrCat(".", field_name));
|
|
229
|
+
if (!errors->FieldHasErrors() && field_value.empty()) {
|
|
230
|
+
errors->AddError("field must not be empty");
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
auto check_expected_value = [&](absl::string_view field_name,
|
|
235
|
+
absl::string_view field_value,
|
|
236
|
+
absl::string_view expected_value) {
|
|
237
|
+
ValidationErrors::ScopedField field(errors, absl::StrCat(".", field_name));
|
|
238
|
+
if (!errors->FieldHasErrors() && field_value != expected_value) {
|
|
239
|
+
errors->AddError(absl::StrCat("field must be ", expected_value));
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
check_expected_value("type", type, kExpectedType);
|
|
244
|
+
check_expected_value("format_version", format_version,
|
|
245
|
+
kExpectedFormatVersion);
|
|
246
|
+
check_non_empty("project", project_id);
|
|
247
|
+
check_non_empty("private_key_id", private_key_id);
|
|
248
|
+
check_non_empty("private_key", private_key);
|
|
249
|
+
check_non_empty("name", service_identity_name);
|
|
250
|
+
check_non_empty("token_uri", token_uri);
|
|
251
|
+
|
|
252
|
+
if (ca_cert_path.has_value()) {
|
|
253
|
+
check_non_empty("ca_cert_path", *ca_cert_path);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
} // namespace
|
|
258
|
+
|
|
259
|
+
absl::StatusOr<std::string> GDCHServiceAccountCredentials::SignUsingSha256(
|
|
260
|
+
absl::string_view str, absl::string_view pem_contents,
|
|
261
|
+
SignatureFormat format) {
|
|
262
|
+
ERR_clear_error();
|
|
263
|
+
std::unique_ptr<BIO, OpenSslDeleter> pem_buffer(BIO_new_mem_buf(
|
|
264
|
+
pem_contents.data(), static_cast<int>(pem_contents.length())));
|
|
265
|
+
if (pem_buffer == nullptr) {
|
|
266
|
+
return absl::InternalError(absl::StrCat(
|
|
267
|
+
"Invalid ServiceAccountCredentials could not create PEM buffer: ",
|
|
268
|
+
CaptureSslErrors()));
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
std::unique_ptr<EVP_PKEY, OpenSslDeleter> private_key(PEM_read_bio_PrivateKey(
|
|
272
|
+
pem_buffer.get(),
|
|
273
|
+
nullptr, // EVP_PKEY **x
|
|
274
|
+
nullptr, // pem_password_cb *cb -- a custom callback.
|
|
275
|
+
// void *u -- this represents the password for the PEM (only
|
|
276
|
+
// applicable for formats such as PKCS12 (.p12 files) that use
|
|
277
|
+
// a password, which we don't currently support.
|
|
278
|
+
nullptr));
|
|
279
|
+
if (private_key == nullptr) {
|
|
280
|
+
return absl::InternalError(
|
|
281
|
+
absl::StrCat("Invalid ServiceAccountCredentials could not parse PEM to "
|
|
282
|
+
"get private key: ",
|
|
283
|
+
CaptureSslErrors()));
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
std::unique_ptr<EVP_MD_CTX, OpenSslDeleter> digest_ctx = GetDigestCtx();
|
|
287
|
+
if (digest_ctx == nullptr) {
|
|
288
|
+
return absl::InternalError(
|
|
289
|
+
absl::StrCat("Invalid ServiceAccountCredentials could not create "
|
|
290
|
+
"context for OpenSSL digest: ",
|
|
291
|
+
CaptureSslErrors()));
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
constexpr int kOpenSslSuccess = 1;
|
|
295
|
+
if (EVP_DigestSignInit(digest_ctx.get(), nullptr, EVP_sha256(), nullptr,
|
|
296
|
+
private_key.get()) != kOpenSslSuccess) {
|
|
297
|
+
return absl::InternalError(
|
|
298
|
+
absl::StrCat("Invalid ServiceAccountCredentials - could not initialize "
|
|
299
|
+
"signing digest: ",
|
|
300
|
+
CaptureSslErrors()));
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (EVP_DigestSignUpdate(digest_ctx.get(), str.data(), str.size()) !=
|
|
304
|
+
kOpenSslSuccess) {
|
|
305
|
+
return absl::InternalError(absl::StrCat(
|
|
306
|
+
"Invalid ServiceAccountCredentials - could not sign blob: ",
|
|
307
|
+
CaptureSslErrors()));
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// The signed SHA256 size depends on the size (the experts say "modulus") of
|
|
311
|
+
// they key. First query the size:
|
|
312
|
+
std::size_t actual_len = 0;
|
|
313
|
+
if (EVP_DigestSignFinal(digest_ctx.get(), nullptr, &actual_len) !=
|
|
314
|
+
kOpenSslSuccess) {
|
|
315
|
+
return absl::InternalError(absl::StrCat(
|
|
316
|
+
"Invalid ServiceAccountCredentials - could not sign blob: ",
|
|
317
|
+
CaptureSslErrors()));
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// Then compute the actual signed digest. Note that OpenSSL requires a
|
|
321
|
+
// `unsigned char*` buffer, so we feed it that.
|
|
322
|
+
std::string buffer(actual_len, '\0');
|
|
323
|
+
if (EVP_DigestSignFinal(digest_ctx.get(),
|
|
324
|
+
reinterpret_cast<unsigned char*>(buffer.data()),
|
|
325
|
+
&actual_len) != kOpenSslSuccess) {
|
|
326
|
+
return absl::InternalError(absl::StrCat(
|
|
327
|
+
"Invalid ServiceAccountCredentials - could not sign blob: ",
|
|
328
|
+
CaptureSslErrors()));
|
|
329
|
+
}
|
|
330
|
+
buffer.resize(actual_len);
|
|
331
|
+
|
|
332
|
+
if (format == SignatureFormat::kDER) {
|
|
333
|
+
return buffer;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return DERToRawSignature(buffer, 32);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
absl::StatusOr<RefCountedPtr<GDCHServiceAccountCredentials>>
|
|
340
|
+
GDCHServiceAccountCredentials::Create(absl::string_view key_file_contents,
|
|
341
|
+
std::string audience) {
|
|
342
|
+
absl::StatusOr<Json> json = JsonParse(key_file_contents);
|
|
343
|
+
if (!json.ok()) return json.status();
|
|
344
|
+
absl::StatusOr<Info> info = LoadFromJson<Info>(*json);
|
|
345
|
+
if (!info.ok()) return info.status();
|
|
346
|
+
absl::StatusOr<URI> token_url = URI::Parse(info->token_uri);
|
|
347
|
+
if (!token_url.ok()) return token_url.status();
|
|
348
|
+
std::string service_account_identity =
|
|
349
|
+
absl::StrCat("system:serviceaccount:", info->project_id, ":",
|
|
350
|
+
info->service_identity_name);
|
|
351
|
+
return MakeRefCounted<GDCHServiceAccountCredentials>(
|
|
352
|
+
std::move(info->private_key_id), std::move(info->private_key),
|
|
353
|
+
std::move(service_account_identity), std::move(info->ca_cert_path),
|
|
354
|
+
*std::move(token_url), std::move(audience));
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
GDCHServiceAccountCredentials::GDCHServiceAccountCredentials(
|
|
358
|
+
std::string private_key_id, std::string private_key,
|
|
359
|
+
std::string service_account_identity,
|
|
360
|
+
std::optional<std::string> ca_cert_path, URI token_url,
|
|
361
|
+
std::string audience)
|
|
362
|
+
: private_key_id_(std::move(private_key_id)),
|
|
363
|
+
private_key_(std::move(private_key)),
|
|
364
|
+
service_account_identity_(std::move(service_account_identity)),
|
|
365
|
+
ca_cert_path_(std::move(ca_cert_path)),
|
|
366
|
+
token_url_(std::move(token_url)),
|
|
367
|
+
audience_(std::move(audience)) {}
|
|
368
|
+
|
|
369
|
+
GDCHServiceAccountCredentials::AssertionComponents
|
|
370
|
+
GDCHServiceAccountCredentials::CreateAssertionComponents(Timestamp now) const {
|
|
371
|
+
Json header = Json::FromObject({
|
|
372
|
+
{"alg", Json::FromString("ES256")},
|
|
373
|
+
{"typ", Json::FromString("JWT")},
|
|
374
|
+
{"kid", Json::FromString(private_key_id_)},
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
Timestamp expiration = now + kTokenLifetime;
|
|
378
|
+
|
|
379
|
+
const int64_t now_from_epoch = now.as_timespec(GPR_CLOCK_REALTIME).tv_sec;
|
|
380
|
+
const int64_t expiration_from_epoch =
|
|
381
|
+
expiration.as_timespec(GPR_CLOCK_REALTIME).tv_sec;
|
|
382
|
+
|
|
383
|
+
Json claim = Json::FromObject({
|
|
384
|
+
{"iss", Json::FromString(service_account_identity_)},
|
|
385
|
+
{"sub", Json::FromString(service_account_identity_)},
|
|
386
|
+
{"aud", Json::FromString(token_url_.ToString())},
|
|
387
|
+
{"iat", Json::FromNumber(now_from_epoch)},
|
|
388
|
+
{"exp", Json::FromNumber(expiration_from_epoch)},
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
return {JsonDump(header), JsonDump(claim)};
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
absl::StatusOr<std::string> GDCHServiceAccountCredentials::MakeJWTAssertion(
|
|
395
|
+
absl::string_view header, absl::string_view claim,
|
|
396
|
+
absl::string_view pem_contents, SignatureFormat format) {
|
|
397
|
+
const std::string body = absl::StrCat(absl::WebSafeBase64Escape(header), ".",
|
|
398
|
+
absl::WebSafeBase64Escape(claim));
|
|
399
|
+
absl::StatusOr<std::string> signature =
|
|
400
|
+
SignUsingSha256(body, pem_contents, format);
|
|
401
|
+
if (!signature.ok()) return signature.status();
|
|
402
|
+
return absl::StrCat(body, ".", absl::WebSafeBase64Escape(*signature));
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
absl::StatusOr<std::string> GDCHServiceAccountCredentials::CreateRequestBody()
|
|
406
|
+
const {
|
|
407
|
+
AssertionComponents components = CreateAssertionComponents(Timestamp::Now());
|
|
408
|
+
absl::StatusOr<std::string> jwt = MakeJWTAssertion(
|
|
409
|
+
components.header, components.claim, private_key_, SignatureFormat::kRaw);
|
|
410
|
+
if (!jwt.ok()) return jwt.status();
|
|
411
|
+
|
|
412
|
+
Json payload = Json::FromObject({
|
|
413
|
+
{"grant_type",
|
|
414
|
+
Json::FromString("urn:ietf:params:oauth:token-type:token-exchange")},
|
|
415
|
+
{"audience", Json::FromString(audience_)},
|
|
416
|
+
{"requested_token_type",
|
|
417
|
+
Json::FromString("urn:ietf:params:oauth:token-type:access_token")},
|
|
418
|
+
{"subject_token", Json::FromString(std::move(*jwt))},
|
|
419
|
+
{"subject_token_type",
|
|
420
|
+
Json::FromString("urn:k8s:params:oauth:token-type:serviceaccount")},
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
return JsonDump(payload);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
void GDCHServiceAccountCredentials::GrpcDeleter::operator()(
|
|
427
|
+
grpc_http_request* ptr) {
|
|
428
|
+
grpc_http_request_destroy(ptr);
|
|
429
|
+
delete ptr;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
absl::StatusOr<GDCHServiceAccountCredentials::GrpcHttpRequestUniquePtr>
|
|
433
|
+
GDCHServiceAccountCredentials::FormatHttpRequest() const {
|
|
434
|
+
absl::StatusOr<std::string> body = CreateRequestBody();
|
|
435
|
+
if (!body.ok()) return body.status();
|
|
436
|
+
|
|
437
|
+
GrpcHttpRequestUniquePtr request(new grpc_http_request);
|
|
438
|
+
memset(request.get(), 0, sizeof(grpc_http_request));
|
|
439
|
+
request->path =
|
|
440
|
+
gpr_strdup(token_url_.path().empty() ? "/" : token_url_.path().c_str());
|
|
441
|
+
request->hdr_count = 1;
|
|
442
|
+
request->hdrs =
|
|
443
|
+
static_cast<grpc_http_header*>(gpr_malloc(sizeof(grpc_http_header)));
|
|
444
|
+
request->hdrs[0].key = gpr_strdup("content-type");
|
|
445
|
+
request->hdrs[0].value = gpr_strdup("application/json");
|
|
446
|
+
|
|
447
|
+
request->body_length = static_cast<int>(body->size());
|
|
448
|
+
request->body = gpr_strdup(body->c_str());
|
|
449
|
+
return request;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
absl::StatusOr<std::string> GDCHServiceAccountCredentials::ParseHttpResponse(
|
|
453
|
+
absl::string_view response_body) {
|
|
454
|
+
absl::StatusOr<Json> response_json = JsonParse(response_body);
|
|
455
|
+
if (!response_json.ok()) {
|
|
456
|
+
return absl::InternalError(
|
|
457
|
+
"The format of response is not a valid json object.");
|
|
458
|
+
}
|
|
459
|
+
auto response = LoadFromJson<Response>(*response_json);
|
|
460
|
+
if (!response.ok()) return response.status();
|
|
461
|
+
return std::move(response->access_token);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
UniqueTypeName GDCHServiceAccountCredentials::type() const {
|
|
465
|
+
return GRPC_UNIQUE_TYPE_NAME_HERE("GDCHServiceAccountCredentials");
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
std::string GDCHServiceAccountCredentials::debug_string() {
|
|
469
|
+
return absl::StrCat("GDCHServiceAccountCredentials{Audience:", audience_,
|
|
470
|
+
"}");
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
OrphanablePtr<HttpRequest> GDCHServiceAccountCredentials::StartHttpRequest(
|
|
474
|
+
grpc_polling_entity* pollent, Timestamp deadline,
|
|
475
|
+
grpc_http_response* response, grpc_closure* on_complete) {
|
|
476
|
+
absl::StatusOr<GrpcHttpRequestUniquePtr> request = FormatHttpRequest();
|
|
477
|
+
if (!request.ok()) {
|
|
478
|
+
ExecCtx::Run(DEBUG_LOCATION, on_complete, request.status());
|
|
479
|
+
return nullptr;
|
|
480
|
+
}
|
|
481
|
+
RefCountedPtr<grpc_channel_credentials> http_request_creds;
|
|
482
|
+
if (token_url_.scheme() == "http") {
|
|
483
|
+
http_request_creds = RefCountedPtr<grpc_channel_credentials>(
|
|
484
|
+
grpc_insecure_credentials_create());
|
|
485
|
+
} else {
|
|
486
|
+
http_request_creds = CreateHttpRequestSSLCredentials();
|
|
487
|
+
}
|
|
488
|
+
OrphanablePtr<HttpRequest> http_request = HttpRequest::Post(
|
|
489
|
+
token_url_, /*args=*/nullptr, pollent, request->get(), deadline,
|
|
490
|
+
on_complete, response, std::move(http_request_creds));
|
|
491
|
+
http_request->Start();
|
|
492
|
+
return http_request;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
absl::StatusOr<RefCountedPtr<TokenFetcherCredentials::Token>>
|
|
496
|
+
GDCHServiceAccountCredentials::ExtractToken(
|
|
497
|
+
const grpc_http_response& response) {
|
|
498
|
+
absl::string_view response_body(response.body, response.body_length);
|
|
499
|
+
absl::StatusOr<std::string> token_str = ParseHttpResponse(response_body);
|
|
500
|
+
if (!token_str.ok()) return token_str.status();
|
|
501
|
+
return MakeRefCounted<Token>(
|
|
502
|
+
Slice::FromCopiedString(absl::StrCat("Bearer ", *token_str)),
|
|
503
|
+
Timestamp::Now() + kTokenLifetime);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
} // namespace grpc_core
|
|
507
|
+
|
|
508
|
+
grpc_call_credentials* grpc_gdch_service_account_credentials_create(
|
|
509
|
+
const char* json_string, const char* audience_string) {
|
|
510
|
+
if (json_string == nullptr || audience_string == nullptr) {
|
|
511
|
+
LOG(ERROR) << "GDCH service account credentials creation failed: "
|
|
512
|
+
<< "json_string or audience_string is null.";
|
|
513
|
+
return nullptr;
|
|
514
|
+
}
|
|
515
|
+
absl::StatusOr<
|
|
516
|
+
grpc_core::RefCountedPtr<grpc_core::GDCHServiceAccountCredentials>>
|
|
517
|
+
creds = grpc_core::GDCHServiceAccountCredentials::Create(json_string,
|
|
518
|
+
audience_string);
|
|
519
|
+
if (!creds.ok()) {
|
|
520
|
+
LOG(ERROR) << "GDCH service account credentials creation failed. Error: "
|
|
521
|
+
<< grpc_core::StatusToString(creds.status());
|
|
522
|
+
return nullptr;
|
|
523
|
+
}
|
|
524
|
+
return creds->release();
|
|
525
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 gRPC authors.
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
//
|
|
16
|
+
|
|
17
|
+
#ifndef GRPC_SRC_CORE_CREDENTIALS_CALL_GDCH_SERVICE_ACCOUNT_GDCH_SERVICE_ACCOUNT_CREDENTIALS_H
|
|
18
|
+
#define GRPC_SRC_CORE_CREDENTIALS_CALL_GDCH_SERVICE_ACCOUNT_GDCH_SERVICE_ACCOUNT_CREDENTIALS_H
|
|
19
|
+
|
|
20
|
+
#include <memory>
|
|
21
|
+
#include <optional>
|
|
22
|
+
#include <string>
|
|
23
|
+
|
|
24
|
+
#include "src/core/credentials/call/token_fetcher/token_fetcher_credentials.h"
|
|
25
|
+
#include "src/core/util/http_client/httpcli.h"
|
|
26
|
+
#include "src/core/util/orphanable.h"
|
|
27
|
+
#include "src/core/util/ref_counted_ptr.h"
|
|
28
|
+
#include "src/core/util/time.h"
|
|
29
|
+
#include "src/core/util/unique_type_name.h"
|
|
30
|
+
#include "src/core/util/uri.h"
|
|
31
|
+
#include "absl/status/statusor.h"
|
|
32
|
+
#include "absl/strings/string_view.h"
|
|
33
|
+
|
|
34
|
+
namespace grpc_core {
|
|
35
|
+
|
|
36
|
+
// GDCH Service Account credentials.
|
|
37
|
+
//
|
|
38
|
+
// Uses the service account to create a JWT assertion which is then exchanged
|
|
39
|
+
// for a STS bearer token.
|
|
40
|
+
//
|
|
41
|
+
// JSON Schema for the service account key file:
|
|
42
|
+
// {
|
|
43
|
+
// "type": "object",
|
|
44
|
+
// "properties": {
|
|
45
|
+
// "type": { "type": "string", "const": "gdch_service_account" },
|
|
46
|
+
// "format_version": { "type": "string", "const": "1" },
|
|
47
|
+
// "project": { "type": "string" },
|
|
48
|
+
// "private_key_id": { "type": "string" },
|
|
49
|
+
// "private_key": { "type": "string" },
|
|
50
|
+
// "name": { "type": "string" },
|
|
51
|
+
// "ca_cert_path": { "type": "string" },
|
|
52
|
+
// "token_uri": { "type": "string" }
|
|
53
|
+
// },
|
|
54
|
+
// "required": [
|
|
55
|
+
// "type",
|
|
56
|
+
// "format_version",
|
|
57
|
+
// "project",
|
|
58
|
+
// "private_key_id",
|
|
59
|
+
// "private_key",
|
|
60
|
+
// "name",
|
|
61
|
+
// "token_uri"
|
|
62
|
+
// ]
|
|
63
|
+
// }
|
|
64
|
+
class GDCHServiceAccountCredentials final : public HttpTokenFetcherCredentials {
|
|
65
|
+
public:
|
|
66
|
+
static absl::StatusOr<RefCountedPtr<GDCHServiceAccountCredentials>> Create(
|
|
67
|
+
absl::string_view key_file_contents, std::string audience);
|
|
68
|
+
|
|
69
|
+
GDCHServiceAccountCredentials(std::string private_key_id,
|
|
70
|
+
std::string private_key,
|
|
71
|
+
std::string service_account_identity,
|
|
72
|
+
std::optional<std::string> ca_cert_path,
|
|
73
|
+
URI token_url, std::string audience);
|
|
74
|
+
|
|
75
|
+
const std::optional<std::string>& ca_cert_path() const {
|
|
76
|
+
return ca_cert_path_;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
std::string debug_string() override;
|
|
80
|
+
|
|
81
|
+
UniqueTypeName type() const override;
|
|
82
|
+
|
|
83
|
+
OrphanablePtr<HttpRequest> StartHttpRequest(
|
|
84
|
+
grpc_polling_entity* pollent, Timestamp deadline,
|
|
85
|
+
grpc_http_response* response, grpc_closure* on_complete) override;
|
|
86
|
+
|
|
87
|
+
absl::StatusOr<RefCountedPtr<Token>> ExtractToken(
|
|
88
|
+
const grpc_http_response& response) override;
|
|
89
|
+
|
|
90
|
+
private:
|
|
91
|
+
friend class GDCHServiceAccountCredentialsTest;
|
|
92
|
+
|
|
93
|
+
// OpenSSL outputs DER format signatures by default. RFC-7515 (JWT/JWS)
|
|
94
|
+
// specifies the Raw format should be used.
|
|
95
|
+
enum class SignatureFormat { kDER, kRaw };
|
|
96
|
+
|
|
97
|
+
struct AssertionComponents {
|
|
98
|
+
std::string header;
|
|
99
|
+
std::string claim;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
struct GrpcDeleter {
|
|
103
|
+
void operator()(grpc_http_request* ptr);
|
|
104
|
+
};
|
|
105
|
+
using GrpcHttpRequestUniquePtr =
|
|
106
|
+
std::unique_ptr<grpc_http_request, GrpcDeleter>;
|
|
107
|
+
|
|
108
|
+
// Signs a string with the private key from a PEM container.
|
|
109
|
+
//
|
|
110
|
+
// @return the signature as an *unencoded* string.
|
|
111
|
+
static absl::StatusOr<std::string> SignUsingSha256(
|
|
112
|
+
absl::string_view str, absl::string_view pem_contents,
|
|
113
|
+
SignatureFormat format);
|
|
114
|
+
|
|
115
|
+
AssertionComponents CreateAssertionComponents(Timestamp now) const;
|
|
116
|
+
|
|
117
|
+
static absl::StatusOr<std::string> MakeJWTAssertion(
|
|
118
|
+
absl::string_view header, absl::string_view claim,
|
|
119
|
+
absl::string_view pem_contents, SignatureFormat format);
|
|
120
|
+
|
|
121
|
+
absl::StatusOr<std::string> CreateRequestBody() const;
|
|
122
|
+
|
|
123
|
+
absl::StatusOr<GrpcHttpRequestUniquePtr> FormatHttpRequest() const;
|
|
124
|
+
|
|
125
|
+
static absl::StatusOr<std::string> ParseHttpResponse(
|
|
126
|
+
absl::string_view response_body);
|
|
127
|
+
|
|
128
|
+
std::string private_key_id_;
|
|
129
|
+
std::string private_key_;
|
|
130
|
+
std::string service_account_identity_;
|
|
131
|
+
std::optional<std::string> ca_cert_path_;
|
|
132
|
+
URI token_url_;
|
|
133
|
+
std::string audience_;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
} // namespace grpc_core
|
|
137
|
+
|
|
138
|
+
#endif // GRPC_SRC_CORE_CREDENTIALS_CALL_GDCH_SERVICE_ACCOUNT_GDCH_SERVICE_ACCOUNT_CREDENTIALS_H
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account"
|
|
30
30
|
#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user"
|
|
31
31
|
#define GRPC_AUTH_JSON_TYPE_EXTERNAL_ACCOUNT "external_account"
|
|
32
|
+
#define GRPC_AUTH_JSON_TYPE_GDCH_SERVICE_ACCOUNT "gdch_service_account"
|
|
32
33
|
|
|
33
34
|
// Gets a child property from a json node.
|
|
34
35
|
const char* grpc_json_get_string_property(const grpc_core::Json& json,
|
|
@@ -244,7 +244,7 @@ char* compute_and_encode_signature(const grpc_auth_json_key* json_key,
|
|
|
244
244
|
const EVP_MD* md = openssl_digest_from_algorithm(signature_algorithm);
|
|
245
245
|
EVP_MD_CTX* md_ctx = nullptr;
|
|
246
246
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
|
247
|
-
EVP_PKEY* key =
|
|
247
|
+
EVP_PKEY* key = nullptr;
|
|
248
248
|
#endif
|
|
249
249
|
size_t sig_len = 0;
|
|
250
250
|
unsigned char* sig = nullptr;
|
|
@@ -256,7 +256,15 @@ char* compute_and_encode_signature(const grpc_auth_json_key* json_key,
|
|
|
256
256
|
goto end;
|
|
257
257
|
}
|
|
258
258
|
#if OPENSSL_VERSION_NUMBER < 0x30000000L
|
|
259
|
-
|
|
259
|
+
key = EVP_PKEY_new();
|
|
260
|
+
if (key == nullptr) {
|
|
261
|
+
LOG(ERROR) << "Could not create EVP_PKEY";
|
|
262
|
+
goto end;
|
|
263
|
+
}
|
|
264
|
+
if (EVP_PKEY_set1_RSA(key, json_key->private_key) == 0) {
|
|
265
|
+
LOG(ERROR) << "Could not set RSA key";
|
|
266
|
+
goto end;
|
|
267
|
+
}
|
|
260
268
|
if (EVP_DigestSignInit(md_ctx, nullptr, md, nullptr, key) != 1) {
|
|
261
269
|
#else
|
|
262
270
|
if (EVP_DigestSignInit(md_ctx, nullptr, md, nullptr, json_key->private_key) !=
|