92d3a59cbf493d1c61a4ac60ab5a9abdd7484e06
[aaa.git] / aaa-idmlight / src / main / java / org / opendaylight / aaa / idm / IdmLightProxy.java
1 /*
2  * Copyright (c) 2014, 2015 Hewlett-Packard Development Company, L.P. 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
9 package org.opendaylight.aaa.idm;
10
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.concurrent.ConcurrentHashMap;
15
16 import org.opendaylight.aaa.ClaimBuilder;
17 import org.opendaylight.aaa.api.AuthenticationException;
18 import org.opendaylight.aaa.api.Claim;
19 import org.opendaylight.aaa.api.CredentialAuth;
20 import org.opendaylight.aaa.api.IDMStoreException;
21 import org.opendaylight.aaa.api.IIDMStore;
22 import org.opendaylight.aaa.api.IdMService;
23 import org.opendaylight.aaa.api.PasswordCredentials;
24 import org.opendaylight.aaa.api.SHA256Calculator;
25 import org.opendaylight.aaa.api.model.Domain;
26 import org.opendaylight.aaa.api.model.Grant;
27 import org.opendaylight.aaa.api.model.Grants;
28 import org.opendaylight.aaa.api.model.Role;
29 import org.opendaylight.aaa.api.model.User;
30 import org.opendaylight.aaa.api.model.Users;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 import com.google.common.base.Preconditions;
35
36 /**
37  * An OSGi proxy for the IdmLight server.
38  *
39  */
40 public class IdmLightProxy implements CredentialAuth<PasswordCredentials>,IdMService {
41
42     private static Logger logger = LoggerFactory.getLogger(IdmLightProxy.class);
43     private static Map<String, Map<PasswordCredentials, Claim>> claimCache = new ConcurrentHashMap<>();
44     static {
45         claimCache.put(IIDMStore.DEFAULT_DOMAIN, new ConcurrentHashMap<PasswordCredentials, Claim>());
46     }
47
48     @Override
49     public Claim authenticate(PasswordCredentials creds) {
50         Preconditions.checkNotNull(creds);
51         Preconditions.checkNotNull(creds.username());
52         Preconditions.checkNotNull(creds.password());
53         String domain = creds.domain() == null  ? IIDMStore.DEFAULT_DOMAIN : creds.domain();
54         // FIXME: Add cache invalidation
55         Map<PasswordCredentials, Claim> cache = claimCache.get(domain);
56         if (cache == null) {
57             cache = new ConcurrentHashMap<PasswordCredentials, Claim>();
58             claimCache.put(domain, cache);
59         }
60         Claim claim = cache.get(creds);
61         if (claim == null) {
62             synchronized (claimCache) {
63                 claim = cache.get(creds);
64                 if (claim == null) {
65                     claim = dbAuthenticate(creds);
66                     if (claim != null) {
67                         cache.put(creds, claim);
68                     }
69                 }
70             }
71         }
72         return claim;
73     }
74
75     public static synchronized void clearClaimCache() {
76         for (Map<PasswordCredentials, Claim> cache : claimCache.values()) {
77             cache.clear();
78         }
79     }
80
81     private static Claim dbAuthenticate(PasswordCredentials creds) {
82         Domain domain=null;
83         User user=null;
84         String credsDomain = creds.domain() == null ? IIDMStore.DEFAULT_DOMAIN : creds.domain();
85         // check to see domain exists
86         // TODO: ensure domain names are unique change to 'getDomain'
87         debug("get domain");
88         try {
89             domain = ServiceLocator.INSTANCE.getStore().readDomain(credsDomain);
90             if(domain==null){
91                 throw new AuthenticationException("Domain :" + credsDomain + " does not exist");
92             }
93         } catch (IDMStoreException e) {
94             throw new AuthenticationException("Error while fetching domain",e);
95         }
96
97         // check to see user exists and passes cred check
98         try {
99            debug("check user / pwd");
100            Users users = ServiceLocator.INSTANCE.getStore().getUsers(creds.username(), credsDomain);
101            List<User> userList = users.getUsers();
102            if (userList.size()==0) {
103               throw new AuthenticationException("User :" + creds.username() + " does not exist in domain "+credsDomain);
104            }
105            user = userList.get(0);
106            if (!SHA256Calculator.getSHA256(creds.password(),user.getSalt()).equals(user.getPassword())) {
107               throw new AuthenticationException("UserName / Password not found");
108            }
109
110            // get all grants & roles for this domain and user
111            debug("get grants");
112            List<String> roles = new ArrayList<String>();
113            Grants grants = ServiceLocator.INSTANCE.getStore().getGrants(domain.getDomainid(),user.getUserid());
114            List<Grant> grantList = grants.getGrants();
115            for (int z=0;z<grantList.size();z++) {
116               Grant grant = grantList.get(z);
117               Role role = ServiceLocator.INSTANCE.getStore().readRole(grant.getRoleid());
118               roles.add(role.getName());
119            }
120
121            // build up the claim
122            debug("build a claim");
123            ClaimBuilder claim = new ClaimBuilder();
124            claim.setUserId(user.getUserid().toString());
125            claim.setUser(creds.username());
126            claim.setDomain(credsDomain);
127            for (int z=0;z<roles.size();z++) {
128               claim.addRole(roles.get(z));
129            }
130            return claim.build();
131         }
132         catch (IDMStoreException se) {
133            throw new AuthenticationException("idm data store exception :" + se.toString() + se);
134         }
135     }
136
137     @Override
138     public List<String> listDomains(String userId) {
139         debug("list Domains for userId:" + userId);
140         List<String> domains = new ArrayList<String>();
141         try {
142            Grants grants = ServiceLocator.INSTANCE.getStore().getGrants(userId);
143            List<Grant> grantList = grants.getGrants();
144            for (int z=0;z<grantList.size();z++) {
145               Grant grant = grantList.get(z);
146               Domain domain = ServiceLocator.INSTANCE.getStore().readDomain(grant.getDomainid());
147               domains.add(domain.getName());
148            }
149            return domains;
150         }
151         catch (IDMStoreException se) {
152            logger.warn("error getting domains " , se.toString(), se);
153            return domains;
154         }
155
156     }
157
158     @Override
159     public List<String> listRoles(String userId, String domainName) {
160         debug("listRoles");
161         List<String> roles = new ArrayList<String>();
162
163         try {
164            // find domain name for specied domain name
165             String did = null;
166             try {
167                 Domain domain = ServiceLocator.INSTANCE.getStore().readDomain(domainName);
168                 if(domain==null){
169                     debug("DomainName: " + domainName + " Not found!");
170                     return roles;
171                 }
172                 did = domain.getDomainid();
173             } catch (IDMStoreException e) {
174                 return roles;
175             }
176
177            // find all grants for uid and did
178            Grants grants = ServiceLocator.INSTANCE.getStore().getGrants(did,userId);
179            List<Grant> grantList = grants.getGrants();
180            for (int z=0;z<grantList.size();z++) {
181               Grant grant = grantList.get(z);
182               Role role = ServiceLocator.INSTANCE.getStore().readRole(grant.getRoleid());
183               roles.add(role.getName());
184            }
185
186            return roles;
187         }
188         catch (IDMStoreException se) {
189            logger.warn("error getting roles " , se.toString(), se);
190            return roles;
191         }
192     }
193
194     private static final void debug(String msg) {
195         if (logger.isDebugEnabled()) {
196             logger.debug(msg);
197         }
198     }
199 }
200