View Javadoc

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          //add the JACC gbean if there is a principal-role mapping and we are on the corect module
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     //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 }