Skip to content

feat(object-store): mask env vars with empty-string storage options - #8098

Closed
westonpace wants to merge 2 commits into
lance-format:mainfrom
westonpace:feat/snapshot-env-vars-object-store
Closed

feat(object-store): mask env vars with empty-string storage options#8098
westonpace wants to merge 2 commits into
lance-format:mainfrom
westonpace:feat/snapshot-env-vars-object-store

Conversation

@westonpace

@westonpace westonpace commented Jul 30, 2026

Copy link
Copy Markdown
Member

A user had two buckets they needed to access. Each bucket was configured with a different credential mechanism. One bucket was using IRSA (AWS_WEB_IDENTITY_TOKEN_FILE + AWS_ROLE_ARN). The other bucket was using ECS credentials (AWS_CONTAINER_CREDENTIALS_FULL_URI).

When all environment variables were set lance would always choose IRSA (since it is higher precedence).

The user tried manually popping out env vars but:

  1. This was inconvenient
  2. If they restored the environment variables after creating the dataset then they would be re-read in the future once the ECS token expired and it would switch back to IRSA.

This PR makes it possible to mask out environment variables using a storage option set to the empty string. In addition, it creates an environment variable snapshot, so expired tokens do not see a different environment.

Setting a storage option to an empty string now masks the environment
variable of the same name (case-insensitive) from the AWS credential
provider chain.

This lets users with both IRSA (AWS_WEB_IDENTITY_TOKEN_FILE + AWS_ROLE_ARN)
and pod/ECS credentials (AWS_CONTAINER_CREDENTIALS_FULL_URI) set in their
environment selectively suppress the higher-priority IRSA provider for a
specific bucket by passing e.g. `{"AWS_WEB_IDENTITY_TOKEN_FILE": ""}` in
storage_options.

Implementation:
- StorageOptions::masked_env_vars() returns the uppercase env var names
  whose keys have empty-string values in storage options
- StorageOptions::as_s3_options() filters out empty-string entries so
  masks are not forwarded as actual S3 config values
- build_credentials_chain_with_masks() builds a CredentialsProviderChain
  that mirrors DefaultCredentialsChain order but skips providers whose
  required env vars are masked
- build_aws_credential() accepts a masked_env_vars parameter and uses
  the custom chain when any masking is in effect

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions github-actions Bot added A-encoding Encoding, IO, file reader/writer enhancement New feature or request labels Jul 30, 2026
@westonpace
westonpace marked this pull request as ready for review July 30, 2026 15:43
@westonpace
westonpace marked this pull request as draft July 30, 2026 15:48
@codecov

codecov Bot commented Jul 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 55.40541% with 33 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
rust/lance-io/src/object_store/providers/aws.rs 49.23% 33 Missing ⚠️

📢 Thoughts on this report? Let us know!

@westonpace

Copy link
Copy Markdown
Member Author

Closing in favor of #8103 which does not reinvent the AWS credential chain

@westonpace westonpace closed this Jul 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-encoding Encoding, IO, file reader/writer enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant