forked from raystack/guardian
-
Notifications
You must be signed in to change notification settings - Fork 2
/
config.go
137 lines (118 loc) · 3.38 KB
/
config.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
134
135
136
137
package gitlab
import (
"errors"
"fmt"
"github.com/goto/guardian/domain"
"github.com/goto/guardian/utils"
"github.com/mitchellh/mapstructure"
"github.com/xanzy/go-gitlab"
)
const (
accountTypeGitlabUserID = "gitlab_user_id"
resourceTypeProject = "project"
resourceTypeGroup = "group"
// https://docs.gitlab.com/ee/api/members.html#roles
roleNoAccess = "no_access"
roleMinimalAccess = "minimal_access"
roleGuest = "guest"
roleReporter = "reporter"
roleDeveloper = "developer"
roleMaintainer = "maintainer"
roleOwner = "owner"
)
var (
validResourceTypes = []string{resourceTypeProject, resourceTypeGroup}
validGitlabRoles = []string{
roleNoAccess,
roleMinimalAccess,
roleGuest,
roleReporter,
roleDeveloper,
roleMaintainer,
roleOwner,
}
gitlabRoleMapping = map[string]gitlab.AccessLevelValue{
roleNoAccess: gitlab.NoPermissions,
roleMinimalAccess: gitlab.AccessLevelValue(5),
roleGuest: gitlab.GuestPermissions,
roleReporter: gitlab.ReporterPermissions,
roleDeveloper: gitlab.DeveloperPermissions,
roleMaintainer: gitlab.MaintainerPermissions,
roleOwner: gitlab.OwnerPermissions,
}
)
type credentials struct {
Host string `mapstructure:"host" yaml:"host" json:"host"`
AccessToken string `mapstructure:"access_token" yaml:"access_token" json:"access_token"`
}
func (c credentials) validate() error {
if c.Host == "" {
return errors.New("host is required")
}
if c.AccessToken == "" {
return errors.New("access_token is required")
}
return nil
}
func (c *credentials) encrypt(encryptor domain.Encryptor) error {
encryptedAccessToken, err := encryptor.Encrypt(c.AccessToken)
if err != nil {
return err
}
c.AccessToken = encryptedAccessToken
return nil
}
func (c *credentials) decrypt(decryptor domain.Decryptor) error {
decryptedAccessToken, err := decryptor.Decrypt(c.AccessToken)
if err != nil {
return err
}
c.AccessToken = decryptedAccessToken
return nil
}
type config struct {
*domain.ProviderConfig
}
func (c *config) getCredentials() (*credentials, error) {
if creds, ok := c.Credentials.(credentials); ok { // parsed
return &creds, nil
} else if mapCreds, ok := c.Credentials.(map[string]interface{}); ok { // not parsed
var creds credentials
if err := mapstructure.Decode(mapCreds, &creds); err != nil {
return nil, fmt.Errorf("unable to decode credentials: %w", err)
}
return &creds, nil
}
return nil, fmt.Errorf("invalid credentials type: %T", c.Credentials)
}
func (c *config) validateGitlabSpecificConfig() error {
// validate credentials
if c.Credentials == nil {
return fmt.Errorf("missing credentials")
}
creds, err := c.getCredentials()
if err != nil {
return err
}
if err := creds.validate(); err != nil {
return fmt.Errorf("invalid credentials: %w", err)
}
// validate resource config
for _, rc := range c.Resources {
if !utils.ContainsString(validResourceTypes, rc.Type) {
return fmt.Errorf("invalid resource type: %q", rc.Type)
}
for _, role := range rc.Roles {
for _, permission := range role.Permissions {
permissionString, ok := permission.(string)
if !ok {
return fmt.Errorf("unexpected permission type: %T, expected: string", permission)
}
if !utils.ContainsString(validGitlabRoles, permissionString) {
return fmt.Errorf("invalid permission: %q", permissionString)
}
}
}
}
return nil
}