1 /**
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one or more
4 * contributor license agreements. See the NOTICE file distributed with
5 * this work for additional information regarding copyright ownership.
6 * The ASF licenses this file to You under the Apache License, Version 2.0
7 * (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 package org.apache.geronimo.security.deployment;
20
21 import java.util.Map;
22 import java.util.HashMap;
23 import java.util.Iterator;
24 import java.util.Set;
25 import java.util.HashSet;
26
27 import javax.security.auth.Subject;
28 import javax.security.auth.x500.X500Principal;
29 import javax.xml.namespace.QName;
30
31 import org.apache.xmlbeans.XmlObject;
32 import org.apache.xmlbeans.QNameSet;
33 import org.apache.geronimo.deployment.DeploymentContext;
34 import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil;
35 import org.apache.geronimo.common.DeploymentException;
36 import org.apache.geronimo.security.deploy.Security;
37 import org.apache.geronimo.security.deploy.Role;
38 import org.apache.geronimo.security.deploy.RealmPrincipalInfo;
39 import org.apache.geronimo.security.deploy.LoginDomainPrincipalInfo;
40 import org.apache.geronimo.security.deploy.PrincipalInfo;
41 import org.apache.geronimo.security.deploy.DistinguishedName;
42 import org.apache.geronimo.security.deploy.DefaultPrincipal;
43 import org.apache.geronimo.security.util.ConfigurationUtil;
44 import org.apache.geronimo.security.jaas.NamedUsernamePasswordCredential;
45 import org.apache.geronimo.security.jacc.ApplicationPrincipalRoleConfigurationManager;
46 import org.apache.geronimo.security.jacc.ApplicationPolicyConfigurationManager;
47 import org.apache.geronimo.xbeans.geronimo.security.GerSecurityType;
48 import org.apache.geronimo.xbeans.geronimo.security.GerRoleMappingsType;
49 import org.apache.geronimo.xbeans.geronimo.security.GerRoleType;
50 import org.apache.geronimo.xbeans.geronimo.security.GerDistinguishedNameType;
51 import org.apache.geronimo.xbeans.geronimo.security.GerDefaultPrincipalType;
52 import org.apache.geronimo.xbeans.geronimo.security.GerNamedUsernamePasswordCredentialType;
53 import org.apache.geronimo.xbeans.geronimo.security.GerRealmPrincipalType;
54 import org.apache.geronimo.xbeans.geronimo.security.GerLoginDomainPrincipalType;
55 import org.apache.geronimo.xbeans.geronimo.security.GerPrincipalType;
56 import org.apache.geronimo.xbeans.geronimo.security.GerSecurityDocument;
57 import org.apache.geronimo.gbean.GBeanData;
58 import org.apache.geronimo.gbean.AbstractName;
59 import org.apache.geronimo.gbean.GBeanInfo;
60 import org.apache.geronimo.gbean.GBeanInfoBuilder;
61 import org.apache.geronimo.kernel.Naming;
62 import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
63 import org.apache.geronimo.kernel.repository.Environment;
64 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
65 import org.apache.geronimo.j2ee.deployment.SecurityBuilder;
66 import org.apache.geronimo.j2ee.deployment.EARContext;
67
68 /**
69 * @version $Rev: 472317 $ $Date: 2006-11-07 14:59:11 -0800 (Tue, 07 Nov 2006) $
70 */
71 public class GeronimoSecurityBuilderImpl implements SecurityBuilder {
72 private static final QName SECURITY_QNAME = GerSecurityDocument.type.getDocumentElementName();
73 private static final QNameSet SECURITY_QNAME_SET = QNameSet.singleton(SECURITY_QNAME);
74
75
76 public void buildEnvironment(XmlObject container, Environment environment) throws DeploymentException {
77 }
78
79 public void build(XmlObject container, DeploymentContext applicationContext, DeploymentContext moduleContext) throws DeploymentException {
80 EARContext earContext = (EARContext) applicationContext;
81 XmlObject[] items = container.selectChildren(SECURITY_QNAME_SET);
82 if (items.length > 1) {
83 throw new DeploymentException("Unexpected count of security elements in geronimo plan " + items.length + " qnameset: " + SECURITY_QNAME_SET);
84 }
85 if (items.length == 1) {
86 GerSecurityType securityType = (GerSecurityType) items[0].copy().changeType(GerSecurityType.type);
87 Security security = buildSecurityConfig(securityType);
88 ClassLoader classLoader = applicationContext.getClassLoader();
89 SecurityConfiguration securityConfiguration = buildSecurityConfiguration(security, classLoader);
90 earContext.setSecurityConfiguration(securityConfiguration);
91 }
92
93 if (earContext.getSecurityConfiguration() != null && applicationContext == moduleContext) {
94 Naming naming = earContext.getNaming();
95 GBeanData roleMapperData = configureRoleMapper(naming, earContext.getModuleName(), earContext.getSecurityConfiguration());
96 try {
97 earContext.addGBean(roleMapperData);
98 } catch (GBeanAlreadyExistsException e) {
99 throw new DeploymentException("Role mapper gbean already present", e);
100 }
101 GBeanData jaccBeanData = configureApplicationPolicyManager(naming, earContext.getModuleName(), earContext.getContextIDToPermissionsMap(), earContext.getSecurityConfiguration());
102 jaccBeanData.setReferencePattern("PrincipalRoleMapper", roleMapperData.getAbstractName());
103 try {
104 earContext.addGBean(jaccBeanData);
105 } catch (GBeanAlreadyExistsException e) {
106 throw new DeploymentException("JACC manager gbean already present", e);
107 }
108 earContext.setJaccManagerName(jaccBeanData.getAbstractName());
109 }
110 }
111
112 public String getNamespace() {
113 XmlBeansUtil.registerSubstitutionGroupElements(org.apache.geronimo.xbeans.geronimo.j2ee.GerSecurityDocument.type.getDocumentElementName(), SECURITY_QNAME_SET);
114
115 return GerSecurityDocument.type.getDocumentElementName().getLocalPart();
116 }
117
118 private static SecurityConfiguration buildSecurityConfiguration(Security security, ClassLoader classLoader) {
119 Map roleDesignates = new HashMap();
120 Map principalRoleMap = new HashMap();
121 Map roleToPrincipalMap = new HashMap();
122 GeronimoSecurityBuilderImpl.buildRolePrincipalMap(security, roleDesignates, roleToPrincipalMap, classLoader);
123 GeronimoSecurityBuilderImpl.invertMap(roleToPrincipalMap, principalRoleMap);
124 return new SecurityConfiguration(principalRoleMap, roleDesignates, security.getDefaultPrincipal(), security.getDefaultRole(), security.isDoAsCurrentCaller(), security.isUseContextHandler());
125 }
126
127 private static Map invertMap(Map roleToPrincipalMap, Map principalRoleMapping) {
128 for (Iterator roles = roleToPrincipalMap.entrySet().iterator(); roles.hasNext();) {
129 Map.Entry entry = (Map.Entry) roles.next();
130 String role = (String) entry.getKey();
131 Set principals = (Set) entry.getValue();
132 for (Iterator iter = principals.iterator(); iter.hasNext();) {
133 java.security.Principal principal = (java.security.Principal) iter.next();
134
135 HashSet roleSet = (HashSet) principalRoleMapping.get(principal);
136 if (roleSet == null) {
137 roleSet = new HashSet();
138 principalRoleMapping.put(principal, roleSet);
139 }
140 roleSet.add(role);
141 }
142 }
143 return principalRoleMapping;
144 }
145
146 /**
147 * non-interface, used in some jetty/tomcat tests
148 *
149 * @param security
150 * @param roleDesignates
151 * @param roleToPrincipalMap
152 * @param classLoader
153 */
154 public static void buildRolePrincipalMap(Security security, Map roleDesignates, Map roleToPrincipalMap, ClassLoader classLoader) {
155
156 Iterator roleMappings = security.getRoleMappings().values().iterator();
157 while (roleMappings.hasNext()) {
158 Role role = (Role) roleMappings.next();
159
160 String roleName = role.getRoleName();
161 Subject roleDesignate = new Subject();
162 Set principalSet = new HashSet();
163
164 Iterator realmPrincipals = role.getRealmPrincipals().iterator();
165 while (realmPrincipals.hasNext()) {
166 RealmPrincipalInfo realmPrincipal = (RealmPrincipalInfo) realmPrincipals.next();
167 java.security.Principal principal = ConfigurationUtil.generateRealmPrincipal(realmPrincipal.getRealm(), realmPrincipal.getDomain(), realmPrincipal, classLoader);
168
169 principalSet.add(principal);
170 if (realmPrincipal.isDesignatedRunAs()) roleDesignate.getPrincipals().add(principal);
171 }
172
173 Iterator domainPrincipals = role.getLoginDomainPrincipals().iterator();
174 while (domainPrincipals.hasNext()) {
175 LoginDomainPrincipalInfo domainPrincipal = (LoginDomainPrincipalInfo) domainPrincipals.next();
176 java.security.Principal principal = ConfigurationUtil.generateDomainPrincipal(domainPrincipal.getDomain(), domainPrincipal, classLoader);
177
178 principalSet.add(principal);
179 if (domainPrincipal.isDesignatedRunAs()) roleDesignate.getPrincipals().add(principal);
180 }
181
182 Iterator principals = role.getPrincipals().iterator();
183 while (principals.hasNext()) {
184 PrincipalInfo plainPrincipalInfo = (PrincipalInfo) principals.next();
185 java.security.Principal principal = ConfigurationUtil.generatePrincipal(plainPrincipalInfo, classLoader);
186
187 principalSet.add(principal);
188 if (plainPrincipalInfo.isDesignatedRunAs()) roleDesignate.getPrincipals().add(principal);
189 }
190
191 for (Iterator names = role.getDistinguishedNames().iterator(); names.hasNext();) {
192 DistinguishedName dn = (DistinguishedName) names.next();
193
194 X500Principal x500Principal = ConfigurationUtil.generateX500Principal(dn.getName());
195
196 principalSet.add(x500Principal);
197 if (dn.isDesignatedRunAs()) roleDesignate.getPrincipals().add(x500Principal);
198 }
199
200 Set roleMapping = (Set) roleToPrincipalMap.get(roleName);
201 if (roleMapping == null) {
202 roleMapping = new HashSet();
203 roleToPrincipalMap.put(roleName, roleMapping);
204 }
205 roleMapping.addAll(principalSet);
206
207 if (roleDesignate.getPrincipals().size() > 0) {
208 roleDesignates.put(roleName, roleDesignate);
209 }
210 }
211 }
212
213 private Security buildSecurityConfig(GerSecurityType securityType) {
214 Security security;
215
216 if (securityType == null) {
217 return null;
218 }
219 security = new Security();
220
221 security.setDoAsCurrentCaller(securityType.getDoasCurrentCaller());
222 security.setUseContextHandler(securityType.getUseContextHandler());
223 if (securityType.isSetDefaultRole()) {
224 security.setDefaultRole(securityType.getDefaultRole().trim());
225 }
226
227 if (securityType.isSetRoleMappings()) {
228 GerRoleMappingsType roleMappingsType = securityType.getRoleMappings();
229 for (int i = 0; i < roleMappingsType.sizeOfRoleArray(); i++) {
230 GerRoleType roleType = roleMappingsType.getRoleArray(i);
231 Role role = new Role();
232
233 String roleName = roleType.getRoleName().trim();
234 role.setRoleName(roleName);
235
236 for (int j = 0; j < roleType.sizeOfRealmPrincipalArray(); j++) {
237 role.getRealmPrincipals().add(GeronimoSecurityBuilderImpl.buildRealmPrincipal(roleType.getRealmPrincipalArray(j)));
238 }
239
240 for (int j = 0; j < roleType.sizeOfLoginDomainPrincipalArray(); j++) {
241 role.getLoginDomainPrincipals().add(GeronimoSecurityBuilderImpl.buildDomainPrincipal(roleType.getLoginDomainPrincipalArray(j)));
242 }
243
244 for (int j = 0; j < roleType.sizeOfPrincipalArray(); j++) {
245 role.getPrincipals().add(buildPrincipal(roleType.getPrincipalArray(j)));
246 }
247
248 for (int j = 0; j < roleType.sizeOfDistinguishedNameArray(); j++) {
249 GerDistinguishedNameType dnType = roleType.getDistinguishedNameArray(j);
250
251 role.getDistinguishedNames().add(new DistinguishedName(dnType.getName().trim(), dnType.getDesignatedRunAs()));
252 }
253
254 security.getRoleMappings().put(roleName, role);
255 }
256 }
257
258 security.setDefaultPrincipal(buildDefaultPrincipal(securityType.getDefaultPrincipal()));
259
260 return security;
261 }
262
263
264 public DefaultPrincipal buildDefaultPrincipal(XmlObject xmlObject) {
265 GerDefaultPrincipalType defaultPrincipalType = (GerDefaultPrincipalType) xmlObject;
266 DefaultPrincipal defaultPrincipal = new DefaultPrincipal();
267
268 if(defaultPrincipalType.isSetPrincipal()) {
269 defaultPrincipal.setPrincipal(buildPrincipal(defaultPrincipalType.getPrincipal()));
270 } else if(defaultPrincipalType.isSetLoginDomainPrincipal()) {
271 defaultPrincipal.setPrincipal(buildDomainPrincipal(defaultPrincipalType.getLoginDomainPrincipal()));
272 } else if(defaultPrincipalType.isSetRealmPrincipal()) {
273 defaultPrincipal.setPrincipal(buildRealmPrincipal(defaultPrincipalType.getRealmPrincipal()));
274 } else {
275 throw new IllegalStateException("default-principal does not contain a principal, login-domain-principal, or realm-principal");
276 }
277 GerNamedUsernamePasswordCredentialType[] namedCredentials = defaultPrincipalType.getNamedUsernamePasswordCredentialArray();
278 if (namedCredentials.length > 0) {
279 Set defaultCredentialSet = new HashSet();
280 for (int i = 0; i < namedCredentials.length; i++) {
281 GerNamedUsernamePasswordCredentialType namedCredentialType = namedCredentials[i];
282 NamedUsernamePasswordCredential namedCredential = new NamedUsernamePasswordCredential(namedCredentialType.getUsername().trim(), namedCredentialType.getPassword().trim().toCharArray(), namedCredentialType.getName().trim());
283 defaultCredentialSet.add(namedCredential);
284 }
285 defaultPrincipal.setNamedUserPasswordCredentials(defaultCredentialSet);
286 }
287 return defaultPrincipal;
288 }
289
290 private static RealmPrincipalInfo buildRealmPrincipal(GerRealmPrincipalType realmPrincipalType) {
291 return new RealmPrincipalInfo(realmPrincipalType.getRealmName().trim(), realmPrincipalType.getDomainName().trim(), realmPrincipalType.getClass1().trim(), realmPrincipalType.getName().trim(), realmPrincipalType.isSetDesignatedRunAs());
292 }
293
294 private static LoginDomainPrincipalInfo buildDomainPrincipal(GerLoginDomainPrincipalType domainPrincipalType) {
295 return new LoginDomainPrincipalInfo(domainPrincipalType.getDomainName().trim(), domainPrincipalType.getClass1().trim(), domainPrincipalType.getName().trim(), domainPrincipalType.isSetDesignatedRunAs());
296 }
297
298
299 public PrincipalInfo buildPrincipal(XmlObject xmlObject) {
300 GerPrincipalType principalType = (GerPrincipalType) xmlObject;
301 return new PrincipalInfo(principalType.getClass1().trim(), principalType.getName().trim(), principalType.isSetDesignatedRunAs());
302 }
303
304 public GBeanData configureRoleMapper(Naming naming, AbstractName moduleName, Object securityConfiguration) {
305 AbstractName roleMapperName = naming.createChildName(moduleName, "RoleMapper", "RoleMapper");
306 GBeanData roleMapperData = new GBeanData(roleMapperName, ApplicationPrincipalRoleConfigurationManager.GBEAN_INFO);
307 roleMapperData.setAttribute("principalRoleMap", ((SecurityConfiguration) securityConfiguration).getPrincipalRoleMap());
308 return roleMapperData;
309 }
310
311 public GBeanData configureApplicationPolicyManager(Naming naming, AbstractName moduleName, Map contextIDToPermissionsMap, Object securityConfiguration) {
312 AbstractName jaccBeanName = naming.createChildName(moduleName, NameFactory.JACC_MANAGER, NameFactory.JACC_MANAGER);
313 GBeanData jaccBeanData = new GBeanData(jaccBeanName, ApplicationPolicyConfigurationManager.GBEAN_INFO);
314 jaccBeanData.setAttribute("contextIdToPermissionsMap", contextIDToPermissionsMap);
315 jaccBeanData.setAttribute("roleDesignates", ((SecurityConfiguration) securityConfiguration).getRoleDesignates());
316 return jaccBeanData;
317
318 }
319
320 public static final GBeanInfo GBEAN_INFO;
321
322 static {
323 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(GeronimoSecurityBuilderImpl.class, NameFactory.MODULE_BUILDER);
324
325 infoFactory.addInterface(SecurityBuilder.class);
326
327
328 GBEAN_INFO = infoFactory.getBeanInfo();
329 }
330
331 public static GBeanInfo getGBeanInfo() {
332 return GBEAN_INFO;
333 }
334
335
336 }