Merge "Fix issues related to checkstyle enforcement for module aaa-authn"
[aaa.git] / aaa-authn / src / main / java / org / opendaylight / aaa / ClientManager.java
1 /*
2  * Copyright (c) 2014 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;
10
11 import java.util.Dictionary;
12 import java.util.HashMap;
13 import java.util.Hashtable;
14 import java.util.Map;
15 import java.util.concurrent.ConcurrentHashMap;
16 import org.apache.felix.dm.Component;
17 import org.opendaylight.aaa.api.AuthenticationException;
18 import org.opendaylight.aaa.api.ClientService;
19 import org.osgi.service.cm.ConfigurationException;
20 import org.osgi.service.cm.ManagedService;
21
22 /**
23  * A configuration-based client manager.
24  *
25  * @author liemmn
26  *
27  */
28 public class ClientManager implements ClientService, ManagedService {
29     static final String CLIENTS = "authorizedClients";
30     private static final String CLIENTS_FORMAT_ERR =
31             "Clients are space-delimited in the form of <client_id>:<client_secret>";
32     private static final String UNAUTHORIZED_CLIENT_ERR = "Unauthorized client";
33
34     // Defaults (needed only for non-Karaf deployments)
35     protected static final Dictionary<String, String> DEFAULTS = new Hashtable<>();
36
37     static {
38         DEFAULTS.put(CLIENTS, "dlux:secrete");
39     }
40
41     private final Map<String, String> clients = new ConcurrentHashMap<>();
42
43     // This should be a singleton
44     ClientManager() {
45     }
46
47     // Called by DM when all required dependencies are satisfied.
48     void init(Component component) throws ConfigurationException {
49         reconfig(DEFAULTS);
50     }
51
52     @Override
53     public void validate(String clientId, String clientSecret) throws AuthenticationException {
54         // TODO: Post-Helium, we will support a CRUD API
55         if (!clients.containsKey(clientId)) {
56             throw new AuthenticationException(UNAUTHORIZED_CLIENT_ERR);
57         }
58         if (!clients.get(clientId).equals(clientSecret)) {
59             throw new AuthenticationException(UNAUTHORIZED_CLIENT_ERR);
60         }
61     }
62
63     @Override
64     public void updated(Dictionary<String, ?> props) throws ConfigurationException {
65         if (props == null) {
66             props = DEFAULTS;
67         }
68         reconfig(props);
69     }
70
71     // Reconfigure the client map...
72     @SuppressWarnings({"rawtypes","checkstyle:IllegalCatch"})
73     private void reconfig(Dictionary props)
74             throws ConfigurationException {
75         try {
76             String authorizedClients = (String) props.get(CLIENTS);
77             Map<String, String> newClients = new HashMap<>();
78             if (authorizedClients != null) {
79                 for (String client : authorizedClients.split(" ")) {
80                     String[] splitClient = client.split(":");
81                     newClients.put(splitClient[0], splitClient[1]);
82                 }
83             }
84             clients.clear();
85             clients.putAll(newClients);
86         } catch (Throwable t) {
87             throw new ConfigurationException(null, CLIENTS_FORMAT_ERR);
88         }
89     }
90 }