From 31ad056819ce5c5c3d8b428a9c82bd1bb43c270a Mon Sep 17 00:00:00 2001 From: Kumar Piyush Date: Sun, 9 Aug 2026 15:27:23 +0530 Subject: [PATCH] Add AWS CodeCommit URL parsing logic Signed-off-by: Kumar Piyush Assisted-by: Antigravity/Claude-Sonnet-4.6 --- auth/aws/provider.go | 47 +++++++++++---- auth/aws/provider_test.go | 119 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 10 deletions(-) diff --git a/auth/aws/provider.go b/auth/aws/provider.go index ab09e8d5..9d7109f3 100644 --- a/auth/aws/provider.go +++ b/auth/aws/provider.go @@ -420,6 +420,41 @@ func (p Provider) NewRESTConfig(ctx context.Context, accessTokens []auth.Token, }, nil } +// ParseCodeCommitURL parses an AWS CodeCommit HTTPS Git URL and returns the +// scheme+host, region, and repository name. +// Supports standard, FIPS, and China partition URLs: +// +// https://git-codecommit.{region}.amazonaws.com/v1/repos/{repository} +// https://git-codecommit-fips.{region}.amazonaws.com/v1/repos/{repository} +// https://git-codecommit.{region}.amazonaws.com.cn/v1/repos/{repository} +// +// See: https://docs.aws.amazon.com/codecommit/latest/userguide/regions.html#regions-git +func ParseCodeCommitURL(rawURL string) (host, region, repo string, err error) { + u, err := url.Parse(rawURL) + if err != nil { + return "", "", "", fmt.Errorf("invalid CodeCommit URL %q: %w", rawURL, err) + } + if !strings.EqualFold(u.Scheme, "https") { + return "", "", "", fmt.Errorf("AWS CodeCommit authentication requires an HTTPS Git URL") + } + hostname := u.Hostname() + urlSplit := strings.Split(hostname, ".") + if len(urlSplit) < 4 || + !(strings.HasPrefix(hostname, "git-codecommit.") || strings.HasPrefix(hostname, "git-codecommit-fips.")) || + !(strings.HasSuffix(hostname, ".amazonaws.com") || strings.HasSuffix(hostname, ".amazonaws.com.cn")) { + return "", "", "", fmt.Errorf("invalid AWS CodeCommit Git URL: %s", u.Host) + } + region = urlSplit[1] + + pathParts := strings.Split(strings.TrimLeft(u.Path, "/"), "/") + if len(pathParts) != 3 || pathParts[0] != "v1" || pathParts[1] != "repos" || pathParts[2] == "" { + return "", "", "", fmt.Errorf("invalid CodeCommit URL %q: path must be /v1/repos/{repository}", rawURL) + } + repo = pathParts[2] + host = fmt.Sprintf("%s://%s", u.Scheme, u.Host) + return host, region, repo, nil +} + // getRegionFromCodeCommitURL extracts the AWS region from a CodeCommit HTTPS // git URL (e.g. https://git-codecommit.us-east-1.amazonaws.com/...). // Returns an error if the URL is nil, not HTTPS, or not a valid CodeCommit URL. @@ -428,16 +463,8 @@ func getRegionFromCodeCommitURL(gitURL *url.URL) (string, error) { if gitURL == nil { return "", fmt.Errorf("Git URL must be specified for AWS CodeCommit authentication") } - if !strings.EqualFold(gitURL.Scheme, "https") { - return "", fmt.Errorf("AWS CodeCommit authentication requires an HTTPS Git URL") - } - urlSplit := strings.Split(gitURL.Hostname(), ".") - if len(urlSplit) < 4 || - !(strings.HasPrefix(gitURL.Hostname(), "git-codecommit.") || strings.HasPrefix(gitURL.Hostname(), "git-codecommit-fips.")) || - !(strings.HasSuffix(gitURL.Hostname(), ".amazonaws.com") || strings.HasSuffix(gitURL.Hostname(), ".amazonaws.com.cn")) { - return "", fmt.Errorf("invalid AWS CodeCommit Git URL: %s", gitURL.Host) - } - return urlSplit[1], nil + _, region, _, err := ParseCodeCommitURL(gitURL.String()) + return region, err } // GetAccessTokenOptionsForGitRepository implements auth.GitCredentialsProvider. diff --git a/auth/aws/provider_test.go b/auth/aws/provider_test.go index b9bed5f4..614903b4 100644 --- a/auth/aws/provider_test.go +++ b/auth/aws/provider_test.go @@ -604,6 +604,125 @@ func TestProvider_GetAccessTokenOptionsForCluster(t *testing.T) { g.Expect(o.STSRegion).To(Equal("us-west-2")) } +func TestParseCodeCommitURL(t *testing.T) { + for _, tt := range []struct { + name string + rawURL string + wantHost string + wantRegion string + wantRepo string + wantErr string + }{ + // --- positive cases --- + { + name: "standard URL us-east-1", + rawURL: "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/my-repo", + wantHost: "https://git-codecommit.us-east-1.amazonaws.com", + wantRegion: "us-east-1", + wantRepo: "my-repo", + }, + { + name: "standard URL eu-west-1", + rawURL: "https://git-codecommit.eu-west-1.amazonaws.com/v1/repos/flux-repo", + wantHost: "https://git-codecommit.eu-west-1.amazonaws.com", + wantRegion: "eu-west-1", + wantRepo: "flux-repo", + }, + { + name: "FIPS URL us-west-2", + rawURL: "https://git-codecommit-fips.us-west-2.amazonaws.com/v1/repos/secure-repo", + wantHost: "https://git-codecommit-fips.us-west-2.amazonaws.com", + wantRegion: "us-west-2", + wantRepo: "secure-repo", + }, + { + name: "China partition URL", + rawURL: "https://git-codecommit.cn-north-1.amazonaws.com.cn/v1/repos/china-repo", + wantHost: "https://git-codecommit.cn-north-1.amazonaws.com.cn", + wantRegion: "cn-north-1", + wantRepo: "china-repo", + }, + { + name: "repo name with hyphens", + rawURL: "https://git-codecommit.ap-southeast-1.amazonaws.com/v1/repos/my-great-repo-123", + wantHost: "https://git-codecommit.ap-southeast-1.amazonaws.com", + wantRegion: "ap-southeast-1", + wantRepo: "my-great-repo-123", + }, + // --- negative cases: scheme --- + { + name: "HTTP scheme rejected", + rawURL: "http://git-codecommit.us-east-1.amazonaws.com/v1/repos/r", + wantErr: "AWS CodeCommit authentication requires an HTTPS Git URL", + }, + { + name: "SSH scheme rejected", + rawURL: "ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/r", + wantErr: "AWS CodeCommit authentication requires an HTTPS Git URL", + }, + { + name: "empty string rejected (no scheme)", + rawURL: "", + wantErr: "AWS CodeCommit authentication requires an HTTPS Git URL", + }, + // --- negative cases: host --- + { + name: "non-CodeCommit host", + rawURL: "https://github.com/org/repo", + wantErr: "invalid AWS CodeCommit Git URL: github.com", + }, + { + name: "codecommit-like but wrong suffix", + rawURL: "https://git-codecommit.us-east-1.example.com/v1/repos/r", + wantErr: "invalid AWS CodeCommit Git URL: git-codecommit.us-east-1.example.com", + }, + // --- negative cases: path --- + { + name: "missing v1/repos prefix", + rawURL: "https://git-codecommit.us-east-1.amazonaws.com/repos/my-repo", + wantErr: `invalid CodeCommit URL "https://git-codecommit.us-east-1.amazonaws.com/repos/my-repo": path must be /v1/repos/{repository}`, + }, + { + name: "empty repository name", + rawURL: "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/", + wantErr: `invalid CodeCommit URL "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/": path must be /v1/repos/{repository}`, + }, + { + name: "path has no repo segment", + rawURL: "https://git-codecommit.us-east-1.amazonaws.com/v1/repos", + wantErr: `invalid CodeCommit URL "https://git-codecommit.us-east-1.amazonaws.com/v1/repos": path must be /v1/repos/{repository}`, + }, + { + name: "extra path segments", + rawURL: "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/r/extra", + wantErr: `invalid CodeCommit URL "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/r/extra": path must be /v1/repos/{repository}`, + }, + // --- edge cases --- + { + name: "unparseable URL", + rawURL: "://not a url", + wantErr: `invalid CodeCommit URL "://not a url":`, + }, + } { + t.Run(tt.name, func(t *testing.T) { + g := NewWithT(t) + host, region, repo, err := aws.ParseCodeCommitURL(tt.rawURL) + if tt.wantErr != "" { + g.Expect(err).To(HaveOccurred()) + g.Expect(err.Error()).To(ContainSubstring(tt.wantErr)) + g.Expect(host).To(BeEmpty()) + g.Expect(region).To(BeEmpty()) + g.Expect(repo).To(BeEmpty()) + } else { + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(host).To(Equal(tt.wantHost)) + g.Expect(region).To(Equal(tt.wantRegion)) + g.Expect(repo).To(Equal(tt.wantRepo)) + } + }) + } +} + func TestProvider_GetAccessTokenOptionsForGitRepository(t *testing.T) { for _, tt := range []struct { name string