Skip to content

Commit afe5f04

Browse files
committed
ACL for mcs
This PR sets the initial version of the ACL for mcs, the idea behind this is to start using the principle of least privileges when assigning policies to users, currently mcsAdmin policy uses admin:* and s3:*, we are assuming users have access to everything which is not good. We need to start validating explicitly if users has acccess to an specific endpoint based on IAM policy actions. In this first version every endpoint (you can see it as a page to), defines a set of well defined admin/s3 actions to work properly, ie: ``` // corresponds to /groups endpoint used by the groups page var groupsActionSet = iampolicy.NewActionSet( iampolicy.ListGroupsAdminAction, iampolicy.AddUserToGroupAdminAction, //iampolicy.GetGroupAdminAction, iampolicy.EnableGroupAdminAction, iampolicy.DisableGroupAdminAction, ) // corresponds to /policies endpoint used by the policies page var iamPoliciesActionSet = iampolicy.NewActionSet( iampolicy.GetPolicyAdminAction, iampolicy.DeletePolicyAdminAction, iampolicy.CreatePolicyAdminAction, iampolicy.AttachPolicyAdminAction, iampolicy.ListUserPoliciesAdminAction, ) ``` With that said, for this initial version, now the sessions endpoint will return a list of authorized pages to be render on the UI, on subsequent prs we will add this verification of authorization via a server middleware.
1 parent acf480f commit afe5f04

File tree

19 files changed

+937
-367
lines changed

19 files changed

+937
-367
lines changed

README.md

Lines changed: 55 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,61 @@ $ set -o history
1919
```
2020
$ cat > mcsAdmin.json << EOF
2121
{
22-
"Version": "2012-10-17",
23-
"Statement": [
24-
{
25-
"Action": [
26-
"admin:*"
27-
],
28-
"Effect": "Allow",
29-
"Sid": ""
30-
},
31-
{
32-
"Action": [
33-
"s3:*"
34-
],
35-
"Effect": "Allow",
36-
"Resource": [
37-
"arn:aws:s3:::*"
38-
],
39-
"Sid": ""
40-
}
41-
]
22+
"Version": "2012-10-17",
23+
"Statement": [{
24+
"Action": [
25+
"admin:ServerInfo",
26+
"admin:CreatePolicy",
27+
"admin:DeletePolicy",
28+
"admin:GetPolicy",
29+
"admin:AttachUserOrGroupPolicy",
30+
"admin:ListUserPolicies",
31+
"admin:ConfigUpdate",
32+
"admin:ConsoleLog",
33+
"admin:AddUserToGroup",
34+
"admin:RemoveUserFromGroup",
35+
"admin:ListGroups",
36+
"admin:EnableGroup",
37+
"admin:DisableGroup",
38+
"admin:Profiling",
39+
"admin:ServerTrace",
40+
"admin:CreateUser",
41+
"admin:DeleteUser",
42+
"admin:ListUsers",
43+
"admin:EnableUser",
44+
"admin:DisableUser",
45+
"admin:GetUser"
46+
],
47+
"Effect": "Allow",
48+
"Sid": ""
49+
},
50+
{
51+
"Action": [
52+
"s3:ListenBucketNotification",
53+
"s3:PutBucketNotification",
54+
"s3:GetBucketNotification",
55+
"s3:ListMultipartUploadParts",
56+
"s3:ListBucketMultipartUploads",
57+
"s3:ListBucket",
58+
"s3:HeadBucket",
59+
"s3:GetObject",
60+
"s3:GetBucketLocation",
61+
"s3:AbortMultipartUpload",
62+
"s3:CreateBucket",
63+
"s3:PutObject",
64+
"s3:DeleteObject",
65+
"s3:DeleteBucket",
66+
"s3:PutBucketPolicy",
67+
"s3:DeleteBucketPolicy",
68+
"s3:GetBucketPolicy"
69+
],
70+
"Effect": "Allow",
71+
"Resource": [
72+
"arn:aws:s3:::*"
73+
],
74+
"Sid": ""
75+
}
76+
]
4277
}
4378
EOF
4479
$ mc admin policy add myminio mcsAdmin mcsAdmin.json

models/session_response.go

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/acl/endpoints.go

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
// This file is part of MinIO Console Server
2+
// Copyright (c) 2020 MinIO, Inc.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package acl
18+
19+
import iampolicy "github.com/minio/minio/pkg/iam/policy"
20+
21+
// endpoints definition
22+
var (
23+
configuration = "/configurations-list"
24+
users = "/users"
25+
groups = "/groups"
26+
iamPolicies = "/policies"
27+
dashboard = "/dashboard"
28+
profiling = "/profiling"
29+
trace = "/trace"
30+
logs = "/logs"
31+
watch = "/watch"
32+
notifications = "/notification-endpoints"
33+
buckets = "/buckets"
34+
)
35+
36+
// configurationActionSet contains the list of admin actions required for this endpoint to work
37+
var configurationActionSet = iampolicy.NewActionSet(
38+
iampolicy.ConfigUpdateAdminAction,
39+
)
40+
41+
// logsActionSet contains the list of admin actions required for this endpoint to work
42+
var logsActionSet = iampolicy.NewActionSet(
43+
iampolicy.ConsoleLogAdminAction,
44+
)
45+
46+
// dashboardActionSet contains the list of admin actions required for this endpoint to work
47+
var dashboardActionSet = iampolicy.NewActionSet(
48+
iampolicy.ServerInfoAdminAction,
49+
)
50+
51+
// groupsActionSet contains the list of admin actions required for this endpoint to work
52+
var groupsActionSet = iampolicy.NewActionSet(
53+
iampolicy.ListGroupsAdminAction,
54+
iampolicy.AddUserToGroupAdminAction,
55+
//iampolicy.GetGroupAdminAction,
56+
iampolicy.EnableGroupAdminAction,
57+
iampolicy.DisableGroupAdminAction,
58+
)
59+
60+
// iamPoliciesActionSet contains the list of admin actions required for this endpoint to work
61+
var iamPoliciesActionSet = iampolicy.NewActionSet(
62+
iampolicy.GetPolicyAdminAction,
63+
iampolicy.DeletePolicyAdminAction,
64+
iampolicy.CreatePolicyAdminAction,
65+
iampolicy.AttachPolicyAdminAction,
66+
iampolicy.ListUserPoliciesAdminAction,
67+
)
68+
69+
// profilingActionSet contains the list of admin actions required for this endpoint to work
70+
var profilingActionSet = iampolicy.NewActionSet(
71+
iampolicy.ProfilingAdminAction,
72+
)
73+
74+
// traceActionSet contains the list of admin actions required for this endpoint to work
75+
var traceActionSet = iampolicy.NewActionSet(
76+
iampolicy.TraceAdminAction,
77+
)
78+
79+
// usersActionSet contains the list of admin actions required for this endpoint to work
80+
var usersActionSet = iampolicy.NewActionSet(
81+
iampolicy.ListUsersAdminAction,
82+
iampolicy.CreateUserAdminAction,
83+
iampolicy.DeleteUserAdminAction,
84+
iampolicy.GetUserAdminAction,
85+
iampolicy.EnableUserAdminAction,
86+
iampolicy.DisableUserAdminAction,
87+
)
88+
89+
// watchActionSet contains the list of admin actions required for this endpoint to work
90+
var watchActionSet = iampolicy.NewActionSet(
91+
iampolicy.ListenBucketNotificationAction,
92+
)
93+
94+
// notificationsActionSet contains the list of admin actions required for this endpoint to work
95+
var notificationsActionSet = iampolicy.NewActionSet(
96+
iampolicy.ListenBucketNotificationAction,
97+
iampolicy.PutBucketNotificationAction,
98+
iampolicy.GetBucketNotificationAction,
99+
)
100+
101+
// bucketsActionSet contains the list of admin actions required for this endpoint to work
102+
var bucketsActionSet = iampolicy.NewActionSet(
103+
// Read access to buckets
104+
iampolicy.ListMultipartUploadPartsAction,
105+
iampolicy.ListBucketMultipartUploadsAction,
106+
iampolicy.ListBucketAction,
107+
iampolicy.HeadBucketAction,
108+
iampolicy.GetObjectAction,
109+
iampolicy.GetBucketLocationAction,
110+
// Write access to buckets
111+
iampolicy.AbortMultipartUploadAction,
112+
iampolicy.CreateBucketAction,
113+
iampolicy.PutObjectAction,
114+
iampolicy.DeleteObjectAction,
115+
iampolicy.DeleteBucketAction,
116+
// Assign bucket policies
117+
iampolicy.PutBucketPolicyAction,
118+
iampolicy.DeleteBucketPolicyAction,
119+
iampolicy.GetBucketPolicyAction,
120+
)
121+
122+
// endpointRules contains the mapping between endpoints and ActionSets, additional rules can be added here
123+
var endpointRules = map[string]iampolicy.ActionSet{
124+
configuration: configurationActionSet,
125+
users: usersActionSet,
126+
groups: groupsActionSet,
127+
iamPolicies: iamPoliciesActionSet,
128+
dashboard: dashboardActionSet,
129+
profiling: profilingActionSet,
130+
trace: traceActionSet,
131+
logs: logsActionSet,
132+
watch: watchActionSet,
133+
notifications: notificationsActionSet,
134+
buckets: bucketsActionSet,
135+
}
136+
137+
// GetActionsStringFromPolicy extract the admin/s3 actions from a given policy and return them in []string format
138+
//
139+
// ie:
140+
// {
141+
// "Version": "2012-10-17",
142+
// "Statement": [{
143+
// "Action": [
144+
// "admin:ServerInfo",
145+
// "admin:CreatePolicy",
146+
// "admin:GetUser"
147+
// ],
148+
// ...
149+
// },
150+
// {
151+
// "Action": [
152+
// "s3:ListenBucketNotification",
153+
// "s3:PutBucketNotification"
154+
// ],
155+
// ...
156+
// }
157+
// ]
158+
// }
159+
// Will produce an array like: ["admin:ServerInfo", "admin:CreatePolicy", "admin:GetUser", "s3:ListenBucketNotification", "s3:PutBucketNotification"]\
160+
func GetActionsStringFromPolicy(policy *iampolicy.Policy) []string {
161+
var actions []string
162+
for _, statement := range policy.Statements {
163+
// We only care about allowed actions
164+
if statement.Effect.IsAllowed(true) {
165+
for _, action := range statement.Actions.ToSlice() {
166+
actions = append(actions, string(action))
167+
}
168+
}
169+
}
170+
return actions
171+
}
172+
173+
// actionsStringToActionSet convert a given string array to iampolicy.ActionSet structure
174+
// this avoids ending with duplicate actions
175+
func actionsStringToActionSet(actions []string) iampolicy.ActionSet {
176+
actionsSet := iampolicy.ActionSet{}
177+
for _, action := range actions {
178+
actionsSet.Add(iampolicy.Action(action))
179+
}
180+
return actionsSet
181+
}
182+
183+
// GetAuthorizedEndpoints return a list of allowed endpoint based on a provided *iampolicy.Policy
184+
// ie: pages the user should have access based on his current privileges
185+
func GetAuthorizedEndpoints(actions []string) []string {
186+
if len(actions) == 0 {
187+
return []string{}
188+
}
189+
// Prepare new ActionSet structure that will hold all the user actions
190+
userAllActionSet := actionsStringToActionSet(actions)
191+
var allowedEndpoints []string
192+
for endpoint, rules := range endpointRules {
193+
actions := rules.Intersection(userAllActionSet)
194+
if len(actions) == len(rules.ToSlice()) {
195+
allowedEndpoints = append(allowedEndpoints, endpoint)
196+
}
197+
}
198+
return allowedEndpoints
199+
}

0 commit comments

Comments
 (0)