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 }