1// Package arn provides a parser for interacting with Amazon Resource Names.
2package arn
3
4import (
5	"errors"
6	"strings"
7)
8
9const (
10	arnDelimiter = ":"
11	arnSections  = 6
12	arnPrefix    = "arn:"
13
14	// zero-indexed
15	sectionPartition = 1
16	sectionService   = 2
17	sectionRegion    = 3
18	sectionAccountID = 4
19	sectionResource  = 5
20
21	// errors
22	invalidPrefix   = "arn: invalid prefix"
23	invalidSections = "arn: not enough sections"
24)
25
26// ARN captures the individual fields of an Amazon Resource Name.
27// See http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html for more information.
28type ARN struct {
29	// The partition that the resource is in. For standard AWS regions, the partition is "aws". If you have resources in
30	// other partitions, the partition is "aws-partitionname". For example, the partition for resources in the China
31	// (Beijing) region is "aws-cn".
32	Partition string
33
34	// The service namespace that identifies the AWS product (for example, Amazon S3, IAM, or Amazon RDS). For a list of
35	// namespaces, see
36	// http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#genref-aws-service-namespaces.
37	Service string
38
39	// The region the resource resides in. Note that the ARNs for some resources do not require a region, so this
40	// component might be omitted.
41	Region string
42
43	// The ID of the AWS account that owns the resource, without the hyphens. For example, 123456789012. Note that the
44	// ARNs for some resources don't require an account number, so this component might be omitted.
45	AccountID string
46
47	// The content of this part of the ARN varies by service. It often includes an indicator of the type of resource —
48	// for example, an IAM user or Amazon RDS database - followed by a slash (/) or a colon (:), followed by the
49	// resource name itself. Some services allows paths for resource names, as described in
50	// http://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arns-paths.
51	Resource string
52}
53
54// Parse parses an ARN into its constituent parts.
55//
56// Some example ARNs:
57// arn:aws:elasticbeanstalk:us-east-1:123456789012:environment/My App/MyEnvironment
58// arn:aws:iam::123456789012:user/David
59// arn:aws:rds:eu-west-1:123456789012:db:mysql-db
60// arn:aws:s3:::my_corporate_bucket/exampleobject.png
61func Parse(arn string) (ARN, error) {
62	if !strings.HasPrefix(arn, arnPrefix) {
63		return ARN{}, errors.New(invalidPrefix)
64	}
65	sections := strings.SplitN(arn, arnDelimiter, arnSections)
66	if len(sections) != arnSections {
67		return ARN{}, errors.New(invalidSections)
68	}
69	return ARN{
70		Partition: sections[sectionPartition],
71		Service:   sections[sectionService],
72		Region:    sections[sectionRegion],
73		AccountID: sections[sectionAccountID],
74		Resource:  sections[sectionResource],
75	}, nil
76}
77
78// IsARN returns whether the given string is an arn
79// by looking for whether the string starts with arn:
80func IsARN(arn string) bool {
81	return strings.HasPrefix(arn, arnPrefix) && strings.Count(arn, ":") >= arnSections-1
82}
83
84// String returns the canonical representation of the ARN
85func (arn ARN) String() string {
86	return arnPrefix +
87		arn.Partition + arnDelimiter +
88		arn.Service + arnDelimiter +
89		arn.Region + arnDelimiter +
90		arn.AccountID + arnDelimiter +
91		arn.Resource
92}
93