github-actions[bot] commented on code in PR #65433:
URL: https://github.com/apache/doris/pull/65433#discussion_r3613741915


##########
gensrc/proto/cloud.proto:
##########
@@ -274,6 +274,9 @@ enum CredProviderTypePB {
     WEB_IDENTITY = 6;  // STSAssumeRoleWebIdentityCredentialsProvider
     CONTAINER = 7;  // TaskRoleCredentialsProvider
     ANONYMOUS = 8;  // AnonymousAWSCredentialsProvider
+    // GKE Workload Identity. Requests to the GCS XML API are authenticated
+    // with a short-lived OAuth2 token from the GKE metadata server.
+    GCP_WORKLOAD_IDENTITY = 9;

Review Comment:
   [P1] Gate this persisted enum for mixed-version consumers
   
   With the previous proto2 schema, value 9 is an unknown closed-enum value, so 
old BE/recycler binaries see this field as unset. Since a Workload Identity 
vault deliberately has no AK/SK/role, those consumers build the default AWS 
client and never attach OAuth, breaking I/O and recycling during a rolling 
upgrade or rollback. Rollback can also preserve tag 17 in the unknown-field set 
across an old Meta Service's nominal HMAC transition, allowing a later new 
consumer to recover value 9 together with keys. Please gate creation/ALTER 
until all consumers advertise support and define/test downgrade handling for 
the raw unknown field.



##########
cloud/src/meta-service/meta_service_resource.cpp:
##########
@@ -1146,6 +1162,38 @@ static int alter_s3_storage_vault_by_id(InstanceInfoPB& 
instance, std::unique_pt
         return -1;
     }
 
+    if (is_gcp_workload_identity_cred_provider(obj_info)) {

Review Comment:
   [P1] Validate the merged credential state for role ALTERs
   
   This validates only an incoming Workload Identity fragment. If the stored 
vault already uses Workload Identity and the user alters only `s3.role_arn`, FE 
emits the role plus `INSTANCE_PROFILE`, this block is skipped, and the later 
role branch persists those AWS credentials while retaining provider GCP and the 
GCS endpoint. BE/recycler then construct an AWS STS provider for GCS and I/O 
fails; ADD already rejects the same combination. Please validate the complete 
merged `ObjectStoreInfoPB` after every credential transition (or reject roles 
for provider GCP) and add the outgoing-role negative test.



##########
be/src/io/fs/s3_obj_storage_client.cpp:
##########
@@ -121,6 +121,7 @@ ObjectStorageUploadResponse 
S3ObjStorageClient::create_multipart_upload(
     CreateMultipartUploadRequest request;
     request.WithBucket(opts.bucket).WithKey(opts.key);
     request.SetContentType("application/octet-stream");
+    _apply_bearer_token(request);

Review Comment:
   [P1] Attach the bearer token after rate limiting
   
   This captures the bearer token before `s3_put_rate_limit()` may sleep. The 
limiter supports rates as low as 1 TPS and an unbounded concurrent deficit, so 
a cached token with only a few minutes remaining can expire in that queue 
before the SDK sends the request. The same ordering is used by every BE and 
recycler request, including pagination and delete batches. Please 
refresh/replace the header inside each rate-limited callback immediately before 
the SDK call, and cover a queued request whose clock advances past token expiry.



##########
cloud/src/meta-service/meta_service_resource.cpp:
##########
@@ -1496,7 +1544,20 @@ void 
MetaServiceImpl::alter_storage_vault(google::protobuf::RpcController* contr
         }
 
         if (use_credential_provider(obj)) {
-            if (!obj.has_provider() || obj.provider() != 
ObjectStoreInfoPB::S3) {
+            if (is_gcp_workload_identity_cred_provider(obj)) {

Review Comment:
   [P1] Support Workload Identity in built-in vault creation
   
   This new keyless special case is confined to `ADD_S3_VAULT`. The parallel 
initial/built-in paths (`CreateInstanceRequest.vault` and `ADD_BUILT_IN_VAULT`) 
still call `add_vault_into_instance()` and then 
`create_object_info_with_encrypt()`, whose non-role branch requires nonempty 
AK/SK. A canonical GCP Workload Identity vault intentionally has no AK/SK/role, 
so cloud control-plane provisioning deterministically returns 
`INVALID_ARGUMENT` before persistence even though it carries the same 
`StorageVaultPB` and enum. Please share the Workload Identity 
validation/persistence logic with those paths and add coverage for both 
built-in entry points.



##########
cloud/src/meta-service/meta_service_resource.cpp:
##########
@@ -768,6 +769,21 @@ static bool use_credential_provider(const 
ObjectStoreInfoPB& obj) {
     return obj.has_cred_provider_type() || has_non_empty_role_arn(obj);
 }
 
+static bool is_gcp_workload_identity_cred_provider(const ObjectStoreInfoPB& 
obj) {
+    return obj.has_cred_provider_type() &&
+           obj.cred_provider_type() == 
CredProviderTypePB::GCP_WORKLOAD_IDENTITY;
+}
+
+static bool normalize_gcs_xml_endpoint(std::string* endpoint, bool 
allow_legacy_http = false) {
+    trim(*endpoint);
+    if (*endpoint == "storage.googleapis.com" || *endpoint == GCS_XML_ENDPOINT 
||

Review Comment:
   [P2] Canonicalize legacy GCS hostnames case-insensitively
   
   Existing HMAC vaults store the endpoint string unchanged, and a mixed-case 
hostname such as `https://Storage.GoogleApis.Com` is valid because DNS 
hostnames are case-insensitive. The FE's new helper also accepts this form, but 
this Meta Service helper compares the stored value with case-sensitive 
equality, so a credential-only HMAC-to-Workload-Identity ALTER is rejected. 
Please compare/parse the scheme and hostname case-insensitively before 
persisting the canonical endpoint, and cover a mixed-case legacy migration.



##########
fe/fe-core/src/main/java/org/apache/doris/catalog/S3Resource.java:
##########
@@ -94,6 +109,22 @@ protected void setProperties(ImmutableMap<String, String> 
newProperties) throws
         Preconditions.checkState(newProperties != null);
         this.properties = Maps.newHashMap(newProperties);
 
+        boolean useWorkloadIdentity =
+                
S3Properties.isGcpWorkloadIdentityCredentialsProvider(properties);
+        if (useWorkloadIdentity) {
+            if (!storageVault) {

Review Comment:
   [P2] Enforce the storage-vault scope on ALTER RESOURCE
   
   This restriction is applied only by `setProperties()`. 
`ResourceMgr.alterResource()` calls `S3Resource.modifyProperties()`, which can 
persist `s3.credentials_provider_type=gcp_workload_identity` on an ordinary S3 
resource (for example when `s3_validity_check=false`) without checking 
`storageVault`. Regular-resource thrift transport does not even send this mode 
without a role, so the successful ALTER creates a misleading/nonfunctional 
edit-log state. Please share this invariant with the modify path and add a 
negative `ALTER RESOURCE` test.



##########
be/src/cloud/cloud_storage_engine.cpp:
##########
@@ -133,7 +133,12 @@ struct VaultCreateFSVisitor {
                   << " check_fs: " << check_fs;
 
         auto fs = DORIS_TRY(io::S3FileSystem::create(s3_conf, id));
-        if (check_fs && !s3_conf.client_conf.role_arn.empty()) {
+        // Probe connectivity for keyless credential modes (assumed role or
+        // GCP Workload Identity): a misconfigured identity should fail loudly 
at startup
+        // rather than on the first tablet write.
+        if (check_fs &&

Review Comment:
   [P1] Make the Workload Identity probe reachable
   
   `check_fs` can never be true here: `first_sync_storage_vault` is initialized 
to `true`, but `sync_storage_vault()` only enables the check when a 
compare-exchange from `false` to `true` succeeds, and there is no write that 
makes the flag false. FE now skips its Workload Identity ping because this BE 
path is supposed to validate the real metadata identity, so an invalid GKE/GCE 
IAM binding is accepted and only fails on the first tablet I/O. Please make the 
first-sync state transition reachable and cover this path with 
`enable_check_storage_vault=true`.



##########
be/src/util/s3_util.cpp:
##########
@@ -89,6 +90,19 @@ doris::Status is_s3_conf_valid(const S3ClientConf& conf) {
     if (conf.region.empty()) {
         return Status::InvalidArgument<false>("Invalid s3 conf, empty region");
     }
+    if (conf.cred_provider_type == CredProviderType::GcpWorkloadIdentity) {
+        if (conf.provider != io::ObjStorageType::GCP) {
+            return Status::InvalidArgument<false>("GCP workload identity 
requires provider GCP");
+        }
+        if (!is_gcs_xml_endpoint(conf.endpoint)) {

Review Comment:
   [P1] Refresh the endpoint during the credential transition
   
   The supported HMAC-to-Workload-Identity ALTER canonicalizes a legacy 
`storage.googleapis.com` endpoint to `https://storage.googleapis.com`, but a 
running BE refreshes the existing filesystem through 
`ObjClientHolder::reset()`. That method starts with the old `_conf` and copies 
credentials and `cred_provider_type`, but not the new endpoint/provider. The 
validation added here therefore rejects the reset configuration with its stale 
host-only endpoint, and the old HMAC client (including the credentials Meta 
Service just removed) remains installed until restart. Please rebuild from the 
full merged client configuration, or at least propagate every identity-defining 
field, and test the live transition.



##########
fe/fe-core/src/main/java/org/apache/doris/catalog/S3Resource.java:
##########
@@ -94,6 +109,22 @@ protected void setProperties(ImmutableMap<String, String> 
newProperties) throws
         Preconditions.checkState(newProperties != null);
         this.properties = Maps.newHashMap(newProperties);
 
+        boolean useWorkloadIdentity =
+                
S3Properties.isGcpWorkloadIdentityCredentialsProvider(properties);
+        if (useWorkloadIdentity) {
+            if (!storageVault) {
+                throw new DdlException("gcp_workload_identity is only 
supported for storage vaults");
+            }
+            try {
+                String endpoint = 
S3Properties.normalizeGcpWorkloadIdentityEndpoint(

Review Comment:
   [P2] Normalize AWS aliases before endpoint validation
   
   Mode detection intentionally accepts `AWS_CREDENTIALS_PROVIDER_TYPE`, but 
this line reads only `s3.endpoint`; `AWS_ENDPOINT` is not converted until 
`requiredS3PingProperties()` runs later. A storage-vault request using the 
supported provider/endpoint aliases therefore detects Workload Identity and 
immediately rejects a null endpoint. Please run `convertToStdProperties()` 
before this branch (or read both aliases) and add a positive alias-based 
creation test.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to