001 /**
002 *
003 * Copyright 2004 Hiram Chirino
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 **/
018 package org.activemq.security.jassjacc;
019
020 import java.io.IOException;
021 import java.util.ArrayList;
022 import java.util.Arrays;
023 import java.util.Enumeration;
024 import java.util.HashMap;
025 import java.util.HashSet;
026 import java.util.Iterator;
027 import java.util.List;
028 import java.util.Properties;
029 import java.util.regex.Matcher;
030 import java.util.regex.Pattern;
031
032 import org.activemq.message.ActiveMQQueue;
033 import org.activemq.message.ActiveMQTopic;
034
035 /**
036 * Parses a Properties object into a set of {@see org.activemq.security.jassjacc.BrokerSecurityConfig} and
037 * {@see org.activemq.security.jassjacc.DestinationSecurityConfig} objects that can be used to
038 * secure the ActiveMQ broker.
039 *
040 * Sample properties configuration:
041 * <pre>
042 *
043 * # Secure a connection the the 'localhost' broker
044 * connect.roles=admins,traders,brokers,guests
045 *
046 * # Secure the TEST_TOPIC topic.
047 * topic.T1.names=TEST_TOPIC
048 * topic.T1.consume.roles=traders
049 * topic.T1.produce.roles=traders,brokers
050 * topic.T1.send.roles=traders,brokers
051 *
052 * # You can also secure more than one destination in one go.
053 * queue.Q1.names=TEST_QUEUE,A_QUEUE,B_QUEUE
054 * queue.Q1.consume.roles=traders
055 * queue.Q1.produce.roles=traders,brokers
056 * queue.Q1.send.roles=traders,brokers
057 *
058 * </pre>
059 *
060 *
061 * @version $Revision: 1.1.1.1 $
062 */
063 public class PropertiesConfigLoader {
064
065 HashMap destinationMap = new HashMap();
066 BrokerSecurityConfig brokerSecurityConfig = new BrokerSecurityConfig();
067
068 public PropertiesConfigLoader(String brokerName, Properties props) throws IOException {
069
070 brokerSecurityConfig.setBrokerName(brokerName);
071 Pattern brokerConnectRoles = Pattern.compile("^connect\\.roles$");
072 Pattern destNames = Pattern.compile("^(queue|topic)\\.([^\\.]+)\\.names$");
073 Pattern destConsumeRoles = Pattern.compile("^(queue|topic)\\.([^\\.]+)\\.consume\\.roles$");
074 Pattern destProduceRoles = Pattern.compile("^(queue|topic)\\.([^\\.]+)\\.produce\\.roles$");
075 Pattern destSendRoles = Pattern.compile("^(queue|topic)\\.([^\\.]+)\\.send\\.roles$");
076
077 Matcher matcher;
078 Enumeration enumeration;
079
080 enumeration = props.propertyNames();
081 while (enumeration.hasMoreElements()) {
082 String prop = (String) enumeration.nextElement();
083 if ((matcher=brokerConnectRoles.matcher(prop)).matches()) {
084 String[] roles = trim(props.getProperty(prop).split("\\,"));
085 brokerSecurityConfig.setConnectRoles(new HashSet(Arrays.asList(roles)));
086 } else if ((matcher=destNames.matcher(prop)).matches()) {
087 String type = matcher.group(1);
088 String dest = matcher.group(2);
089 setDestNames( type, dest, trim(props.getProperty(prop).split("\\,")) );
090 }
091 }
092
093 enumeration = props.propertyNames();
094 while (enumeration.hasMoreElements()) {
095 String prop = (String) enumeration.nextElement();
096 if ((matcher=destConsumeRoles.matcher(prop)).matches()) {
097 String type = matcher.group(1);
098 String dest = matcher.group(2);
099 setDestConsumeRoles( type, dest, trim(props.getProperty(prop).split("\\,")) );
100 } else if ((matcher=destProduceRoles.matcher(prop)).matches()) {
101 String type = matcher.group(1);
102 String dest = matcher.group(2);
103 setDestProduceRoles( type, dest, trim(props.getProperty(prop).split("\\,")) );
104 } else if ((matcher=destSendRoles.matcher(prop)).matches()) {
105 String type = matcher.group(1);
106 String dest = matcher.group(2);
107 setDestSendRoles( type, dest, trim(props.getProperty(prop).split("\\,")) );
108 }
109 }
110
111 }
112
113 private void setDestSendRoles(String type, String dest, String[] roles) throws IOException {
114 List configs = getDestConfig(type, dest);
115 for (Iterator iter = configs.iterator(); iter.hasNext();) {
116 DestinationSecurityConfig config = (DestinationSecurityConfig) iter.next();
117 config.setProduceRoles(new HashSet(Arrays.asList(roles)));
118 }
119 }
120
121 private void setDestProduceRoles(String type, String dest, String[] roles) throws IOException {
122 List configs = getDestConfig(type, dest);
123 for (Iterator iter = configs.iterator(); iter.hasNext();) {
124 DestinationSecurityConfig config = (DestinationSecurityConfig) iter.next();
125 config.setProduceRoles(new HashSet(Arrays.asList(roles)));
126 }
127 }
128
129 private void setDestConsumeRoles(String type, String dest, String[] roles) throws IOException {
130 List configs = getDestConfig(type, dest);
131 for (Iterator iter = configs.iterator(); iter.hasNext();) {
132 DestinationSecurityConfig config = (DestinationSecurityConfig) iter.next();
133 config.setConsumeRoles(new HashSet(Arrays.asList(roles)));
134 }
135 }
136
137 private List getDestConfig(String type, String dest) throws IOException {
138 List rc = (List) destinationMap.get(type+":"+dest);
139 if( rc==null ) {
140 throw new IOException("Expected property not found: "+type+"."+dest+".names");
141 }
142 return rc;
143 }
144
145 private void setDestNames(String type, String dest, String[] names) throws IOException {
146 ArrayList list = new ArrayList();
147 for (int i = 0; i < names.length; i++) {
148 DestinationSecurityConfig config = new DestinationSecurityConfig();
149 config.setBrokerName( brokerSecurityConfig.getBrokerName() );
150 if( "queue".equals(type) ) {
151 config.setDestination(new ActiveMQQueue(dest));
152 } else {
153 config.setDestination(new ActiveMQTopic(dest));
154 }
155 list.add(config);
156 }
157 destinationMap.put(type+":"+dest, list);
158 }
159
160 private static String[] trim(String[] brokers) {
161 for (int i = 0; i < brokers.length; i++) {
162 brokers[i] = brokers[i].trim();
163 }
164 return brokers;
165 }
166
167 public DestinationSecurityConfig[] getDestinationSecurityConfigs() {
168 ArrayList answer = new ArrayList();
169 for (Iterator iter = destinationMap.values().iterator(); iter.hasNext();) {
170 List l = (List) iter.next();
171 answer.addAll(l);
172 }
173
174 DestinationSecurityConfig rc[] = new DestinationSecurityConfig[answer.size()];
175 answer.toArray(rc);
176 return rc;
177 }
178
179 public BrokerSecurityConfig getBrokerSecurityConfig() {
180 return brokerSecurityConfig;
181 }
182
183 public void installSecurity() {
184 JassJaccSecurityAdapter.secure(brokerSecurityConfig);
185
186 DestinationSecurityConfig[] destinationSecurityConfigs = getDestinationSecurityConfigs();
187 for (int i = 0; i < destinationSecurityConfigs.length; i++) {
188 DestinationSecurityConfig config = destinationSecurityConfigs[i];
189 JassJaccSecurityAdapter.secure(config);
190 }
191
192 }
193
194 }