arn.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package awsrulesfn
  2. import (
  3. "strings"
  4. )
  5. // ARN provides AWS ARN components broken out into a data structure.
  6. type ARN struct {
  7. Partition string
  8. Service string
  9. Region string
  10. AccountId string
  11. ResourceId OptionalStringSlice
  12. }
  13. const (
  14. arnDelimiters = ":"
  15. resourceDelimiters = "/:"
  16. arnSections = 6
  17. arnPrefix = "arn:"
  18. // zero-indexed
  19. sectionPartition = 1
  20. sectionService = 2
  21. sectionRegion = 3
  22. sectionAccountID = 4
  23. sectionResource = 5
  24. )
  25. // ParseARN returns an [ARN] value parsed from the input string provided. If
  26. // the ARN cannot be parsed nil will be returned, and error added to
  27. // [ErrorCollector].
  28. func ParseARN(input string) *ARN {
  29. if !strings.HasPrefix(input, arnPrefix) {
  30. return nil
  31. }
  32. sections := strings.SplitN(input, arnDelimiters, arnSections)
  33. if numSections := len(sections); numSections != arnSections {
  34. return nil
  35. }
  36. if sections[sectionPartition] == "" {
  37. return nil
  38. }
  39. if sections[sectionService] == "" {
  40. return nil
  41. }
  42. if sections[sectionResource] == "" {
  43. return nil
  44. }
  45. return &ARN{
  46. Partition: sections[sectionPartition],
  47. Service: sections[sectionService],
  48. Region: sections[sectionRegion],
  49. AccountId: sections[sectionAccountID],
  50. ResourceId: splitResource(sections[sectionResource]),
  51. }
  52. }
  53. // splitResource splits the resource components by the ARN resource delimiters.
  54. func splitResource(v string) []string {
  55. var parts []string
  56. var offset int
  57. for offset <= len(v) {
  58. idx := strings.IndexAny(v[offset:], "/:")
  59. if idx < 0 {
  60. parts = append(parts, v[offset:])
  61. break
  62. }
  63. parts = append(parts, v[offset:idx+offset])
  64. offset += idx + 1
  65. }
  66. return parts
  67. }
  68. // OptionalStringSlice provides a helper to safely get the index of a string
  69. // slice that may be out of bounds. Returns pointer to string if index is
  70. // valid. Otherwise returns nil.
  71. type OptionalStringSlice []string
  72. // Get returns a string pointer of the string at index i if the index is valid.
  73. // Otherwise returns nil.
  74. func (s OptionalStringSlice) Get(i int) *string {
  75. if i < 0 || i >= len(s) {
  76. return nil
  77. }
  78. v := s[i]
  79. return &v
  80. }