forked from mhausenblas/rbIAM
-
Notifications
You must be signed in to change notification settings - Fork 0
/
iam.go
133 lines (124 loc) · 3.11 KB
/
iam.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package main
import (
"context"
"fmt"
"net/url"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/iam"
"github.com/aws/aws-sdk-go-v2/service/sts"
)
// user queries IAM to retrieve info on the user issuing the request.
func (ag *AccessGraph) user(cfg aws.Config) error {
svc := iam.New(cfg)
req := svc.GetUserRequest(&iam.GetUserInput{})
res, err := req.Send(context.Background())
if err != nil {
return err
}
ag.User = res.User
return nil
}
// formatCaller provides a textual rendering of the combined IAM user and caller information.
func formatCaller(ag *AccessGraph) string {
user := ag.User
caller := ag.Caller
return fmt.Sprintf(
" Account ID: %v\n"+
" User name: %v\n"+
" User ID: %v\n"+
" Caller ID: %v\n"+
" Path: %v\n"+
" Created at: %v\n"+
" Tags: %v\n",
*caller.Account,
*user.UserName,
*user.UserId,
*caller.UserId,
*user.Path,
user.CreateDate,
user.Tags,
)
}
// callerIdentity queries STS to retrieve the identity of the caller.
func (ag *AccessGraph) callerIdentity(cfg aws.Config) error {
svc := sts.New(cfg)
req := svc.GetCallerIdentityRequest(&sts.GetCallerIdentityInput{})
res, err := req.Send(context.Background())
if err != nil {
return err
}
ag.Caller = res
return nil
}
// roles queries IAM for roles in use, related to EKS.
// This is done simply by checking if the role ARN contains EKS or eks.
func (ag *AccessGraph) roles(cfg aws.Config) error {
svc := iam.New(cfg)
req := svc.ListRolesRequest(&iam.ListRolesInput{})
res, err := req.Send(context.TODO())
if err != nil {
return err
}
ag.Roles = make(map[string]iam.Role)
for _, role := range res.Roles {
rolearn := *role.Arn
ag.Roles[rolearn] = role
}
return nil
}
// formatRole provides a textual rendering of a role
func formatRole(role *iam.Role) string {
arpd := ""
u, err := url.QueryUnescape(*role.AssumeRolePolicyDocument)
if err == nil {
arpd = u
}
return fmt.Sprintf(
" Name: %v\n"+
" ID: %v\n"+
" Path: %v\n"+
" Assume role by: %v\n"+
" Maximum session duration: %v sec\n"+
" Created at: %v\n"+
" Tags: %v\n",
*role.RoleName,
*role.RoleId,
*role.Path,
arpd,
*role.MaxSessionDuration,
role.CreateDate,
role.Tags,
)
}
// policies queries IAM for attached policies
func (ag *AccessGraph) policies(cfg aws.Config) error {
svc := iam.New(cfg)
req := svc.ListPoliciesRequest(&iam.ListPoliciesInput{OnlyAttached: aws.Bool(true)})
res, err := req.Send(context.TODO())
if err != nil {
return err
}
ag.Policies = make(map[string]iam.Policy)
for _, policy := range res.Policies {
policyarn := *policy.Arn
ag.Policies[policyarn] = policy
}
return nil
}
// formatPolicy provides a textual rendering of a policy.
func formatPolicy(policy *iam.Policy) string {
return fmt.Sprintf(
" Name: %v\n"+
" ID: %v\n"+
" Path: %v\n"+
" Number of entities the policy is attached: %v\n"+
" Created at: %v\n"+
" Updated at: %v\n",
*policy.PolicyName,
*policy.PolicyId,
*policy.Path,
*policy.AttachmentCount,
*policy.CreateDate,
*policy.UpdateDate,
)
}