-
Notifications
You must be signed in to change notification settings - Fork 13
/
iiDatamanagerPolicies.r
196 lines (178 loc) · 7.15 KB
/
iiDatamanagerPolicies.r
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# \file iiDatamanagerPolicies.r
# \brief Sudo microservices policy implementations to enable datamanager control of vault process.
# \author Paul Frederiks
# \author Lazlo Westerhof
# \copyright Copyright (c) 2017-2022, Utrecht University. All rights reserved.
# \license GPLv3 see LICENSE.
# This policy override enables the datamanager to manage ACL's in the vault
# it's signature is defined in the sudo microservice
# The implementation is redirected to iiDatamanagerPreSudoObjAclSet in iiDatamanagerPolicies.r
acPreSudoObjAclSet(*recursive, *accessLevel, *otherName, *objPath, *policyKv) {
ON (*otherName like regex "(datamanager|research|deposit|read)-.*") {
iiDatamanagerPreSudoObjAclSet(*recursive, *accessLevel, *otherName, *objPath, *policyKv);
}
}
# \brief This rule should be called from acPreSudoObjAclSet on sudo ACL set actions.
#
# \param[in] recursive
# \param[in] accessLevel
# \param[in] otherName
# \param[in] objPath
# \param[in] policyKv
#
iiDatamanagerPreSudoObjAclSet(*recursive, *accessLevel, *otherName, *objPath, *policyKv) {
# Initially current user will be set as actor.
# If policyKv holds another, then that actor will override.
*actor = uuClientFullName;
foreach(*key in *policyKv) {
if (*key == "actor") {
*actor = *policyKv.actor
break;
}
}
iiCanDatamanagerAclSet(*objPath, *actor, *otherName, *recursive, *accessLevel, *allowed, *reason);
writeString("serverLog", "iiDatamanagerPreSudoObjAclSet: *reason");
if (*allowed) {
succeed;
}
fail;
}
# \brief Determine the datamanager group belonging to a vault group as vault
# groups do not have metadata on the category themselves.
#
# \param[in] vaultGroup group name starting with vault-
# \param[out] datamanagerGroup group name of the datamanager group belonging to the category of the research group
# associated with the vault
#
iiDatamanagerGroupFromVaultGroup(*vaultGroup, *datamanagerGroup) {
uuGetBaseGroup(*vaultGroup, *baseGroup);
uuGroupGetCategory(*baseGroup, *category, *subcategory);
*datamanagerGroup = "datamanager-*category";
uuGroupExists(*datamanagerGroup, *datamanagerExists);
if (!*datamanagerExists) {
*datamanagerGroup = "";
}
}
# \brief Check if the requester is allowed to change ACL's in the vault.
#
# \param[in] objPath
# \param[in] actor
# \param[in] otherName
# \param[in] recursive
# \param[in] accessLevel
# \param[out] allowed
# \param[out] reason
#
iiCanDatamanagerAclSet(*objPath, *actor, *otherName, *recursive, *accessLevel, *allowed, *reason) {
# When the datamanager needs write/read access to the root of a vault package this rule is run
on (*otherName like "datamanager-*" && *objPath like regex "/[^/]+/home/" ++ IIVAULTPREFIX ++".*") {
writeString("serverLog", "iiCanDatamanagerAclSet: <*actor> wants to obtain <*accessLevel> on <*objPath>");
if (*accessLevel != "write" && *accessLevel != "read") {
*allowed = false;
*reason = "A datamanager can only obtain or revoke write access for the datamanager group to a vault package";
succeed;
}
msiGetObjType(*objPath, *objType);
if (*objType != "-c") {
*allowed = false;
*reason = "A datamanager can only change permissions on collections in the vault";
succeed;
}
uuGroupExists(*otherName, *datamanagerExists);
if (!*datamanagerExists) {
*allowed = false;
*reason = "User is not a datamanager or *otherName does not exist.";
succeed;
}
uuGroupGetMemberType(*otherName, *actor, *userTypeIfDatamanager);
if (*userTypeIfDatamanager == "normal" || *userTypeIfDatamanager == "manager") {
*allowed = true;
*reason = "User is a datamanager.";
} else {
*allowed = false;
*reason = "User is not a datamanager.";
succeed;
}
}
# When a datamanager wants to grant or revoke read access for a research or read group in the vault, this rule will run
on (*objPath like regex "/[^/]+/home/" ++ IIVAULTPREFIX ++".*") {
writeString("serverLog", "iiCanDatamanagerAclSet: <*actor> wants to set <*accessLevel> for <*otherName> on <*objPath>");
if (*accessLevel != "read" && *accessLevel != "null") {
*allowed = false;
*reason = "A datamanager can only grant write or read access or revoke access in the vault.";
succeed;
}
uuChop(*otherName, *_, *baseGroupName, "-", true);
if (*otherName == IIGROUPPREFIX ++ *baseGroupName || *otherName == "deposit-" ++ *baseGroupName || *otherName == "read-" ++ *baseGroupName) {
if (*otherName == "deposit-" ++ *baseGroupName) {
uuGroupGetCategory("deposit-" ++ *baseGroupName, *category, *subcategory);
} else {
uuGroupGetCategory(IIGROUPPREFIX ++ *baseGroupName, *category, *subcategory);
uuGroupExists("research-*baseGroupName", *researchExists);
if (!*researchExists) {
*allowed = false;
*reason = "Cannot grant or revoke read access, research group *category does not exist.";
succeed;
}
}
uuGroupExists("datamanager-*category", *datamanagerExists);
if (!*datamanagerExists) {
*allowed = false;
*reason = "User is not a datamanager or no datamanager exists.";
succeed;
}
uuGroupGetMemberType("datamanager-*category", *actor, *userTypeIfDatamanager);
if (*userTypeIfDatamanager == "normal" || *userTypeIfDatamanager == "manager") {
*allowed = true;
*reason = "User is a datamanager of category *category.";
} else {
*allowed = false;
*reason = "User is not a datamanager.";
succeed;
}
} else {
*allowed = false;
*reason = "Only research groups can be granted read access to the vault";
succeed;
}
*vaultGroupName = IIVAULTPREFIX ++ *baseGroupName;
*pathElems = split(*objPath, "/");
if (size(*pathElems) < 4) {
*allowed = false;
*reason = "*objPath is not a datapackage in the vault.";
} else if (elem(*pathElems, 2) != *vaultGroupName) {
*allowed = false;
*reason = "*objPath is not part of *vaultGroupName";
}
}
# when a status transition in the research area is invoked by the datamanager, he needs temporary write access to change the folder status
on (*objPath like regex "/[^/]+/home/" ++ IIGROUPPREFIX ++ ".*") {
if (*accessLevel == "inherit" || *accessLevel == "own") {
*allowed = false;
*reason = "Cannot grant own or inherit to *objPath";
succeed;
}
*groupName = "";
rule_collection_group_name(*objPath, *groupName);
uuGroupGetCategory(*groupName, *category, *subcategory);
if (*otherName == "datamanager-*category") {
uuGroupGetMemberType(*otherName, *actor, *userTypeIfDatamanager);
if (*userTypeIfDatamanager == "normal" || *userTypeIfDatamanager == "manager") {
*allowed = true;
*reason = "User is a datamanager of category *category.";
} else {
*allowed = false;
*reason = "User is not a datamanager.";
}
} else {
*allowed = false;
*reason = "Permission can only be granted to the datamanager-*category group, not *otherName.";
}
}
# fallback to prevent users defining and using their own iiCanDatamanagerAclSet.
# This is also reached when the frontend requests a status change it is not allowed to do.
on (true) {
*allowed = false;
*reason = "Current status of folder *objPath is not 'submitted', 'accepted' or 'rejected'. Therefore the requested action can not be completed as a datamanager.";
}
}