From 150a19435ad553746e393718edc36af68610c09e Mon Sep 17 00:00:00 2001 From: Rahul Singh Date: Sat, 7 Mar 2026 09:52:38 -0800 Subject: [PATCH] feat: shorten credential paths with nanoid and ~/.tiam directory Replace UUID-based session IDs with 10-char nanoid for shorter credential file names. Rename credential directory from ~/.timebound-iam to ~/.tiam. Bump version to 0.7.0. --- go.mod | 13 ++++++++----- go.sum | 18 ++++++++++++++++-- main.go | 6 +++--- timebound/aws/broker.go | 10 +++++++--- 4 files changed, 34 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index aeeae7c..7b4bb08 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,14 @@ module github.com/builder-magic/timebound-iam go 1.25.5 require ( - github.com/aws/aws-sdk-go-v2 v1.41.1 // indirect - github.com/aws/aws-sdk-go-v2/config v1.32.7 // indirect + github.com/aws/aws-sdk-go-v2 v1.41.1 + github.com/aws/aws-sdk-go-v2/config v1.32.7 + github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 + github.com/matoous/go-nanoid/v2 v2.1.0 + github.com/modelcontextprotocol/go-sdk v1.3.0 +) + +require ( github.com/aws/aws-sdk-go-v2/credentials v1.19.7 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 // indirect @@ -15,11 +21,8 @@ require ( github.com/aws/aws-sdk-go-v2/service/signin v1.0.5 // indirect github.com/aws/aws-sdk-go-v2/service/sso v1.30.9 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.13 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 // indirect github.com/aws/smithy-go v1.24.0 // indirect github.com/google/jsonschema-go v0.4.2 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/modelcontextprotocol/go-sdk v1.3.0 // indirect github.com/yosida95/uritemplate/v3 v3.0.2 // indirect golang.org/x/oauth2 v0.30.0 // indirect ) diff --git a/go.sum b/go.sum index ba13c5b..08ce307 100644 --- a/go.sum +++ b/go.sum @@ -26,13 +26,27 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.41.6 h1:5fFjR/ToSOzB2OQ/XqWpZBmNvmP/ github.com/aws/aws-sdk-go-v2/service/sts v1.41.6/go.mod h1:qgFDZQSD/Kys7nJnVqYlWKnh0SSdMjAi0uSwON4wgYQ= github.com/aws/smithy-go v1.24.0 h1:LpilSUItNPFr1eY85RYgTIg5eIEPtvFbskaFcmmIUnk= github.com/aws/smithy-go v1.24.0/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= +github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/jsonschema-go v0.4.2 h1:tmrUohrwoLZZS/P3x7ex0WAVknEkBZM46iALbcqoRA8= github.com/google/jsonschema-go v0.4.2/go.mod h1:r5quNTdLOYEz95Ru18zA0ydNbBuYoo9tgaYcxEYhJVE= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/matoous/go-nanoid/v2 v2.1.0 h1:P64+dmq21hhWdtvZfEAofnvJULaRR1Yib0+PnU669bE= +github.com/matoous/go-nanoid/v2 v2.1.0/go.mod h1:KlbGNQ+FhrUNIHUxZdL63t7tl4LaPkZNpUULS8H4uVM= github.com/modelcontextprotocol/go-sdk v1.3.0 h1:gMfZkv3DzQF5q/DcQePo5rahEY+sguyPfXDfNBcT0Zs= github.com/modelcontextprotocol/go-sdk v1.3.0/go.mod h1:AnQ//Qc6+4nIyyrB4cxBU7UW9VibK4iOZBeyP/rF1IE= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 4a2893a..4635d0c 100644 --- a/main.go +++ b/main.go @@ -19,9 +19,9 @@ import ( const ( serverName = "timebound-iam" - serverVersion = "0.6.0" + serverVersion = "0.7.0" - defaultDirName = ".timebound-iam" + defaultDirName = ".tiam" credentialSubdir = "credentials" ) @@ -146,7 +146,7 @@ func hasHelpFlag(args []string) bool { return false } -// resolveCredentialDir returns the credential directory path (~/.timebound-iam/credentials), +// resolveCredentialDir returns the credential directory path (~/.tiam/credentials), // creating it if needed with 0700 permissions. func resolveCredentialDir() (string, error) { home, err := os.UserHomeDir() diff --git a/timebound/aws/broker.go b/timebound/aws/broker.go index a007615..f41c470 100644 --- a/timebound/aws/broker.go +++ b/timebound/aws/broker.go @@ -10,7 +10,7 @@ import ( awsconfig "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/sts" ststypes "github.com/aws/aws-sdk-go-v2/service/sts/types" - "github.com/google/uuid" + nanoid "github.com/matoous/go-nanoid/v2" ) const ( @@ -145,7 +145,11 @@ func (b *Broker) GrantAccess(ctx context.Context, input GrantAccessInput) (*Sess return nil, fmt.Errorf("too many services: STS allows at most %d session policies per call, got %d", maxPolicyARNs, len(policyARNs)) } - sessionName := fmt.Sprintf("timebound-iam-%s", uuid.New().String()) + id, err := nanoid.New(10) + if err != nil { + return nil, fmt.Errorf("generating session ID: %w", err) + } + sessionName := fmt.Sprintf("timebound-iam-%s", id) durationSeconds := int32(input.TTL.Seconds()) result, err := b.stsClient.AssumeRole(ctx, &sts.AssumeRoleInput{ @@ -160,7 +164,7 @@ func (b *Broker) GrantAccess(ctx context.Context, input GrantAccessInput) (*Sess creds := result.Credentials return &Session{ - ID: sessionName, + ID: id, Services: input.Services, Level: input.Level, Profile: input.Profile,