Skip to content

Conversation

@simonw
Copy link
Owner

@simonw simonw commented Dec 16, 2025

New localserver command that starts a localhost HTTP server serving temporary S3 credentials:

  • Serves credentials on GET / as JSON
  • --duration option to control credential regeneration (required)
  • -p/--port to set port (default 8094)
  • --read-only/--write-only permission options
  • --prefix option for key restriction
  • Credentials cached internally, regenerated after refresh interval
  • Thread-safe with dogpile prevention

Also fixes tests to work with newer versions of click that removed the mix_stderr parameter from CliRunner.

🤖 Generated with Claude Code

Claude Code transcript: https://gistpreview.github.io/?500add71f397874ebadb8e04e8a33b53

New `localserver` command that starts a localhost HTTP server serving
temporary S3 credentials:

- Serves credentials on GET / as JSON
- --refresh-interval option to control credential regeneration (required)
- -p/--port to set port (default 8094)
- --read-only/--write-only permission options
- --prefix option for key restriction
- Credentials cached internally, regenerated after refresh interval
- Thread-safe with dogpile prevention

Also fixes tests to work with newer versions of click that removed
the mix_stderr parameter from CliRunner.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@simonw simonw added the enhancement New feature or request label Dec 16, 2025
simonw and others added 4 commits December 16, 2025 13:49
- Renamed --refresh-interval to -d/--duration using existing DurationParam
  validation (15 minutes to 12 hours)
- Extracted localserver code into s3_credentials/localserver.py module:
  - CredentialCache class for thread-safe credential caching
  - make_credential_handler for HTTP request handling
  - run_server function to start the server
- Moved localserver tests to tests/test_localserver.py
- Added documentation in docs/localserver.md
- Updated docs index to include localserver

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The AWS CLI credential_process requires Version: 1 in the JSON output.
Without this field, the credential_process integration won't work.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@simonw
Copy link
Owner Author

simonw commented Dec 16, 2025

I manually tested it following these tips from Claude:

⏺ Now, to verify the AWS CLI credential_process integration works, you can run these commands:

  1. Start the localserver (in one terminal, with a real bucket you have access to):
    s3-credentials localserver YOUR-BUCKET-NAME --duration 15m

  2. Test the JSON output manually:
    curl -s http://localhost:8094/ | jq .

This should show output with "Version": 1:

{
  "Version": 1,
  "AccessKeyId": "ASIA...",
  "SecretAccessKey": "...",
  "SessionToken": "...",
  "Expiration": "..."
}
  1. Test with AWS CLI credential_process:

Add a profile to your AWS config

echo '[profile localserver-test]
credential_process = curl -s http://localhost:8094/' >> ~/.aws/config

Test it works

aws s3 ls s3://YOUR-BUCKET-NAME/ --profile localserver-test

Or check the identity

aws sts get-caller-identity --profile localserver-test
  1. Clean up (remove the test profile):

Edit ~/.aws/config and remove the [profile localserver-test] section

Sources:

Like this:

~ % aws sts get-caller-identity --profile localserver-test           
{
    "UserId": "AROAWXFXAIOZADV4DDGSA:s3.read-write.litestream-experiments",
    "Account": "462092780466",
    "Arn": "arn:aws:sts::462092780466:assumed-role/s3-credentials.AmazonS3FullAccess/s3.read-write.litestream-experiments"
}

@simonw simonw marked this pull request as ready for review December 16, 2025 22:06
simonw and others added 2 commits December 16, 2025 14:08
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@simonw
Copy link
Owner Author

simonw commented Dec 16, 2025

Refactored the code a bit: http://gistpreview.github.io/?99b41ecbf1c6157024cf9c122ce37e22

Consolidates three separate tests (success, 404, 500) into a single
parametrized test for cleaner, more maintainable test code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@simonw simonw merged commit de3b9c1 into main Dec 16, 2025
10 checks passed
@simonw simonw deleted the localserver branch December 16, 2025 22:16
simonw added a commit that referenced this pull request Dec 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants