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    }