1package arn 2 3import ( 4 "fmt" 5 "strings" 6 7 "github.com/aws/aws-sdk-go/aws/arn" 8) 9 10var supportedServiceARN = []string{ 11 "s3", 12 "s3-outposts", 13 "s3-object-lambda", 14} 15 16func isSupportedServiceARN(service string) bool { 17 for _, name := range supportedServiceARN { 18 if name == service { 19 return true 20 } 21 } 22 return false 23} 24 25// Resource provides the interfaces abstracting ARNs of specific resource 26// types. 27type Resource interface { 28 GetARN() arn.ARN 29 String() string 30} 31 32// ResourceParser provides the function for parsing an ARN's resource 33// component into a typed resource. 34type ResourceParser func(arn.ARN) (Resource, error) 35 36// ParseResource parses an AWS ARN into a typed resource for the S3 API. 37func ParseResource(s string, resParser ResourceParser) (resARN Resource, err error) { 38 a, err := arn.Parse(s) 39 if err != nil { 40 return nil, err 41 } 42 43 if len(a.Partition) == 0 { 44 return nil, InvalidARNError{ARN: a, Reason: "partition not set"} 45 } 46 47 if !isSupportedServiceARN(a.Service) { 48 return nil, InvalidARNError{ARN: a, Reason: "service is not supported"} 49 } 50 51 if strings.HasPrefix(a.Region, "fips-") || strings.HasSuffix(a.Region, "-fips") { 52 return nil, InvalidARNError{ARN: a, Reason: "FIPS region not allowed in ARN"} 53 } 54 55 if len(a.Resource) == 0 { 56 return nil, InvalidARNError{ARN: a, Reason: "resource not set"} 57 } 58 59 return resParser(a) 60} 61 62// SplitResource splits the resource components by the ARN resource delimiters. 63func SplitResource(v string) []string { 64 var parts []string 65 var offset int 66 67 for offset <= len(v) { 68 idx := strings.IndexAny(v[offset:], "/:") 69 if idx < 0 { 70 parts = append(parts, v[offset:]) 71 break 72 } 73 parts = append(parts, v[offset:idx+offset]) 74 offset += idx + 1 75 } 76 77 return parts 78} 79 80// IsARN returns whether the given string is an ARN 81func IsARN(s string) bool { 82 return arn.IsARN(s) 83} 84 85// InvalidARNError provides the error for an invalid ARN error. 86type InvalidARNError struct { 87 ARN arn.ARN 88 Reason string 89} 90 91// Error returns a string denoting the occurred InvalidARNError 92func (e InvalidARNError) Error() string { 93 return fmt.Sprintf("invalid Amazon %s ARN, %s, %s", e.ARN.Service, e.Reason, e.ARN.String()) 94} 95