github.com/aavshr/aws-sdk-go@v1.41.3/internal/s3shared/arn/arn.go (about)

     1  package arn
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/aavshr/aws-sdk-go/aws/arn"
     8  )
     9  
    10  var supportedServiceARN = []string{
    11  	"s3",
    12  	"s3-outposts",
    13  	"s3-object-lambda",
    14  }
    15  
    16  func 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.
    27  type 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.
    34  type ResourceParser func(arn.ARN) (Resource, error)
    35  
    36  // ParseResource parses an AWS ARN into a typed resource for the S3 API.
    37  func 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.
    63  func 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
    81  func IsARN(s string) bool {
    82  	return arn.IsARN(s)
    83  }
    84  
    85  // InvalidARNError provides the error for an invalid ARN error.
    86  type InvalidARNError struct {
    87  	ARN    arn.ARN
    88  	Reason string
    89  }
    90  
    91  // Error returns a string denoting the occurred InvalidARNError
    92  func (e InvalidARNError) Error() string {
    93  	return fmt.Sprintf("invalid Amazon %s ARN, %s, %s", e.ARN.Service, e.Reason, e.ARN.String())
    94  }