From 2bca3d672e14c56147903f00c584b90a41fffa17 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Jul 2026 14:16:03 +0000 Subject: [PATCH 1/2] fix(pull): pin AWS region for STS so `devbox global push` works without an ambient region (#2591) The STS client used to assume the JetpackS3Federated role was built from config.LoadDefaultConfig(ctx) with no region. AWS SDK v2 cannot resolve the STS endpoint without a region, so users who have no AWS region configured in their environment (a fresh Jetify signup, no ~/.aws/config, no AWS_REGION) hit: Error: operation error STS: AssumeRoleWithWebIdentity, failed to resolve service endpoint, endpoint rule error, Invalid Configuration: Missing Region The `region` constant already existed and was applied to the downstream S3 config, but only via a post-hoc `config.Region = region` mutation because the local variable shadowed the imported `config` package. Pin the region on both configs via config.WithRegion(region), fix the shadowing (cfg), and stop ignoring the first LoadDefaultConfig error. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01NZuVavP5v2abUek98MDBCQ --- internal/pullbox/s3/config.go | 15 ++++++--- internal/pullbox/s3/config_test.go | 54 ++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 internal/pullbox/s3/config_test.go diff --git a/internal/pullbox/s3/config.go b/internal/pullbox/s3/config.go index ff6fdac523a..5efd142ba84 100644 --- a/internal/pullbox/s3/config.go +++ b/internal/pullbox/s3/config.go @@ -23,7 +23,14 @@ const ( ) func assumeRole(ctx context.Context, c *devopt.Credentials) (*aws.Config, error) { - noPermsConfig, _ := config.LoadDefaultConfig(ctx) + // STS needs an explicit region to resolve its endpoint. Without one, + // users who don't have an AWS region configured in their environment hit + // "Invalid Configuration: Missing Region" when running `devbox global + // push`. Pin it to the bucket's region, same as the config below. + noPermsConfig, err := config.LoadDefaultConfig(ctx, config.WithRegion(region)) + if err != nil { + return nil, errors.WithStack(err) + } stsClient := sts.NewFromConfig(noPermsConfig) creds, err := stsClient.AssumeRoleWithWebIdentity( ctx, @@ -37,8 +44,9 @@ func assumeRole(ctx context.Context, c *devopt.Credentials) (*aws.Config, error) return nil, err } - config, err := config.LoadDefaultConfig( + cfg, err := config.LoadDefaultConfig( ctx, + config.WithRegion(region), config.WithCredentialsProvider( credentials.NewStaticCredentialsProvider( *creds.Credentials.AccessKeyId, @@ -47,9 +55,8 @@ func assumeRole(ctx context.Context, c *devopt.Credentials) (*aws.Config, error) ), ), ) - config.Region = region if err != nil { return nil, errors.WithStack(err) } - return &config, err + return &cfg, nil } diff --git a/internal/pullbox/s3/config_test.go b/internal/pullbox/s3/config_test.go new file mode 100644 index 00000000000..95c1a0e5990 --- /dev/null +++ b/internal/pullbox/s3/config_test.go @@ -0,0 +1,54 @@ +package s3 + +import ( + "context" + "testing" + + "github.com/aws/aws-sdk-go-v2/config" +) + +// TestConfigPinsRegion guards against a regression of jetify-com/devbox#2591, +// where `devbox global push` failed with "Invalid Configuration: Missing +// Region" for users who had no AWS region configured in their environment. +// +// assumeRole builds AWS configs (for both the STS and S3 clients) that must +// explicitly pin the region, since neither STS nor S3 can resolve an endpoint +// without one. This test reproduces the reporter's environment (no region +// configured anywhere) and verifies that pinning the region via +// config.WithRegion(region) still yields a config with the expected region. +func TestConfigPinsRegion(t *testing.T) { + if region == "" { + t.Fatal("region constant must not be empty; STS/S3 endpoint resolution requires it") + } + + // Simulate a user with no AWS region configured anywhere: clear the + // region environment variables and point the shared config/credentials + // files at nonexistent paths so no ambient region leaks in. + t.Setenv("AWS_REGION", "") + t.Setenv("AWS_DEFAULT_REGION", "") + t.Setenv("AWS_CONFIG_FILE", "/dev/null") + t.Setenv("AWS_SHARED_CREDENTIALS_FILE", "/dev/null") + + ctx := context.Background() + + // Without an explicit region, the loaded config has no region. This is the + // condition that produced the "Missing Region" error before the fix. + noRegion, err := config.LoadDefaultConfig(ctx) + if err != nil { + t.Fatalf("loading default config: %v", err) + } + if noRegion.Region != "" { + t.Skipf("test environment provides a default AWS region (%q); "+ + "cannot exercise the missing-region case", noRegion.Region) + } + + // With the region pinned (as assumeRole now does for both configs), the + // region is set regardless of the environment. + pinned, err := config.LoadDefaultConfig(ctx, config.WithRegion(region)) + if err != nil { + t.Fatalf("loading config with pinned region: %v", err) + } + if pinned.Region != region { + t.Errorf("pinned region = %q, want %q", pinned.Region, region) + } +} From da0e88669cec07036ac7dd35278c0afba4467005 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 30 Jul 2026 14:19:32 +0000 Subject: [PATCH 2/2] fix(pull): satisfy linters (usetesting, varnamelen) - Use t.Context() instead of context.Background() in the new test. - Rename the too-short assumeRole parameter `c` to `cred`. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01NZuVavP5v2abUek98MDBCQ --- internal/pullbox/s3/config.go | 6 +++--- internal/pullbox/s3/config_test.go | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/internal/pullbox/s3/config.go b/internal/pullbox/s3/config.go index 5efd142ba84..c8a1004ebc9 100644 --- a/internal/pullbox/s3/config.go +++ b/internal/pullbox/s3/config.go @@ -22,7 +22,7 @@ const ( region = "us-east-2" ) -func assumeRole(ctx context.Context, c *devopt.Credentials) (*aws.Config, error) { +func assumeRole(ctx context.Context, cred *devopt.Credentials) (*aws.Config, error) { // STS needs an explicit region to resolve its endpoint. Without one, // users who don't have an AWS region configured in their environment hit // "Invalid Configuration: Missing Region" when running `devbox global @@ -36,8 +36,8 @@ func assumeRole(ctx context.Context, c *devopt.Credentials) (*aws.Config, error) ctx, &sts.AssumeRoleWithWebIdentityInput{ RoleArn: aws.String(roleArn), - RoleSessionName: aws.String(c.Email), - WebIdentityToken: aws.String(c.IDToken), + RoleSessionName: aws.String(cred.Email), + WebIdentityToken: aws.String(cred.IDToken), }, ) if err != nil { diff --git a/internal/pullbox/s3/config_test.go b/internal/pullbox/s3/config_test.go index 95c1a0e5990..28faa4c0ee6 100644 --- a/internal/pullbox/s3/config_test.go +++ b/internal/pullbox/s3/config_test.go @@ -1,7 +1,6 @@ package s3 import ( - "context" "testing" "github.com/aws/aws-sdk-go-v2/config" @@ -29,7 +28,7 @@ func TestConfigPinsRegion(t *testing.T) { t.Setenv("AWS_CONFIG_FILE", "/dev/null") t.Setenv("AWS_SHARED_CREDENTIALS_FILE", "/dev/null") - ctx := context.Background() + ctx := t.Context() // Without an explicit region, the loaded config has no region. This is the // condition that produced the "Missing Region" error before the fix.