diff --git a/.github/workflows/MainDistributionPipeline.yml b/.github/workflows/MainDistributionPipeline.yml index 90248c5..a98ddab 100644 --- a/.github/workflows/MainDistributionPipeline.yml +++ b/.github/workflows/MainDistributionPipeline.yml @@ -17,7 +17,7 @@ jobs: uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@v1.5-variegata with: extension_name: aws - duckdb_version: v1.5.3 + duckdb_version: v1.5.4 ci_tools_version: v1.5-variegata exclude_archs: 'wasm_mvp;wasm_eh;wasm_threads;windows_amd64_rtools;windows_amd64_mingw' # Doesn't work anyway: env local file or env access possible @@ -28,7 +28,7 @@ jobs: secrets: inherit with: extension_name: aws - duckdb_version: v1.5.3 + duckdb_version: v1.5.4 ci_tools_version: v1.5-variegata exclude_archs: 'wasm_mvp;wasm_eh;wasm_threads;windows_amd64_rtools;windows_amd64_mingw' # Doesn't work anyway: env local file or env access possible deploy_latest: ${{ startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' }} diff --git a/src/aws_secret.cpp b/src/aws_secret.cpp index c7d3b7a..678de21 100644 --- a/src/aws_secret.cpp +++ b/src/aws_secret.cpp @@ -2,6 +2,7 @@ #include "duckdb/common/case_insensitive_map.hpp" #include "duckdb/common/exception.hpp" +#include "duckdb/main/database.hpp" #include "duckdb/main/extension/extension_loader.hpp" #include @@ -43,6 +44,12 @@ static struct { const string default_ = "exists"; } CreateAwsSecretValidation; +//! Note: this is a partial duplication of duckdb's GetDefaultUserAgent() +//! It needs to be reimplemented since the format is not compatible +static string DuckDBAwsUserAgentAppId() { + return "duckdb/" + string(DuckDB::LibraryVersion()); +} + //! Build a ClientConfiguration with the detected CA file path applied (if any). //! This is required because libcurl is statically linked from a RHEL-based //! manylinux image, so its default CA path is /etc/pki/tls/certs/ca-bundle.crt, @@ -55,6 +62,12 @@ static Aws::Client::ClientConfiguration BuildClientConfigWithCa() { if (!SELECTED_CURL_CERT_PATH.empty()) { cfg.caFile = SELECTED_CURL_CERT_PATH; } + // Identify DuckDB in the User-Agent, unless the user has already configured an app + // id (via AWS_SDK_UA_APP_ID or the sdk_ua_app_id profile key, which the + // ClientConfiguration constructor loads into cfg.appId): their value wins. + if (cfg.appId.empty()) { + cfg.appId = DuckDBAwsUserAgentAppId(); + } return cfg; } @@ -137,12 +150,10 @@ class DuckDBCustomAWSCredentialsProviderChain : public Aws::Auth::AWSCredentials aws_profile.SetExternalId(external_id); AddSTSProvider(aws_profile); } else if (item == "sso") { - // Pass an explicit ClientConfiguration so the SSO portal HTTPS call - // uses the detected CA path. See BuildClientConfigWithCa() comment. - auto sso_config = Aws::MakeShared("DuckDBAwsSSO"); - if (!SELECTED_CURL_CERT_PATH.empty()) { - sso_config->caFile = SELECTED_CURL_CERT_PATH; - } + // Pass an explicit ClientConfiguration so the SSO portal HTTPS call uses + // the detected CA path and the DuckDB app id. See BuildClientConfigWithCa(). + auto sso_config = Aws::MakeShared("DuckDBAwsSSO", + BuildClientConfigWithCa()); if (profile.empty()) { AddProvider(std::make_shared(Aws::String(), sso_config)); } else {