001 /*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 *
020 */
021 package org.apache.qpid.server.security.auth.database;
022
023 import java.io.FileNotFoundException;
024 import java.io.IOException;
025 import java.lang.reflect.Method;
026 import java.util.HashMap;
027 import java.util.List;
028 import java.util.Map;
029
030 import org.apache.commons.configuration.Configuration;
031 import org.apache.commons.configuration.ConfigurationException;
032
033 import org.apache.log4j.Logger;
034
035 import org.apache.qpid.configuration.PropertyUtils;
036 import org.apache.qpid.configuration.PropertyException;
037 import org.apache.qpid.server.configuration.ServerConfiguration;
038 import org.apache.qpid.server.registry.ApplicationRegistry;
039 import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
040 import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager;
041 import org.apache.qpid.server.security.access.management.AMQUserManagementMBean;
042 import org.apache.qpid.AMQException;
043
044 import javax.management.JMException;
045
046 public class ConfigurationFilePrincipalDatabaseManager implements PrincipalDatabaseManager
047 {
048 private static final Logger _logger = Logger.getLogger(ConfigurationFilePrincipalDatabaseManager.class);
049
050 Map<String, PrincipalDatabase> _databases;
051
052 public ConfigurationFilePrincipalDatabaseManager(ServerConfiguration _configuration) throws Exception
053 {
054 _logger.info("Initialising PrincipleDatabase authentication manager");
055 _databases = initialisePrincipalDatabases(_configuration);
056 }
057
058 private Map<String, PrincipalDatabase> initialisePrincipalDatabases(ServerConfiguration _configuration) throws Exception
059 {
060 List<String> databaseNames = _configuration.getPrincipalDatabaseNames();
061 List<String> databaseClasses = _configuration.getPrincipalDatabaseClass();
062 Map<String, PrincipalDatabase> databases = new HashMap<String, PrincipalDatabase>();
063
064 if (databaseNames.size() == 0)
065 {
066 _logger.warn("No Principal databases specified. Broker running with NO AUTHENTICATION");
067 }
068
069 for (int i = 0; i < databaseNames.size(); i++)
070 {
071 Object o;
072 try
073 {
074 o = Class.forName(databaseClasses.get(i)).newInstance();
075 }
076 catch (Exception e)
077 {
078 throw new Exception("Error initialising principal database: " + e, e);
079 }
080
081 if (!(o instanceof PrincipalDatabase))
082 {
083 throw new Exception("Principal databases must implement the PrincipalDatabase interface");
084 }
085
086 initialisePrincipalDatabase((PrincipalDatabase) o, _configuration, i);
087
088 String name = databaseNames.get(i);
089 if ((name == null) || (name.length() == 0))
090 {
091 throw new Exception("Principal database names must have length greater than or equal to one character");
092 }
093
094 PrincipalDatabase pd = databases.get(name);
095 if (pd != null)
096 {
097 throw new Exception("Duplicate principal database name not permitted");
098 }
099
100 _logger.info("Initialised principal database '" + name + "' successfully");
101 databases.put(name, (PrincipalDatabase) o);
102 }
103
104 return databases;
105 }
106
107 private void initialisePrincipalDatabase(PrincipalDatabase principalDatabase, ServerConfiguration _configuration, int index)
108 throws FileNotFoundException, ConfigurationException
109 {
110 List<String> argumentNames = _configuration.getPrincipalDatabaseAttributeNames(index);
111 List<String> argumentValues = _configuration.getPrincipalDatabaseAttributeValues(index);
112 for (int i = 0; i < argumentNames.size(); i++)
113 {
114 String argName = argumentNames.get(i);
115 if ((argName == null) || (argName.length() == 0))
116 {
117 throw new ConfigurationException("Argument names must have length >= 1 character");
118 }
119
120 if (Character.isLowerCase(argName.charAt(0)))
121 {
122 argName = Character.toUpperCase(argName.charAt(0)) + argName.substring(1);
123 }
124
125 String methodName = "set" + argName;
126 Method method = null;
127 try
128 {
129 method = principalDatabase.getClass().getMethod(methodName, String.class);
130 }
131 catch (Exception e)
132 {
133 // do nothing.. as on error method will be null
134 }
135
136 if (method == null)
137 {
138 throw new ConfigurationException("No method " + methodName + " found in class "
139 + principalDatabase.getClass()
140 + " hence unable to configure principal database. The method must be public and "
141 + "have a single String argument with a void return type");
142 }
143
144 try
145 {
146 method.invoke(principalDatabase, PropertyUtils.replaceProperties(argumentValues.get(i)));
147 }
148 catch (Exception ite)
149 {
150 if (ite instanceof ConfigurationException)
151 {
152 throw(ConfigurationException) ite;
153 }
154 else
155 {
156 throw new ConfigurationException(ite.getMessage(), ite);
157 }
158 }
159 }
160 }
161
162 public Map<String, PrincipalDatabase> getDatabases()
163 {
164 return _databases;
165 }
166
167 public void initialiseManagement(ServerConfiguration config) throws ConfigurationException
168 {
169 try
170 {
171 AMQUserManagementMBean _mbean = new AMQUserManagementMBean();
172
173 List<String> principalDBs = config.getManagementPrincipalDBs();
174
175 if (principalDBs.size() == 0)
176 {
177 throw new ConfigurationException("No principal-database specified for jmx security");
178 }
179
180 String databaseName = principalDBs.get(0);
181
182 PrincipalDatabase database = getDatabases().get(databaseName);
183
184 if (database == null)
185 {
186 throw new ConfigurationException("Principal-database '" + databaseName + "' not found");
187 }
188
189 _mbean.setPrincipalDatabase(database);
190
191 List<String> jmxaccesslist = config.getManagementAccessList();
192
193 if (jmxaccesslist.size() == 0)
194 {
195 throw new ConfigurationException("No access control files specified for jmx security");
196 }
197
198 String jmxaccesssFile = null;
199
200 try
201 {
202 jmxaccesssFile = PropertyUtils.replaceProperties(jmxaccesslist.get(0));
203 }
204 catch (PropertyException e)
205 {
206 throw new ConfigurationException("Unable to parse access control filename '" + jmxaccesssFile + "'");
207 }
208
209 try
210 {
211 _mbean.setAccessFile(jmxaccesssFile);
212 }
213 catch (IOException e)
214 {
215 _logger.warn("Unable to load access file:" + jmxaccesssFile);
216 }
217
218 try
219 {
220 _mbean.register();
221 }
222 catch (AMQException e)
223 {
224 _logger.warn("Unable to register user management MBean");
225 }
226 }
227 catch (JMException e)
228 {
229 _logger.warn("User management disabled as unable to create MBean:" + e);
230 }
231 }
232 }
|