001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * 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, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package org.apache.geronimo.security.deployment; 020 021 import java.util.Map; 022 import java.util.HashMap; 023 import java.util.Iterator; 024 import java.util.Set; 025 import java.util.HashSet; 026 027 import javax.security.auth.Subject; 028 import javax.security.auth.x500.X500Principal; 029 import javax.xml.namespace.QName; 030 031 import org.apache.xmlbeans.XmlObject; 032 import org.apache.xmlbeans.QNameSet; 033 import org.apache.geronimo.deployment.DeploymentContext; 034 import org.apache.geronimo.deployment.xmlbeans.XmlBeansUtil; 035 import org.apache.geronimo.common.DeploymentException; 036 import org.apache.geronimo.security.deploy.Security; 037 import org.apache.geronimo.security.deploy.Role; 038 import org.apache.geronimo.security.deploy.RealmPrincipalInfo; 039 import org.apache.geronimo.security.deploy.LoginDomainPrincipalInfo; 040 import org.apache.geronimo.security.deploy.PrincipalInfo; 041 import org.apache.geronimo.security.deploy.DistinguishedName; 042 import org.apache.geronimo.security.deploy.DefaultPrincipal; 043 import org.apache.geronimo.security.util.ConfigurationUtil; 044 import org.apache.geronimo.security.jaas.NamedUsernamePasswordCredential; 045 import org.apache.geronimo.security.jacc.ApplicationPrincipalRoleConfigurationManager; 046 import org.apache.geronimo.security.jacc.ApplicationPolicyConfigurationManager; 047 import org.apache.geronimo.xbeans.geronimo.security.GerSecurityType; 048 import org.apache.geronimo.xbeans.geronimo.security.GerRoleMappingsType; 049 import org.apache.geronimo.xbeans.geronimo.security.GerRoleType; 050 import org.apache.geronimo.xbeans.geronimo.security.GerDistinguishedNameType; 051 import org.apache.geronimo.xbeans.geronimo.security.GerDefaultPrincipalType; 052 import org.apache.geronimo.xbeans.geronimo.security.GerNamedUsernamePasswordCredentialType; 053 import org.apache.geronimo.xbeans.geronimo.security.GerRealmPrincipalType; 054 import org.apache.geronimo.xbeans.geronimo.security.GerLoginDomainPrincipalType; 055 import org.apache.geronimo.xbeans.geronimo.security.GerPrincipalType; 056 import org.apache.geronimo.xbeans.geronimo.security.GerSecurityDocument; 057 import org.apache.geronimo.gbean.GBeanData; 058 import org.apache.geronimo.gbean.AbstractName; 059 import org.apache.geronimo.gbean.GBeanInfo; 060 import org.apache.geronimo.gbean.GBeanInfoBuilder; 061 import org.apache.geronimo.kernel.Naming; 062 import org.apache.geronimo.kernel.GBeanAlreadyExistsException; 063 import org.apache.geronimo.kernel.repository.Environment; 064 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 065 import org.apache.geronimo.j2ee.deployment.SecurityBuilder; 066 import org.apache.geronimo.j2ee.deployment.EARContext; 067 068 /** 069 * @version $Rev: 472317 $ $Date: 2006-11-07 14:59:11 -0800 (Tue, 07 Nov 2006) $ 070 */ 071 public class GeronimoSecurityBuilderImpl implements SecurityBuilder { 072 private static final QName SECURITY_QNAME = GerSecurityDocument.type.getDocumentElementName(); 073 private static final QNameSet SECURITY_QNAME_SET = QNameSet.singleton(SECURITY_QNAME); 074 075 076 public void buildEnvironment(XmlObject container, Environment environment) throws DeploymentException { 077 } 078 079 public void build(XmlObject container, DeploymentContext applicationContext, DeploymentContext moduleContext) throws DeploymentException { 080 EARContext earContext = (EARContext) applicationContext; 081 XmlObject[] items = container.selectChildren(SECURITY_QNAME_SET); 082 if (items.length > 1) { 083 throw new DeploymentException("Unexpected count of security elements in geronimo plan " + items.length + " qnameset: " + SECURITY_QNAME_SET); 084 } 085 if (items.length == 1) { 086 GerSecurityType securityType = (GerSecurityType) items[0].copy().changeType(GerSecurityType.type); 087 Security security = buildSecurityConfig(securityType); 088 ClassLoader classLoader = applicationContext.getClassLoader(); 089 SecurityConfiguration securityConfiguration = buildSecurityConfiguration(security, classLoader); 090 earContext.setSecurityConfiguration(securityConfiguration); 091 } 092 //add the JACC gbean if there is a principal-role mapping and we are on the corect module 093 if (earContext.getSecurityConfiguration() != null && applicationContext == moduleContext) { 094 Naming naming = earContext.getNaming(); 095 GBeanData roleMapperData = configureRoleMapper(naming, earContext.getModuleName(), earContext.getSecurityConfiguration()); 096 try { 097 earContext.addGBean(roleMapperData); 098 } catch (GBeanAlreadyExistsException e) { 099 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 //used from app client builder 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 //used from TSSConfigEditor 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 }