SimpleXML.java
001 /*
002  *  Licensed to the Apache Software Foundation (ASF) under one
003  *  or more contributor license agreements.  See the NOTICE file
004  *  distributed with this work for additional information
005  *  regarding copyright ownership.  The ASF licenses this file
006  *  to you under the Apache License, Version 2.0 (the
007  *  "License"); you may not use this file except in compliance
008  *  with the License.  You may obtain a copy of the License at
009  *
010  *    http://www.apache.org/licenses/LICENSE-2.0
011  *
012  *  Unless required by applicable law or agreed to in writing,
013  *  software distributed under the License is distributed on an
014  *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015  *  KIND, either express or implied.  See the License for the
016  *  specific language governing permissions and limitations
017  *  under the License.
018  *
019  *
020  */
021 
022 package org.apache.qpid.server.security.access.plugins;
023 
024 import org.apache.commons.configuration.Configuration;
025 import org.apache.log4j.Logger;
026 import org.apache.qpid.AMQConnectionException;
027 import org.apache.qpid.framing.AMQMethodBody;
028 import org.apache.qpid.framing.AMQShortString;
029 import org.apache.qpid.framing.BasicConsumeBody;
030 import org.apache.qpid.framing.BasicPublishBody;
031 
032 import org.apache.qpid.protocol.AMQConstant;
033 import org.apache.qpid.server.exchange.Exchange;
034 import org.apache.qpid.server.protocol.AMQProtocolSession;
035 import org.apache.qpid.server.queue.AMQQueue;
036 import org.apache.qpid.server.security.access.ACLManager;
037 import org.apache.qpid.server.security.access.ACLPlugin;
038 import org.apache.qpid.server.security.access.ACLPluginFactory;
039 import org.apache.qpid.server.security.access.AccessResult;
040 import org.apache.qpid.server.security.access.Permission;
041 import org.apache.qpid.server.security.access.PrincipalPermissions;
042 import org.apache.qpid.server.security.access.ACLPlugin.AuthzResult;
043 import org.apache.qpid.server.virtualhost.VirtualHost;
044 
045 import java.util.Map;
046 import java.util.concurrent.ConcurrentHashMap;
047 
048 /**
049  * This uses the default
050  */
051 public class SimpleXML implements ACLPlugin
052 {
053     public static final ACLPluginFactory FACTORY = new ACLPluginFactory()
054     {
055         public boolean supportsTag(String name)
056         {
057             return name.startsWith("access_control_list");
058         }
059 
060         public ACLPlugin newInstance(Configuration config)
061         {
062             SimpleXML plugin = new SimpleXML();
063             plugin.setConfiguration(config);
064             return plugin;
065         }
066     };
067     
068     private Map<String, PrincipalPermissions> _users;
069     private final AccessResult GRANTED = new AccessResult(this, AccessResult.AccessStatus.GRANTED);
070 
071     public SimpleXML()
072     {
073         _users = new ConcurrentHashMap<String, PrincipalPermissions>();
074     }
075 
076     public void setConfiguration(Configuration config)
077     {
078         processConfig(config);
079     }
080 
081     private void processConfig(Configuration config)
082     {
083         processPublish(config);
084 
085         processConsume(config);
086 
087         processCreate(config);
088     }
089 
090     /**
091      * Publish format takes Exchange + Routing Key Pairs
092      
093      @param config
094      *            XML Configuration
095      */
096     private void processPublish(Configuration config)
097     {
098         Configuration publishConfig = config.subset("access_control_list.publish");
099 
100         // Process users that have full publish permission
101         String[] users = publishConfig.getStringArray("users.user");
102 
103         for (String user : users)
104         {
105             grant(Permission.PUBLISH, user);
106         }
107 
108         // Process exchange limited users
109         int exchangeCount = 0;
110         Configuration exchangeConfig = publishConfig.subset("exchanges.exchange(" + exchangeCount + ")");
111 
112         while (!exchangeConfig.isEmpty())
113         {
114             // Get Exchange Name
115             AMQShortString exchangeName = new AMQShortString(exchangeConfig.getString("name"));
116 
117             // Get Routing Keys
118             int keyCount = 0;
119             Configuration routingkeyConfig = exchangeConfig.subset("routing_keys.routing_key(" + keyCount + ")");
120 
121             while (!routingkeyConfig.isEmpty())
122             {
123                 // Get RoutingKey Value
124                 AMQShortString routingKeyValue = new AMQShortString(routingkeyConfig.getString("value"));
125 
126                 // Apply Exchange + RoutingKey permissions to Users
127                 users = routingkeyConfig.getStringArray("users.user");
128                 for (String user : users)
129                 {
130                     grant(Permission.PUBLISH, user, exchangeName, routingKeyValue);
131                 }
132 
133                 // Apply permissions to Groups
134 
135                 // Check for more configs
136                 keyCount++;
137                 routingkeyConfig = exchangeConfig.subset("routing_keys.routing_key(" + keyCount + ")");
138             }
139 
140             // Apply Exchange wide permissions to Users
141             users = exchangeConfig.getStringArray("exchange(" + exchangeCount + ").users.user");
142 
143             for (String user : users)
144             {
145                 grant(Permission.PUBLISH, user, exchangeName);
146             }
147 
148             // Apply permissions to Groups
149             exchangeCount++;
150             exchangeConfig = publishConfig.subset("exchanges.exchange(" + exchangeCount + ")");
151         }
152     }
153 
154     private void grant(Permission permission, String user, Object... parameters)
155     {
156         PrincipalPermissions permissions = _users.get(user);
157 
158         if (permissions == null)
159         {
160             permissions = new PrincipalPermissions(user);
161         }
162 
163         _users.put(user, permissions);
164         permissions.grant(permission, parameters);
165     }
166 
167     private void processConsume(Configuration config)
168     {
169         Configuration consumeConfig = config.subset("access_control_list.consume");
170 
171         // Process queue limited users
172         int queueCount = 0;
173         Configuration queueConfig = consumeConfig.subset("queues.queue(" + queueCount + ")");
174 
175         while (!queueConfig.isEmpty())
176         {
177             // Get queue Name
178             AMQShortString queueName = new AMQShortString(queueConfig.getString("name"));
179             // if there is no name then there may be a temporary element
180             boolean temporary = queueConfig.containsKey("temporary");
181             boolean ownQueues = queueConfig.containsKey("own_queues");
182 
183             // Process permissions for this queue
184             String[] users = queueConfig.getStringArray("users.user");
185             for (String user : users)
186             {
187                 grant(Permission.CONSUME, user, queueName, temporary, ownQueues);
188             }
189 
190             // See if we have another config
191             queueCount++;
192             queueConfig = consumeConfig.subset("queues.queue(" + queueCount + ")");
193         }
194 
195         // Process users that have full consume permission
196         String[] users = consumeConfig.getStringArray("users.user");
197 
198         for (String user : users)
199         {
200             grant(Permission.CONSUME, user);
201         }
202     }
203 
204     private void processCreate(Configuration config)
205     {
206         Configuration createConfig = config.subset("access_control_list.create");
207 
208         // Process create permissions for queue creation
209         int queueCount = 0;
210         Configuration queueConfig = createConfig.subset("queues.queue(" + queueCount + ")");
211 
212         while (!queueConfig.isEmpty())
213         {
214             // Get queue Name
215             AMQShortString queueName = new AMQShortString(queueConfig.getString("name"));
216 
217             // if there is no name then there may be a temporary element
218             boolean temporary = queueConfig.containsKey("temporary");
219 
220             int exchangeCount = 0;
221             Configuration exchangeConfig = queueConfig.subset("exchanges.exchange(" + exchangeCount + ")");
222 
223             while (!exchangeConfig.isEmpty())
224             {
225 
226                 AMQShortString exchange = new AMQShortString(exchangeConfig.getString("name"));
227                 AMQShortString routingKey = new AMQShortString(exchangeConfig.getString("routing_key"));
228 
229                 // Process permissions for this queue
230                 String[] users = exchangeConfig.getStringArray("users.user");
231                 for (String user : users)
232                 {
233                     grant(Permission.CREATEEXCHANGE, user, exchange);
234                     grant(Permission.CREATEQUEUE, user, temporary, (queueName.equals(""null : queueName)(exchange
235                             .equals(""null : exchange)(routingKey.equals(""null : routingKey));
236                 }
237 
238                 // See if we have another config
239                 exchangeCount++;
240                 exchangeConfig = queueConfig.subset("exchanges.exchange(" + exchangeCount + ")");
241             }
242 
243             // Process users that are not bound to an exchange
244             String[] users = queueConfig.getStringArray("users.user");
245 
246             for (String user : users)
247             {
248                 grant(Permission.CREATEQUEUE, user, temporary, queueName);
249             }
250 
251             // See if we have another config
252             queueCount++;
253             queueConfig = createConfig.subset("queues.queue(" + queueCount + ")");
254         }
255 
256         // Process create permissions for exchange creation
257         int exchangeCount = 0;
258         Configuration exchangeConfig = createConfig.subset("exchanges.exchange(" + exchangeCount + ")");
259 
260         while (!exchangeConfig.isEmpty())
261         {
262             AMQShortString exchange = new AMQShortString(exchangeConfig.getString("name"));
263             AMQShortString clazz = new AMQShortString(exchangeConfig.getString("class"));
264 
265             // Process permissions for this queue
266             String[] users = exchangeConfig.getStringArray("users.user");
267             for (String user : users)
268             {
269                 grant(Permission.CREATEEXCHANGE, user, exchange, clazz);
270             }
271 
272             // See if we have another config
273             exchangeCount++;
274             exchangeConfig = queueConfig.subset("exchanges.exchange(" + exchangeCount + ")");
275         }
276 
277         // Process users that have full create permission
278         String[] users = createConfig.getStringArray("users.user");
279 
280         for (String user : users)
281         {
282             grant(Permission.CREATEEXCHANGE, user);
283             grant(Permission.CREATEQUEUE, user);
284         }
285 
286     }
287 
288     public String getPluginName()
289     {
290         return "Simple";
291     }
292 
293     public AuthzResult authoriseBind(AMQProtocolSession session, Exchange exch, AMQQueue queue, AMQShortString routingKey)
294     {
295         PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
296         if (principalPermissions == null)
297         {
298             return AuthzResult.DENIED;
299         }
300         else
301         {
302             return principalPermissions.authorise(Permission.BIND, null, exch, queue, routingKey);
303         }
304     }
305 
306     public AuthzResult authoriseConnect(AMQProtocolSession session, VirtualHost virtualHost)
307     {
308         PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
309         if (principalPermissions == null)
310         {
311             return AuthzResult.DENIED;
312         }
313         else
314         {
315             return principalPermissions.authorise(Permission.ACCESS);
316         }
317     }
318 
319     public AuthzResult authoriseConsume(AMQProtocolSession session, boolean noAck, AMQQueue queue)
320     {
321         PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
322         if (principalPermissions == null)
323         {
324             return AuthzResult.DENIED;
325         }
326         else
327         {
328             return principalPermissions.authorise(Permission.CONSUME, queue);
329         }
330     }
331 
332     public AuthzResult authoriseConsume(AMQProtocolSession session, boolean exclusive, boolean noAck, boolean noLocal,
333             boolean nowait, AMQQueue queue)
334     {
335         return authoriseConsume(session, noAck, queue);
336     }
337 
338     public AuthzResult authoriseCreateExchange(AMQProtocolSession session, boolean autoDelete, boolean durable,
339             AMQShortString exchangeName, boolean internal, boolean nowait, boolean passive, AMQShortString exchangeType)
340     {
341         PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
342         if (principalPermissions == null)
343         {
344             return AuthzResult.DENIED;
345         }
346         else
347         {
348             return principalPermissions.authorise(Permission.CREATEEXCHANGE, exchangeName);
349         }
350     }
351 
352     public AuthzResult authoriseCreateQueue(AMQProtocolSession session, boolean autoDelete, boolean durable, boolean exclusive,
353             boolean nowait, boolean passive, AMQShortString queue)
354     {
355         PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
356         if (principalPermissions == null)
357         {
358             return AuthzResult.DENIED;
359         }
360         else
361         {
362             return principalPermissions.authorise(Permission.CREATEQUEUE, autoDelete, queue);
363         }
364     }
365 
366     public AuthzResult authoriseDelete(AMQProtocolSession session, AMQQueue queue)
367     {
368         PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
369         if (principalPermissions == null)
370         {
371             return AuthzResult.DENIED;
372         }
373         else
374         {
375             return principalPermissions.authorise(Permission.DELETE);
376         }
377     }
378 
379     public AuthzResult authoriseDelete(AMQProtocolSession session, Exchange exchange)
380     {
381         PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
382         if (principalPermissions == null)
383         {
384             return AuthzResult.DENIED;
385         }
386         else
387         {
388             return principalPermissions.authorise(Permission.DELETE);
389         }
390     }
391 
392     public AuthzResult authorisePublish(AMQProtocolSession session, boolean immediate, boolean mandatory,
393             AMQShortString routingKey, Exchange e)
394     {
395         PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
396         if (principalPermissions == null)
397         {
398             return AuthzResult.DENIED;
399         }
400         else
401         {
402             return principalPermissions.authorise(Permission.PUBLISH, e, routingKey);
403         }
404     }
405 
406     public AuthzResult authorisePurge(AMQProtocolSession session, AMQQueue queue)
407     {
408         PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
409         if (principalPermissions == null)
410         {
411             return AuthzResult.DENIED;
412         }
413         else
414         {
415             return principalPermissions.authorise(Permission.PURGE);
416         }
417     }
418 
419     public AuthzResult authoriseUnbind(AMQProtocolSession session, Exchange exch, AMQShortString routingKey, AMQQueue queue)
420     {
421         PrincipalPermissions principalPermissions = _users.get(session.getAuthorizedID().getName());
422         if (principalPermissions == null)
423         {
424             return AuthzResult.DENIED;
425         }
426         else
427         {
428             return principalPermissions.authorise(Permission.UNBIND);
429         }
430     }
431 
432 }