-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy patharn.go
114 lines (105 loc) · 2.88 KB
/
arn.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package vault_plugin_auth_tencentcloud
import (
"errors"
"fmt"
"strings"
)
const (
arnRoleType arnType = iota // roleName
arnAssumedRoleType // assumed-role
)
const (
roleName = "roleName"
assumedRole = "assumed-role"
)
type arnType int
// toString
func (t arnType) String() string {
switch t {
case arnRoleType:
return roleName
case arnAssumedRoleType:
return assumedRole
default:
return ""
}
}
type arn struct {
Uin string
RoleName string
RoleId string
Full string
Type arnType
}
// check member
func (a *arn) IsMemberOf(possibleParent *arn) bool {
if possibleParent.Type != arnRoleType && possibleParent.Type != arnAssumedRoleType {
return false
}
if possibleParent.Uin != a.Uin {
return false
}
if possibleParent.RoleName != a.RoleName {
return false
}
return true
}
func parseARN(a string) (*arn, error) {
// camArn should look like one of the following:
// 1. qcs::cam::uin/<uin>:roleName/<RoleName>
// 2. qcs::sts:<uin>:assumed-role/<RoleId>
// if we get something like 2, then we want to transform that back to what
// most people would expect, which is qcs::cam::uin/<uin>:roleName/<RoleName>
if a == "" {
return nil, fmt.Errorf("no arn provided")
}
parsed := &arn{
Full: a,
}
outerFields := strings.Split(a, ":")
if len(outerFields) != 6 && len(outerFields) != 5 {
return nil, fmt.Errorf("unrecognized arn: contains %d colon-separated fields, expected 6 or 5", len(outerFields))
}
if outerFields[0] != "qcs" {
return nil, errors.New(`unrecognized arn: does not begin with "qcs:"`)
}
if outerFields[2] != "cam" && outerFields[2] != "sts" {
return nil, fmt.Errorf("unrecognized service: %v, not cam or sts", outerFields[2])
}
if outerFields[2] == "cam" {
uinFields := strings.Split(outerFields[4], "/")
if len(uinFields) < 2 {
return nil, fmt.Errorf("unrecognized arn: %q contains fewer than 2 slash-separated uinFields", outerFields[4])
}
parsed.Uin = uinFields[1]
roleFiles := strings.Split(outerFields[5], "/")
if len(roleFiles) == 2 {
parsed.Type = arnRoleType
if roleFiles[0] == roleName {
parsed.RoleName = roleFiles[1]
} else {
return nil, errors.New("the caller's arn does not match the role's arn")
}
} else {
return nil, fmt.Errorf("unrecognized arn: %q contains fewer than 2 slash-separated roleFiles", outerFields[4])
}
} else if outerFields[2] == "sts" {
parsed.Uin = outerFields[3]
roleFiles := strings.Split(outerFields[4], "/")
if len(roleFiles) == 2 {
parsed.Type = arnAssumedRoleType
if roleFiles[0] == assumedRole {
parsed.RoleId = roleFiles[1]
} else {
return nil, errors.New("the caller's arn does not match the role's arn")
}
} else {
return nil, fmt.Errorf("unrecognized arn: %q contains fewer than 2 slash-separated roleFiles", outerFields[4])
}
}
return parsed, nil
}
// toString
func (a *arn) String() string {
return a.Full
}