Skip to content

Identify DuckDB in AWS API User-Agent via ClientConfiguration appId#171

Merged
Tmonster merged 2 commits into
duckdb:v1.5-variegatafrom
carlopi:user_agent_aws
Jul 17, 2026
Merged

Identify DuckDB in AWS API User-Agent via ClientConfiguration appId#171
Tmonster merged 2 commits into
duckdb:v1.5-variegatafrom
carlopi:user_agent_aws

Conversation

@carlopi

@carlopi carlopi commented Jul 16, 2026

Copy link
Copy Markdown
Member

Every AWS API call the extension makes (STS AssumeRole, SSO portal, RDS) previously went out with the bare aws-sdk-cpp default User-Agent, with nothing identifying DuckDB. Stamp ClientConfiguration::appId with "duckdb/DuckDB::LibraryVersion()" in BuildClientConfigWithCa(), and route the SSO client config through the same helper, so the SDK appends " app/duckdb/" to the User-Agent of every client we build.

The token matches DuckDB's own User-Agent product token (duckdb/, GetDefaultUserAgent) that httpfs sends on regular HTTP/S3 calls.

A user-configured app id (AWS_SDK_UA_APP_ID env
var or sdk_ua_app_id profile key, which the ClientConfiguration constructor loads into appId) still wins.

This is a purely programmatic per-client approach: no process-global env mutation, and no custom HttpClientFactory. It covers the clients this extension constructs and hands a config (STS AssumeRole, SSO, RDS). The credential-discovery providers that build their own default-config client internally (IMDS/instance-profile, STS web-identity, the default provider chain) are not covered, as the SDK exposes no per-config app id for them short of the env var or an HTTP-layer interceptor.

Example, before:

aws-sdk-cpp/1.11.702 ua/2.0 md/aws-crt#0.x.x os/Darwin#25.4.0 md/arch#arm64 lang/c++#C++17 md/clang#17.0.0

after:

aws-sdk-cpp/1.11.702 ua/2.0 md/aws-crt#0.x.x os/Darwin#25.4.0 md/arch#arm64 lang/c++#C++17 md/clang#17.0.0 app/duckdb/v1.5.4

(see app/duckdb/v1.5.4 appended)

@carlopi
carlopi requested a review from Tmonster July 16, 2026 08:26

@Tmonster Tmonster left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wondering why we do not user GetDefaultUserAgent()?

Comment thread src/aws_secret.cpp Outdated
Comment thread src/aws_secret.cpp
//! identifies this as an SDK call, so no extension-specific suffix is needed. The SDK
//! appends the app id verbatim. See aws-sdk-cpp ClientConfiguration::ComputeUserAgentString.
static string DuckDBAwsUserAgentAppId() {
return "duckdb/" + string(DuckDB::LibraryVersion());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use GetDefaultUserAgent()? link

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a non-static method on the config, so it would need config to be wired in the callstack. I think that might be appropriate with a rework, but for a bug fix this is I think the proper solution.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I got the question, we can't use DBConfig::UserAgent, see above, and we could use GetDefaultUserAgent but: requires changes duckdb side, and more importantly '(' and ')' are not whitelisted, so depending on details they might become rendered as --, and then we can as well just skip them, and solve this properly.

carlopi added 2 commits July 17, 2026 09:37
Every AWS API call the extension makes (STS AssumeRole, SSO portal, RDS)
previously went out with the bare aws-sdk-cpp default User-Agent, with
nothing identifying DuckDB. Stamp ClientConfiguration::appId with
"duckdb/<DuckDB::LibraryVersion()>" in BuildClientConfigWithCa(), and route
the SSO client config through the same helper, so the SDK appends
" app/duckdb/<version>" to the User-Agent of every client we build.

The token matches DuckDB's own User-Agent product token (duckdb/<version>,
GetDefaultUserAgent) that httpfs sends on regular HTTP/S3 calls.

A user-configured app id (AWS_SDK_UA_APP_ID env
var or sdk_ua_app_id profile key, which the ClientConfiguration constructor
loads into appId) still wins.

This is a purely programmatic per-client approach: no process-global env
mutation, and no custom HttpClientFactory. It covers the clients this
extension constructs and hands a config (STS AssumeRole, SSO, RDS). The
credential-discovery providers that build their own default-config client
internally (IMDS/instance-profile, STS web-identity, the default provider
chain) are not covered, as the SDK exposes no per-config app id for them
short of the env var or an HTTP-layer interceptor.
@carlopi
carlopi requested a review from Tmonster July 17, 2026 07:39
@Tmonster

Copy link
Copy Markdown
Member

Thanks!

@Tmonster
Tmonster merged commit efa54a9 into duckdb:v1.5-variegata Jul 17, 2026
14 checks passed
@carlopi
carlopi deleted the user_agent_aws branch July 17, 2026 10:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants