// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package moduleaddrs import ( "fmt" "net/url" "strings" ) // detectS3 detects strings that seem like schemeless references to // Amazon S3 and translates them into URLs for the "s3" getter. func detectS3(src string) (string, bool, error) { if len(src) == 0 { return "", false, nil } if strings.Contains(src, ".amazonaws.com/") { parts := strings.Split(src, "/") if len(parts) < 2 { return "", false, fmt.Errorf( "URL is not a valid S3 URL") } hostParts := strings.Split(parts[0], ".") if len(hostParts) == 3 { return detectS3PathStyle(hostParts[0], parts[1:]) } else if len(hostParts) == 4 { return detectS3OldVhostStyle(hostParts[1], hostParts[0], parts[1:]) } else if len(hostParts) == 5 && hostParts[1] == "s3" { return detectS3NewVhostStyle(hostParts[2], hostParts[0], parts[1:]) } else { return "", false, fmt.Errorf( "URL is not a valid S3 URL") } } return "", false, nil } func detectS3PathStyle(region string, parts []string) (string, bool, error) { urlStr := fmt.Sprintf("https://%s.amazonaws.com/%s", region, strings.Join(parts, "/")) url, err := url.Parse(urlStr) if err != nil { return "", false, fmt.Errorf("error parsing S3 URL: %s", err) } return "s3::" + url.String(), true, nil } func detectS3OldVhostStyle(region, bucket string, parts []string) (string, bool, error) { urlStr := fmt.Sprintf("https://%s.amazonaws.com/%s/%s", region, bucket, strings.Join(parts, "/")) url, err := url.Parse(urlStr) if err != nil { return "", false, fmt.Errorf("error parsing S3 URL: %s", err) } return "s3::" + url.String(), true, nil } func detectS3NewVhostStyle(region, bucket string, parts []string) (string, bool, error) { urlStr := fmt.Sprintf("https://s3.%s.amazonaws.com/%s/%s", region, bucket, strings.Join(parts, "/")) url, err := url.Parse(urlStr) if err != nil { return "", false, fmt.Errorf("error parsing S3 URL: %s", err) } return "s3::" + url.String(), true, nil }