0
# Authorization Management
1
2
The authorization management components provide the core interfaces and implementations for controlling access to CDAP resources through role-based access control and privilege management.
3
4
## Core Authorization Interface
5
6
### Authorizer
7
8
The main interface that authorization extensions must implement to provide custom authorization logic.
9
10
```java { .api }
11
@Beta
12
interface Authorizer extends PrivilegesFetcher, PrivilegesManager, AuthorizationEnforcer {
13
/**
14
* Initialize the Authorizer with the provided context.
15
*/
16
void initialize(AuthorizationContext context) throws Exception;
17
18
/**
19
* Create a new role.
20
*/
21
void createRole(Role role) throws Exception;
22
23
/**
24
* Drop a role.
25
*/
26
void dropRole(Role role) throws Exception;
27
28
/**
29
* Add a role to the specified Principal.
30
*/
31
void addRoleToPrincipal(Role role, Principal principal) throws Exception;
32
33
/**
34
* Remove a role from the specified Principal.
35
*/
36
void removeRoleFromPrincipal(Role role, Principal principal) throws Exception;
37
38
/**
39
* List all roles for the specified Principal.
40
*/
41
Set<Role> listRoles(Principal principal) throws Exception;
42
43
/**
44
* List all available roles in the system.
45
*/
46
Set<Role> listAllRoles() throws Exception;
47
48
/**
49
* Cleanup method called when the authorizer is destroyed.
50
*/
51
void destroy() throws Exception;
52
}
53
```
54
55
### AuthorizationEnforcer
56
57
Interface for enforcing access control decisions.
58
59
```java { .api }
60
@Beta
61
interface AuthorizationEnforcer {
62
/**
63
* Enforce authorization for a single action.
64
*/
65
void enforce(EntityId entity, Principal principal, Action action) throws Exception;
66
67
/**
68
* Enforce authorization for multiple actions.
69
*/
70
void enforce(EntityId entity, Principal principal, Set<Action> actions) throws Exception;
71
72
/**
73
* Check which entities are visible to the principal.
74
*/
75
Set<? extends EntityId> isVisible(Set<? extends EntityId> entityIds, Principal principal) throws Exception;
76
}
77
```
78
79
### PrivilegesManager
80
81
Interface for managing privileges on entities.
82
83
```java { .api }
84
interface PrivilegesManager {
85
/**
86
* Grant privileges to a principal on an authorizable entity.
87
*/
88
void grant(Authorizable authorizable, Principal principal, Set<Action> actions) throws Exception;
89
90
/**
91
* Revoke specific privileges from a principal on an authorizable entity.
92
*/
93
void revoke(Authorizable authorizable, Principal principal, Set<Action> actions) throws Exception;
94
95
/**
96
* Revoke all privileges on an authorizable entity.
97
*/
98
void revoke(Authorizable authorizable) throws Exception;
99
100
/**
101
* List all privileges for a principal.
102
*/
103
Set<Privilege> listPrivileges(Principal principal) throws Exception;
104
}
105
```
106
107
### PrivilegesFetcher
108
109
Interface for retrieving privilege information.
110
111
```java { .api }
112
interface PrivilegesFetcher {
113
/**
114
* List all privileges for the specified principal.
115
*/
116
Set<Privilege> listPrivileges(Principal principal) throws Exception;
117
}
118
```
119
120
## Base Implementation Classes
121
122
### AbstractAuthorizer
123
124
Abstract base class providing default implementations for lifecycle methods.
125
126
```java { .api }
127
abstract class AbstractAuthorizer implements Authorizer {
128
protected static final Predicate<EntityId> ALLOW_ALL;
129
130
/**
131
* Default no-op initialization.
132
*/
133
void initialize(AuthorizationContext context) throws Exception;
134
135
/**
136
* Default no-op cleanup.
137
*/
138
void destroy() throws Exception;
139
140
/**
141
* Single-action enforcement that delegates to multi-action method.
142
*/
143
void enforce(EntityId entity, Principal principal, Action action) throws Exception;
144
}
145
```
146
147
### NoOpAuthorizer
148
149
No-operation implementation used when authorization is disabled.
150
151
```java { .api }
152
class NoOpAuthorizer extends AbstractAuthorizer {
153
void enforce(EntityId entity, Principal principal, Set<Action> actions) throws Exception;
154
Set<? extends EntityId> isVisible(Set<? extends EntityId> entityIds, Principal principal) throws Exception;
155
void grant(Authorizable authorizable, Principal principal, Set<Action> actions) throws Exception;
156
void revoke(Authorizable authorizable, Principal principal, Set<Action> actions) throws Exception;
157
void revoke(Authorizable authorizable) throws Exception;
158
void createRole(Role role);
159
void dropRole(Role role);
160
void addRoleToPrincipal(Role role, Principal principal);
161
void removeRoleFromPrincipal(Role role, Principal principal);
162
Set<Role> listRoles(Principal principal);
163
Set<Role> listAllRoles();
164
Set<Privilege> listPrivileges(Principal principal);
165
}
166
```
167
168
## Authorization Context
169
170
### AuthorizationContext
171
172
Context interface providing access to CDAP services for authorization extensions.
173
174
```java { .api }
175
interface AuthorizationContext extends DatasetContext, Admin, Transactional,
176
AuthenticationContext, SecureStore {
177
/**
178
* Get extension properties from cdap-site.xml with prefix
179
* security.authorization.extension.config.
180
*/
181
Properties getExtensionProperties();
182
183
// Messaging operations (all throw UnsupportedOperationException)
184
void createTopic(String topic) throws TopicAlreadyExistsException, IOException;
185
void createTopic(String topic, Map<String, String> properties) throws TopicAlreadyExistsException, IOException;
186
Map<String, String> getTopicProperties(String topic) throws TopicNotFoundException, IOException;
187
void updateTopic(String topic, Map<String, String> properties) throws TopicNotFoundException, IOException;
188
void deleteTopic(String topic) throws TopicNotFoundException, IOException;
189
}
190
```
191
192
## Usage Examples
193
194
### Custom Authorization Backend
195
196
```java
197
public class LdapAuthorizer extends AbstractAuthorizer {
198
private LdapConnection ldapConnection;
199
private String baseDn;
200
201
@Override
202
public void initialize(AuthorizationContext context) throws Exception {
203
Properties props = context.getExtensionProperties();
204
String ldapUrl = props.getProperty("ldap.url");
205
String bindDn = props.getProperty("ldap.bind.dn");
206
String bindPassword = props.getProperty("ldap.bind.password");
207
baseDn = props.getProperty("ldap.base.dn");
208
209
ldapConnection = new LdapConnection(ldapUrl, bindDn, bindPassword);
210
}
211
212
@Override
213
public void enforce(EntityId entity, Principal principal, Set<Action> actions)
214
throws Exception {
215
// Query LDAP to check if user has required permissions
216
String userDn = "uid=" + principal.getName() + "," + baseDn;
217
218
for (Action action : actions) {
219
if (!hasLdapPermission(userDn, entity, action)) {
220
throw new UnauthorizedException(principal, action, entity);
221
}
222
}
223
}
224
225
@Override
226
public void grant(Authorizable authorizable, Principal principal, Set<Action> actions)
227
throws Exception {
228
// Add LDAP group membership or attributes
229
String userDn = "uid=" + principal.getName() + "," + baseDn;
230
for (Action action : actions) {
231
String groupDn = buildPermissionGroupDn(authorizable, action);
232
ldapConnection.addUserToGroup(userDn, groupDn);
233
}
234
}
235
236
@Override
237
public Set<Role> listRoles(Principal principal) throws Exception {
238
// Query LDAP groups for user
239
String userDn = "uid=" + principal.getName() + "," + baseDn;
240
return ldapConnection.getUserGroups(userDn)
241
.stream()
242
.map(groupName -> new Role(groupName))
243
.collect(Collectors.toSet());
244
}
245
246
@Override
247
public void destroy() throws Exception {
248
if (ldapConnection != null) {
249
ldapConnection.close();
250
}
251
}
252
253
private boolean hasLdapPermission(String userDn, EntityId entity, Action action) {
254
// Implementation specific to your LDAP schema
255
return false;
256
}
257
258
private String buildPermissionGroupDn(Authorizable authorizable, Action action) {
259
// Build group DN based on your LDAP schema
260
return "cn=" + authorizable.toString() + "-" + action.name() + "," + baseDn;
261
}
262
}
263
```
264
265
### Role-Based Access Control
266
267
```java
268
public class SimpleRoleAuthorizer extends AbstractAuthorizer {
269
private Map<String, Set<Role>> userRoles = new HashMap<>();
270
private Map<Role, Set<Privilege>> rolePrivileges = new HashMap<>();
271
272
@Override
273
public void createRole(Role role) throws Exception {
274
if (rolePrivileges.containsKey(role)) {
275
throw new AlreadyExistsException(role);
276
}
277
rolePrivileges.put(role, new HashSet<>());
278
}
279
280
@Override
281
public void addRoleToPrincipal(Role role, Principal principal) throws Exception {
282
if (!rolePrivileges.containsKey(role)) {
283
throw new NotFoundException(role);
284
}
285
userRoles.computeIfAbsent(principal.getName(), k -> new HashSet<>()).add(role);
286
}
287
288
@Override
289
public void grant(Authorizable authorizable, Principal principal, Set<Action> actions)
290
throws Exception {
291
// If granting to a role, update role privileges
292
if (principal.getType() == PrincipalType.ROLE) {
293
Role role = new Role(principal.getName());
294
Set<Privilege> privileges = rolePrivileges.get(role);
295
if (privileges != null) {
296
for (Action action : actions) {
297
privileges.add(new Privilege(authorizable, action));
298
}
299
}
300
}
301
}
302
303
@Override
304
public void enforce(EntityId entity, Principal principal, Set<Action> actions)
305
throws Exception {
306
Set<Privilege> userPrivileges = getUserPrivileges(principal);
307
308
for (Action action : actions) {
309
boolean hasPermission = userPrivileges.stream()
310
.anyMatch(p -> p.getAction().equals(action) &&
311
entityMatches(p.getAuthorizable(), entity));
312
313
if (!hasPermission) {
314
throw new UnauthorizedException(principal, action, entity);
315
}
316
}
317
}
318
319
private Set<Privilege> getUserPrivileges(Principal principal) {
320
Set<Privilege> privileges = new HashSet<>();
321
Set<Role> roles = userRoles.get(principal.getName());
322
323
if (roles != null) {
324
for (Role role : roles) {
325
Set<Privilege> rolePrivs = rolePrivileges.get(role);
326
if (rolePrivs != null) {
327
privileges.addAll(rolePrivs);
328
}
329
}
330
}
331
332
return privileges;
333
}
334
335
private boolean entityMatches(Authorizable authorizable, EntityId entity) {
336
// Implementation-specific logic to match entities
337
return authorizable.toString().equals(entity.toString());
338
}
339
}