88fba0ba2a03513cbc75c9c402dc7a6f15e0c62f
[moon.git] /
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.aaa.authn.mdsal.store;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import java.util.List;
14 import java.util.concurrent.ExecutionException;
15 import org.opendaylight.aaa.api.IDMStoreException;
16 import org.opendaylight.aaa.api.IDMStoreUtil;
17 import org.opendaylight.aaa.api.SHA256Calculator;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
20 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
23 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
24 import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.Authentication;
25 import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Domain;
26 import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.DomainBuilder;
27 import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.DomainKey;
28 import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Grant;
29 import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.GrantBuilder;
30 import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.GrantKey;
31 import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.Role;
32 import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.RoleBuilder;
33 import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.RoleKey;
34 import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.User;
35 import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.UserBuilder;
36 import org.opendaylight.yang.gen.v1.urn.aaa.yang.authn.claims.rev141029.authentication.UserKey;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * @author Sharon Aicler - saichler@cisco.com
43  *
44  */
45 public class IDMMDSALStore {
46
47     private static final Logger LOG = LoggerFactory.getLogger(IDMMDSALStore.class);
48     private final DataBroker dataBroker;
49
50     public IDMMDSALStore(DataBroker dataBroker) {
51         this.dataBroker = dataBroker;
52     }
53
54     public static final String getString(String aValue, String bValue) {
55         if (aValue != null)
56             return aValue;
57         return bValue;
58     }
59
60     public static final Boolean getBoolean(Boolean aValue, Boolean bValue) {
61         if (aValue != null)
62             return aValue;
63         return bValue;
64     }
65
66     public static boolean waitForSubmit(CheckedFuture<Void, TransactionCommitFailedException> submit) {
67         // This can happen only when testing
68         if (submit == null)
69             return false;
70         while (!submit.isDone() && !submit.isCancelled()) {
71             try {
72                 Thread.sleep(1000);
73             } catch (Exception err) {
74                 LOG.error("Interrupted", err);
75             }
76         }
77         return submit.isCancelled();
78     }
79
80     // Domain methods
81     public Domain writeDomain(Domain domain) {
82         Preconditions.checkNotNull(domain);
83         Preconditions.checkNotNull(domain.getName());
84         Preconditions.checkNotNull(domain.isEnabled());
85         DomainBuilder b = new DomainBuilder();
86         b.setDescription(domain.getDescription());
87         b.setDomainid(domain.getName());
88         b.setEnabled(domain.isEnabled());
89         b.setName(domain.getName());
90         b.setKey(new DomainKey(b.getName()));
91         domain = b.build();
92         InstanceIdentifier<Domain> ID = InstanceIdentifier.create(Authentication.class).child(
93                 Domain.class, new DomainKey(domain.getDomainid()));
94         WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
95         wrt.put(LogicalDatastoreType.CONFIGURATION, ID, domain, true);
96         CheckedFuture<Void, TransactionCommitFailedException> submit = wrt.submit();
97         if (!waitForSubmit(submit)) {
98             return domain;
99         } else {
100             return null;
101         }
102     }
103
104     public Domain readDomain(String domainid) {
105         Preconditions.checkNotNull(domainid);
106         InstanceIdentifier<Domain> ID = InstanceIdentifier.create(Authentication.class).child(
107                 Domain.class, new DomainKey(domainid));
108         ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
109         CheckedFuture<Optional<Domain>, ReadFailedException> read = rot.read(
110                 LogicalDatastoreType.CONFIGURATION, ID);
111         if (read == null) {
112             LOG.error("Failed to read domain from data store");
113             return null;
114         }
115         Optional<Domain> optional = null;
116         try {
117             optional = read.get();
118         } catch (InterruptedException | ExecutionException e1) {
119             LOG.error("Failed to read domain from data store", e1);
120             return null;
121         }
122
123         if (optional == null)
124             return null;
125
126         if (!optional.isPresent())
127             return null;
128
129         return optional.get();
130     }
131
132     public Domain deleteDomain(String domainid) {
133         Preconditions.checkNotNull(domainid);
134         Domain domain = readDomain(domainid);
135         if (domain == null) {
136             LOG.error("Failed to delete domain from data store, unknown domain");
137             return null;
138         }
139         InstanceIdentifier<Domain> ID = InstanceIdentifier.create(Authentication.class).child(
140                 Domain.class, new DomainKey(domainid));
141         WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
142         wrt.delete(LogicalDatastoreType.CONFIGURATION, ID);
143         wrt.submit();
144         return domain;
145     }
146
147     public Domain updateDomain(Domain domain) throws IDMStoreException {
148         Preconditions.checkNotNull(domain);
149         Preconditions.checkNotNull(domain.getDomainid());
150         Domain existing = readDomain(domain.getDomainid());
151         DomainBuilder b = new DomainBuilder();
152         b.setDescription(getString(domain.getDescription(), existing.getDescription()));
153         b.setName(existing.getName());
154         b.setEnabled(getBoolean(domain.isEnabled(), existing.isEnabled()));
155         return writeDomain(b.build());
156     }
157
158     public List<Domain> getAllDomains() {
159         InstanceIdentifier<Authentication> id = InstanceIdentifier.create(Authentication.class);
160         ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
161         CheckedFuture<Optional<Authentication>, ReadFailedException> read = rot.read(
162                 LogicalDatastoreType.CONFIGURATION, id);
163         if (read == null)
164             return null;
165
166         try {
167             if (read.get() == null)
168                 return null;
169             if (read.get().isPresent()) {
170                 Authentication auth = read.get().get();
171                 return auth.getDomain();
172             }
173         } catch (Exception err) {
174             LOG.error("Failed to read domains", err);
175         }
176         return null;
177     }
178
179     public List<Role> getAllRoles() {
180         InstanceIdentifier<Authentication> id = InstanceIdentifier.create(Authentication.class);
181         ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
182         CheckedFuture<Optional<Authentication>, ReadFailedException> read = rot.read(
183                 LogicalDatastoreType.CONFIGURATION, id);
184         if (read == null)
185             return null;
186
187         try {
188             if (read.get() == null)
189                 return null;
190             if (read.get().isPresent()) {
191                 Authentication auth = read.get().get();
192                 return auth.getRole();
193             }
194         } catch (Exception err) {
195             LOG.error("Failed to read domains", err);
196         }
197         return null;
198     }
199
200     public List<User> getAllUsers() {
201         InstanceIdentifier<Authentication> id = InstanceIdentifier.create(Authentication.class);
202         ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
203         CheckedFuture<Optional<Authentication>, ReadFailedException> read = rot.read(
204                 LogicalDatastoreType.CONFIGURATION, id);
205         if (read == null)
206             return null;
207
208         try {
209             if (read.get() == null)
210                 return null;
211             if (read.get().isPresent()) {
212                 Authentication auth = read.get().get();
213                 return auth.getUser();
214             }
215         } catch (Exception err) {
216             LOG.error("Failed to read domains", err);
217         }
218         return null;
219     }
220
221     public List<Grant> getAllGrants() {
222         InstanceIdentifier<Authentication> id = InstanceIdentifier.create(Authentication.class);
223         ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
224         CheckedFuture<Optional<Authentication>, ReadFailedException> read = rot.read(
225                 LogicalDatastoreType.CONFIGURATION, id);
226         if (read == null)
227             return null;
228
229         try {
230             if (read.get() == null)
231                 return null;
232             if (read.get().isPresent()) {
233                 Authentication auth = read.get().get();
234                 return auth.getGrant();
235             }
236         } catch (Exception err) {
237             LOG.error("Failed to read domains", err);
238         }
239         return null;
240     }
241
242     // Role methods
243     public Role writeRole(Role role) {
244         Preconditions.checkNotNull(role);
245         Preconditions.checkNotNull(role.getName());
246         Preconditions.checkNotNull(role.getDomainid());
247         Preconditions.checkNotNull(readDomain(role.getDomainid()));
248         RoleBuilder b = new RoleBuilder();
249         b.setDescription(role.getDescription());
250         b.setRoleid(IDMStoreUtil.createRoleid(role.getName(), role.getDomainid()));
251         b.setKey(new RoleKey(b.getRoleid()));
252         b.setName(role.getName());
253         b.setDomainid(role.getDomainid());
254         role = b.build();
255         InstanceIdentifier<Role> ID = InstanceIdentifier.create(Authentication.class).child(
256                 Role.class, new RoleKey(role.getRoleid()));
257         WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
258         wrt.put(LogicalDatastoreType.CONFIGURATION, ID, role, true);
259         CheckedFuture<Void, TransactionCommitFailedException> submit = wrt.submit();
260         if (!waitForSubmit(submit)) {
261             return role;
262         } else {
263             return null;
264         }
265     }
266
267     public Role readRole(String roleid) {
268         Preconditions.checkNotNull(roleid);
269         InstanceIdentifier<Role> ID = InstanceIdentifier.create(Authentication.class).child(
270                 Role.class, new RoleKey(roleid));
271         ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
272         CheckedFuture<Optional<Role>, ReadFailedException> read = rot.read(
273                 LogicalDatastoreType.CONFIGURATION, ID);
274         if (read == null) {
275             LOG.error("Failed to read role from data store");
276             return null;
277         }
278         Optional<Role> optional = null;
279         try {
280             optional = read.get();
281         } catch (InterruptedException | ExecutionException e1) {
282             LOG.error("Failed to read role from data store", e1);
283             return null;
284         }
285
286         if (optional == null)
287             return null;
288
289         if (!optional.isPresent())
290             return null;
291
292         return optional.get();
293     }
294
295     public Role deleteRole(String roleid) {
296         Preconditions.checkNotNull(roleid);
297         Role role = readRole(roleid);
298         if (role == null) {
299             LOG.error("Failed to delete role from data store, unknown role");
300             return null;
301         }
302         InstanceIdentifier<Role> ID = InstanceIdentifier.create(Authentication.class).child(
303                 Role.class, new RoleKey(roleid));
304         WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
305         wrt.delete(LogicalDatastoreType.CONFIGURATION, ID);
306         wrt.submit();
307         return role;
308     }
309
310     public Role updateRole(Role role) {
311         Preconditions.checkNotNull(role);
312         Preconditions.checkNotNull(role.getRoleid());
313         Role existing = readRole(role.getRoleid());
314         RoleBuilder b = new RoleBuilder();
315         b.setDescription(getString(role.getDescription(), existing.getDescription()));
316         b.setName(existing.getName());
317         b.setDomainid(existing.getDomainid());
318         return writeRole(b.build());
319     }
320
321     // User methods
322     public User writeUser(User user) throws IDMStoreException {
323         Preconditions.checkNotNull(user);
324         Preconditions.checkNotNull(user.getName());
325         Preconditions.checkNotNull(user.getDomainid());
326         Preconditions.checkNotNull(readDomain(user.getDomainid()));
327         UserBuilder b = new UserBuilder();
328         if (user.getSalt() == null) {
329             b.setSalt(SHA256Calculator.generateSALT());
330         } else {
331             b.setSalt(user.getSalt());
332         }
333         b.setUserid(IDMStoreUtil.createUserid(user.getName(), user.getDomainid()));
334         b.setDescription(user.getDescription());
335         b.setDomainid(user.getDomainid());
336         b.setEmail(user.getEmail());
337         b.setEnabled(user.isEnabled());
338         b.setKey(new UserKey(b.getUserid()));
339         b.setName(user.getName());
340         b.setPassword(SHA256Calculator.getSHA256(user.getPassword(), b.getSalt()));
341         user = b.build();
342         InstanceIdentifier<User> ID = InstanceIdentifier.create(Authentication.class).child(
343                 User.class, new UserKey(user.getUserid()));
344         WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
345         wrt.put(LogicalDatastoreType.CONFIGURATION, ID, user, true);
346         CheckedFuture<Void, TransactionCommitFailedException> submit = wrt.submit();
347         if (!waitForSubmit(submit)) {
348             return user;
349         } else {
350             return null;
351         }
352     }
353
354     public User readUser(String userid) {
355         Preconditions.checkNotNull(userid);
356         InstanceIdentifier<User> ID = InstanceIdentifier.create(Authentication.class).child(
357                 User.class, new UserKey(userid));
358         ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
359         CheckedFuture<Optional<User>, ReadFailedException> read = rot.read(
360                 LogicalDatastoreType.CONFIGURATION, ID);
361         if (read == null) {
362             LOG.error("Failed to read user from data store");
363             return null;
364         }
365         Optional<User> optional = null;
366         try {
367             optional = read.get();
368         } catch (InterruptedException | ExecutionException e1) {
369             LOG.error("Failed to read domain from data store", e1);
370             return null;
371         }
372
373         if (optional == null)
374             return null;
375
376         if (!optional.isPresent())
377             return null;
378
379         return optional.get();
380     }
381
382     public User deleteUser(String userid) {
383         Preconditions.checkNotNull(userid);
384         User user = readUser(userid);
385         if (user == null) {
386             LOG.error("Failed to delete user from data store, unknown user");
387             return null;
388         }
389         InstanceIdentifier<User> ID = InstanceIdentifier.create(Authentication.class).child(
390                 User.class, new UserKey(userid));
391         WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
392         wrt.delete(LogicalDatastoreType.CONFIGURATION, ID);
393         wrt.submit();
394         return user;
395     }
396
397     public User updateUser(User user) throws IDMStoreException {
398         Preconditions.checkNotNull(user);
399         Preconditions.checkNotNull(user.getUserid());
400         User existing = readUser(user.getUserid());
401         UserBuilder b = new UserBuilder();
402         b.setName(existing.getName());
403         b.setDomainid(existing.getDomainid());
404         b.setDescription(getString(user.getDescription(), existing.getDescription()));
405         b.setEmail(getString(user.getEmail(), existing.getEmail()));
406         b.setEnabled(getBoolean(user.isEnabled(), existing.isEnabled()));
407         b.setPassword(getString(user.getPassword(), existing.getPassword()));
408         b.setSalt(getString(user.getSalt(), existing.getSalt()));
409         return writeUser(b.build());
410     }
411
412     // Grant methods
413     public Grant writeGrant(Grant grant) throws IDMStoreException {
414         Preconditions.checkNotNull(grant);
415         Preconditions.checkNotNull(grant.getDomainid());
416         Preconditions.checkNotNull(grant.getUserid());
417         Preconditions.checkNotNull(grant.getRoleid());
418         Preconditions.checkNotNull(readDomain(grant.getDomainid()));
419         Preconditions.checkNotNull(readUser(grant.getUserid()));
420         Preconditions.checkNotNull(readRole(grant.getRoleid()));
421         GrantBuilder b = new GrantBuilder();
422         b.setDomainid(grant.getDomainid());
423         b.setRoleid(grant.getRoleid());
424         b.setUserid(grant.getUserid());
425         b.setGrantid(IDMStoreUtil.createGrantid(grant.getUserid(), grant.getDomainid(),
426                 grant.getRoleid()));
427         b.setKey(new GrantKey(b.getGrantid()));
428         grant = b.build();
429         InstanceIdentifier<Grant> ID = InstanceIdentifier.create(Authentication.class).child(
430                 Grant.class, new GrantKey(grant.getGrantid()));
431         WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
432         wrt.put(LogicalDatastoreType.CONFIGURATION, ID, grant, true);
433         CheckedFuture<Void, TransactionCommitFailedException> submit = wrt.submit();
434         if (!waitForSubmit(submit)) {
435             return grant;
436         } else {
437             return null;
438         }
439     }
440
441     public Grant readGrant(String grantid) {
442         Preconditions.checkNotNull(grantid);
443         InstanceIdentifier<Grant> ID = InstanceIdentifier.create(Authentication.class).child(
444                 Grant.class, new GrantKey(grantid));
445         ReadOnlyTransaction rot = dataBroker.newReadOnlyTransaction();
446         CheckedFuture<Optional<Grant>, ReadFailedException> read = rot.read(
447                 LogicalDatastoreType.CONFIGURATION, ID);
448         if (read == null) {
449             LOG.error("Failed to read grant from data store");
450             return null;
451         }
452         Optional<Grant> optional = null;
453         try {
454             optional = read.get();
455         } catch (InterruptedException | ExecutionException e1) {
456             LOG.error("Failed to read domain from data store", e1);
457             return null;
458         }
459
460         if (optional == null)
461             return null;
462
463         if (!optional.isPresent())
464             return null;
465
466         return optional.get();
467     }
468
469     public Grant deleteGrant(String grantid) {
470         Preconditions.checkNotNull(grantid);
471         Grant grant = readGrant(grantid);
472         if (grant == null) {
473             LOG.error("Failed to delete grant from data store, unknown grant");
474             return null;
475         }
476         InstanceIdentifier<Grant> ID = InstanceIdentifier.create(Authentication.class).child(
477                 Grant.class, new GrantKey(grantid));
478         WriteTransaction wrt = dataBroker.newWriteOnlyTransaction();
479         wrt.delete(LogicalDatastoreType.CONFIGURATION, ID);
480         wrt.submit();
481         return grant;
482     }
483 }