25
25
description = "APIs to handle cross namespace ACL" )
26
26
@ Controller ("/api/namespaces/{namespace}/acls" )
27
27
public class AccessControlListController extends NamespacedResourceController {
28
+ /**
29
+ * The namespace service
30
+ */
28
31
@ Inject
29
32
NamespaceService namespaceService ;
33
+
34
+ /**
35
+ * The ACL service
36
+ */
30
37
@ Inject
31
38
AccessControlEntryService accessControlEntryService ;
32
39
40
+ /**
41
+ * Get all ACLs of given namespace
42
+ * @param namespace The namespace
43
+ * @param limit The ACL scope
44
+ * @return A list of ACLs
45
+ */
33
46
@ Operation (summary = "Returns the Access Control Entry List" )
34
47
@ Get ("{?limit}" )
35
48
public List <AccessControlEntry > list (String namespace , Optional <AclLimit > limit ) {
36
- if (limit .isEmpty ())
49
+ if (limit .isEmpty ()) {
37
50
limit = Optional .of (AclLimit .ALL );
51
+ }
38
52
39
53
Namespace ns = getNamespace (namespace );
40
-
41
54
switch (limit .get ()) {
42
55
case GRANTEE :
43
56
return accessControlEntryService .findAllGrantedToNamespace (ns )
@@ -69,6 +82,12 @@ public List<AccessControlEntry> list(String namespace, Optional<AclLimit> limit)
69
82
70
83
}
71
84
85
+ /**
86
+ * Get an ACL by namespace and name
87
+ * @param namespace The name
88
+ * @param acl The ACL name
89
+ * @return The ACL
90
+ */
72
91
@ Get ("/{acl}" )
73
92
public Optional <AccessControlEntry > get (String namespace , String acl ) {
74
93
return list (namespace , Optional .of (AclLimit .ALL ))
@@ -77,75 +96,94 @@ public Optional<AccessControlEntry> get(String namespace, String acl) {
77
96
.findFirst ();
78
97
}
79
98
99
+ /**
100
+ * Create an ACL
101
+ * @param authentication The authentication entity
102
+ * @param namespace The namespace
103
+ * @param accessControlEntry The ACL
104
+ * @param dryrun Is dry run mode or not ?
105
+ * @return An HTTP response
106
+ */
80
107
@ Post ("{?dryrun}" )
81
108
public HttpResponse <AccessControlEntry > apply (Authentication authentication , String namespace , @ Valid @ Body AccessControlEntry accessControlEntry , @ QueryValue (defaultValue = "false" ) boolean dryrun ) {
82
109
Namespace ns = getNamespace (namespace );
83
110
84
111
List <String > roles = (List <String >) authentication .getAttributes ().get ("roles" );
85
112
boolean isAdmin = roles .contains (ResourceBasedSecurityRule .IS_ADMIN );
86
- // self assigned ACL (spec.grantedTo == metadata.namespace)
113
+ // Self assigned ACL (spec.grantedTo == metadata.namespace)
87
114
boolean isSelfAssignedACL = namespace .equals (accessControlEntry .getSpec ().getGrantedTo ());
88
115
89
116
List <String > validationErrors ;
90
117
if (isAdmin && isSelfAssignedACL ) {
91
- // validate overlapping OWNER
118
+ // Validate overlapping OWNER
92
119
validationErrors = accessControlEntryService .validateAsAdmin (accessControlEntry , ns );
93
120
} else {
94
121
validationErrors = accessControlEntryService .validate (accessControlEntry , ns );
95
122
}
123
+
96
124
if (!validationErrors .isEmpty ()) {
97
125
throw new ResourceValidationException (validationErrors , accessControlEntry .getKind (), accessControlEntry .getMetadata ().getName ());
98
126
}
127
+
99
128
// AccessControlEntry spec is immutable
100
129
// This prevents accidental updates on ACL resources already declared with the same name (with differents rules)
101
130
Optional <AccessControlEntry > existingACL = accessControlEntryService .findByName (namespace , accessControlEntry .getMetadata ().getName ());
102
131
if (existingACL .isPresent () && !existingACL .get ().getSpec ().equals (accessControlEntry .getSpec ())){
103
132
throw new ResourceValidationException (List .of ("Invalid modification: `spec` is immutable. You can still update `metadata`" ), accessControlEntry .getKind (), accessControlEntry .getMetadata ().getName ());
104
133
}
105
134
106
- //augment
107
135
accessControlEntry .getMetadata ().setCreationTimestamp (Date .from (Instant .now ()));
108
136
accessControlEntry .getMetadata ().setCluster (ns .getMetadata ().getCluster ());
109
137
accessControlEntry .getMetadata ().setNamespace (ns .getMetadata ().getName ());
110
138
111
- if (existingACL .isPresent () && existingACL .get ().equals (accessControlEntry )){
139
+ if (existingACL .isPresent () && existingACL .get ().equals (accessControlEntry )) {
112
140
return formatHttpResponse (existingACL .get (), ApplyStatus .unchanged );
113
141
}
142
+
114
143
ApplyStatus status = existingACL .isPresent () ? ApplyStatus .changed : ApplyStatus .created ;
115
144
116
- //dryrun checks
145
+ // Dry run checks
117
146
if (dryrun ) {
118
147
return formatHttpResponse (accessControlEntry , status );
119
148
}
149
+
120
150
sendEventLog (accessControlEntry .getKind (),
121
151
accessControlEntry .getMetadata (),
122
152
status ,
123
- existingACL .isPresent () ? existingACL . get (). getSpec () : null ,
153
+ existingACL .< Object > map ( AccessControlEntry :: getSpec ). orElse ( null ) ,
124
154
accessControlEntry .getSpec ());
125
155
126
- //store
156
+ // Store
127
157
return formatHttpResponse (accessControlEntryService .create (accessControlEntry ), status );
128
158
}
129
159
160
+ /**
161
+ * Delete an ACL
162
+ * @param authentication The authentication entity
163
+ * @param namespace The namespace
164
+ * @param name The ACL name
165
+ * @param dryrun Is dry run mode or not ?
166
+ * @return An HTTP response
167
+ */
130
168
@ Delete ("/{name}{?dryrun}" )
131
169
@ Status (HttpStatus .NO_CONTENT )
132
170
public HttpResponse <Void > delete (Authentication authentication , String namespace , String name , @ QueryValue (defaultValue = "false" ) boolean dryrun ) {
133
-
171
+ Namespace ns = getNamespace ( namespace );
134
172
AccessControlEntry accessControlEntry = accessControlEntryService
135
173
.findByName (namespace , name )
136
174
.orElseThrow (() -> new ResourceValidationException (
137
175
List .of ("Invalid value " + name + " for name : AccessControlEntry doesn't exist in this namespace" ),
138
176
"AccessControlEntry" ,
139
- name
140
- )
177
+ name )
141
178
);
142
179
143
180
List <String > roles = (List <String >) authentication .getAttributes ().get ("roles" );
144
181
boolean isAdmin = roles .contains (ResourceBasedSecurityRule .IS_ADMIN );
145
- // self assigned ACL (spec.grantedTo == metadata.namespace)
182
+ // Self assigned ACL (spec.grantedTo == metadata.namespace)
146
183
boolean isSelfAssignedACL = namespace .equals (accessControlEntry .getSpec ().getGrantedTo ());
184
+
147
185
if (isSelfAssignedACL && !isAdmin ) {
148
- // prevent delete
186
+ // Prevent delete
149
187
throw new ResourceValidationException (
150
188
List .of ("Only admins can delete this AccessControlEntry" ),
151
189
"AccessControlEntry" ,
@@ -158,7 +196,7 @@ public HttpResponse<Void> delete(Authentication authentication, String namespace
158
196
}
159
197
160
198
sendEventLog (accessControlEntry .getKind (), accessControlEntry .getMetadata (), ApplyStatus .deleted ,accessControlEntry .getSpec (), null );
161
- accessControlEntryService .delete (accessControlEntry );
199
+ accessControlEntryService .delete (ns , accessControlEntry );
162
200
return HttpResponse .noContent ();
163
201
}
164
202
0 commit comments