001/*
002* The contents of this file are subject to the terms of the Common Development and
003* Distribution License (the License). You may not use this file except in compliance with the
004* License.
005*
006* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007* specific language governing permission and limitations under the License.
008*
009* When distributing Covered Software, include this CDDL Header Notice in each file and include
010* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011* Header, with the fields enclosed by brackets [] replaced by your own identifying
012* information: "Portions Copyrighted [year] [name of copyright owner]".
013*
014* Copyright 2014-2016 ForgeRock AS.
015*/
016
017package org.forgerock.openam.sts.config.user;
018
019import org.apache.xml.security.encryption.XMLCipher;
020import org.forgerock.guava.common.base.Objects;
021import org.forgerock.json.JsonValue;
022import org.forgerock.openam.shared.sts.SharedSTSConstants;
023import org.forgerock.openam.sts.AMSTSConstants;
024import org.forgerock.openam.sts.MapMarshallUtils;
025import org.forgerock.openam.utils.CollectionUtils;
026
027import java.io.UnsupportedEncodingException;
028import java.util.Arrays;
029import java.util.Collections;
030import java.util.HashMap;
031import java.util.LinkedHashMap;
032import java.util.LinkedHashSet;
033import java.util.Map;
034import java.util.Set;
035
036import static org.forgerock.json.JsonValue.field;
037import static org.forgerock.json.JsonValue.json;
038import static org.forgerock.json.JsonValue.object;
039
040/**
041 * Encapsulates the configuration state necessary to produce SAML2 assertions.
042 *
043 * Each published rest-sts instance will encapsulate state to allow it to issue saml2 assertions for a single
044 * SP. Thus the spEntityId, and spAcsUrl (the url of the SP's assertion consumer service) are specified in this class.
045 * The signatureAlias corresponds to the IDP's signing key, and the encryptionKeyAlias could correspond to the SP's
046 * public key corresponding to the key used to encrypt the symmetric key used to encrypt assertion elements.
047 *
048 * @supported.all.api
049 */
050public class SAML2Config {
051
052    /*
053    * TODO: Ambiguity in the context of setting the customAttributeStatementsProviderClassName
054    * and the customAttributeMapperClassName. As it currently stands, the customAttributeStatementsProvider will be passed
055    * an instance of the customAttributeMapper if both are specified. The usual case will simply to set the customAttributeMapper,
056    * as this allows custom attributes to be set in the AttributeStatement.
057    *
058    * TODO: do I want a name-qualifier in addition to a nameIdFormat?
059    */
060
061    private static final String EQUALS = "=";
062
063    /**
064     * Builder used to programmatically create {@linkplain SAML2Config} objects
065     *
066     * @supported.all.api
067     */
068    public static class SAML2ConfigBuilder {
069        private String idpId;
070        /*
071        Cannot use the SAML2Constants defined in openam-federation, as this dependency
072        introduces a dependency on openam-core, which pulls the ws-* dependencies into the soap-sts, which I don't want.
073        Also can't use the SAML2Constants in wss4j, as I don't want this dependency in the rest-sts (as it depends upon
074        SAML2Config). Just define the value here.
075         */
076        private String nameIdFormat = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified";
077        private Map<String, String> attributeMap;
078        private long tokenLifetimeInSeconds = 60 * 10; //default token lifetime is 10 minutes
079        private String customConditionsProviderClassName;
080        private String customSubjectProviderClassName;
081        private String customAuthenticationStatementsProviderClassName;
082        private String customAttributeStatementsProviderClassName;
083        private String customAuthzDecisionStatementsProviderClassName;
084        private String customAttributeMapperClassName;
085        private String customAuthNContextMapperClassName;
086        private String spEntityId;
087        private String spAcsUrl;
088        private boolean signAssertion;
089        private boolean encryptNameID;
090        private boolean encryptAttributes;
091        private boolean encryptAssertion;
092        private String encryptionAlgorithm;
093        private int encryptionAlgorithmStrength;
094        private String keystoreFileName;
095        private byte[] keystorePassword;
096        /*
097        Corresponds to the key used to sign the assertion.
098         */
099        private String signatureKeyAlias;
100        private byte[] signatureKeyPassword;
101        /*
102        Corresponds to the SP's x509 cert -  the corresponding public key is used to encrypt the symmetric key used to
103        encrypt assertion elements
104         */
105        private String encryptionKeyAlias;
106
107        private SAML2ConfigBuilder() {}
108
109        /**
110         * Sets the name-id format on the SAML2ConfigBuilder.
111         *
112         * @param nameIdFormat the name-id format.
113         * @return the SAML2ConfigBuilder with the specified name-id format.
114         */
115        public SAML2ConfigBuilder nameIdFormat(String nameIdFormat) {
116            //TODO - test to see if it matches one of the allowed values?
117            this.nameIdFormat = nameIdFormat;
118            return this;
119        }
120
121        /**
122         * Sets the Idenity Provider id on the SAML2ConfigBuilder.
123         *
124         * @param idpId the Identity Provider id.
125         * @return the SAML2ConfigBuilder with the specified Identity Provider id.
126         */
127        public SAML2ConfigBuilder idpId(String idpId) {
128            this.idpId = idpId;
129            return this;
130        }
131
132        /**
133         * Sets the attribute map on the SAML2ConfigBuilder.
134         *
135         * @param attributeMap the attribute map.
136         * @return the SAML2ConfigBuilder with the specified attribute map.
137         */
138        public SAML2ConfigBuilder attributeMap(Map<String, String> attributeMap) {
139            this.attributeMap = Collections.unmodifiableMap(attributeMap);
140            return this;
141        }
142
143        /**
144         * Sets the token lifetime (in seconds) on the SAML2ConfigBuilder.
145         *
146         * @param lifetimeInSeconds the token lifetime.
147         * @return the SAML2ConfigBuilder with the specified token lifetime.
148         */
149        public SAML2ConfigBuilder tokenLifetimeInSeconds(long lifetimeInSeconds) {
150            this.tokenLifetimeInSeconds = lifetimeInSeconds;
151            return this;
152        }
153
154        /**
155         * Sets the CustomConditionsProvider classname on the SAML2ConfigBuilder.
156         *
157         * @param customConditionsProviderClassName the CustomConditionsProvider classname.
158         * @return the SAML2ConfigBuilder with the specified CustomConditionsProvider classname.
159         */
160        public SAML2ConfigBuilder customConditionsProviderClassName(String customConditionsProviderClassName) {
161            this.customConditionsProviderClassName = customConditionsProviderClassName;
162            return this;
163        }
164
165        /**
166         * Sets the CustomSubjectProvider classname on the SAML2ConfigBuilder.
167         *
168         * @param customSubjectProviderClassName the CustomSubjectProvider classname.
169         * @return the SAML2ConfigBuilder with the specified CustomSubjectProvider classname.
170         */
171        public SAML2ConfigBuilder customSubjectProviderClassName(String customSubjectProviderClassName) {
172            this.customSubjectProviderClassName = customSubjectProviderClassName;
173            return this;
174        }
175
176        /**
177         * Sets the CustomAuthenticationStatementsProvider classname on the SAML2ConfigBuilder.
178         *
179         * @param customAuthenticationStatementsProviderClassName the CustomAuthenticationStatementsProvider classname.
180         * @return the SAML2ConfigBuilder with the specified CustomAuthenticationStatementsProvider classname.
181         */
182        public SAML2ConfigBuilder customAuthenticationStatementsProviderClassName(String customAuthenticationStatementsProviderClassName) {
183            this.customAuthenticationStatementsProviderClassName = customAuthenticationStatementsProviderClassName;
184            return this;
185        }
186
187        /**
188         * Sets the CustomAttributeStatementsProvider classname on the SAML2ConfigBuilder.
189         *
190         * @param customAttributeStatementsProviderClassName the CustomAuthenticationStatementsProvider classname.
191         * @return the SAML2ConfigBuilder with the specified CustomAuthenticationStatementsProvider classname.
192         */
193        public SAML2ConfigBuilder customAttributeStatementsProviderClassName(String customAttributeStatementsProviderClassName) {
194            this.customAttributeStatementsProviderClassName = customAttributeStatementsProviderClassName;
195            return this;
196        }
197
198        /**
199         * Sets the CustomAuthzDecisionStatementsProvider classname on the SAML2ConfigBuilder.
200         *
201         * @param customAuthzDecisionStatementsProviderClassName the CustomAuthzDecisionStatementsProvider classname.
202         * @return the SAML2ConfigBuilder with the specified CustomAuthzDecisionStatementsProvider classname.
203         */
204        public SAML2ConfigBuilder customAuthzDecisionStatementsProviderClassName(String customAuthzDecisionStatementsProviderClassName) {
205            this.customAuthzDecisionStatementsProviderClassName = customAuthzDecisionStatementsProviderClassName;
206            return this;
207        }
208
209        /**
210         * Sets the CustomAttributeMapper classname on the SAML2ConfigBuilder.
211         *
212         * @param customAttributeMapperClassName the CustomAttributeMapper classname.
213         * @return the SAML2ConfigBuilder with the specified CustomAttributeMapper classname.
214         */
215        public SAML2ConfigBuilder customAttributeMapperClassName(String customAttributeMapperClassName) {
216            this.customAttributeMapperClassName = customAttributeMapperClassName;
217            return this;
218        }
219
220        /**
221         * Sets the CustomAuthNContextMapper classname on the SAML2ConfigBuilder.
222         *
223         * @param customAuthNContextMapperClassName the CustomAuthNContextMapper classname.
224         * @return the SAML2ConfigBuilder with the specified CustomAuthNContextMapper classname.
225         */
226        public SAML2ConfigBuilder customAuthNContextMapperClassName(String customAuthNContextMapperClassName) {
227            this.customAuthNContextMapperClassName = customAuthNContextMapperClassName;
228            return this;
229        }
230
231        /**
232         * Sets the SP entity id on the SAML2ConfigBuilder.
233         *
234         * @param spEntityId the SP entity id.
235         * @return the SAML2Config builder with the specified SP entity id.
236         */
237        public SAML2ConfigBuilder spEntityId(String spEntityId) {
238            this.spEntityId = spEntityId;
239            return this;
240        }
241
242        /**
243         * Sets the SP ACS url on the SAML2ConfigBuilder.
244         *
245         * @param spAcsUrl the SP ACS url.
246         * @return the SAML2Config builder with the specified SP ACS url.
247         */
248        public SAML2ConfigBuilder spAcsUrl(String spAcsUrl) {
249            this.spAcsUrl = spAcsUrl;
250            return this;
251        }
252
253        /**
254         * Sets the signature key alias on the SAML2ConfigBuilder.
255         *
256         * @param signatureKeyAlias the signature key alias.
257         * @return the SAML2Config builder with the specified signature key alias.
258         */
259        public SAML2ConfigBuilder signatureKeyAlias(String signatureKeyAlias) {
260            this.signatureKeyAlias = signatureKeyAlias;
261            return this;
262        }
263
264        /**
265         * Sets the signature key password on the SAML2ConfigBuilder.
266         *
267         * @param signatureKeyPassword the signature key password.
268         * @return the SAML2Config builder with the specified signature key password.
269         */
270        public SAML2ConfigBuilder signatureKeyPassword(byte[] signatureKeyPassword) {
271            this.signatureKeyPassword = signatureKeyPassword;
272            return this;
273        }
274
275        /**
276         * Sets the encryption key alias on the SAML2ConfigBuilder.
277         *
278         * @param encryptionKeyAlias the encryption key alias.
279         * @return the SAML2Config builder with the specified encryption key alias.
280         */
281        public SAML2ConfigBuilder encryptionKeyAlias(String encryptionKeyAlias) {
282            this.encryptionKeyAlias = encryptionKeyAlias;
283            return this;
284        }
285
286        /**
287         * Sets whether the SAML2Config assertion should be signed.
288         *
289         * @param signAssertion whether the assertion should be signed.
290         * @return the SAML2ConfigBuilder with the assertion signed flag set.
291         */
292        public SAML2ConfigBuilder signAssertion(boolean signAssertion) {
293            this.signAssertion = signAssertion;
294            return this;
295        }
296
297        /**
298         * Sets whether the SAML2Config name-id should be encrypted.
299         *
300         * @param encryptNameID whether the name-id should be encrypted.
301         * @return the SAML2ConfigBuilder with the name-id encryption flag set.
302         */
303        public SAML2ConfigBuilder encryptNameID(boolean encryptNameID) {
304            this.encryptNameID = encryptNameID;
305            return this;
306        }
307
308        /**
309         * Sets whether SAML2Config attributes should be encrypted.
310         *
311         * @param encryptAttributes whether the attributes should be encrypted.
312         * @return the SAML2ConfigBuilder with the attribute encryption flag set.
313         */
314        public SAML2ConfigBuilder encryptAttributes(boolean encryptAttributes) {
315            this.encryptAttributes = encryptAttributes;
316            return this;
317        }
318
319        /**
320         * Sets whether SAML2Config assertion should be encrypted.
321         *
322         * @param encryptAssertion whether the assertion should be encrypted.
323         * @return the SAML2ConfigBuilder with the assertion encryption flag set.
324         */
325        public SAML2ConfigBuilder encryptAssertion(boolean encryptAssertion) {
326            this.encryptAssertion = encryptAssertion;
327            return this;
328        }
329
330        /*
331        Note that the encryption of SAML2 assertions, is, by default, delegated to the FMEncProvider class, which supports
332        only http://www.w3.org/2001/04/xmlenc#aes128-cbc, http://www.w3.org/2001/04/xmlenc#aes192-cbc,
333        http://www.w3.org/2001/04/xmlenc#aes256-cbc, or http://www.w3.org/2001/04/xmlenc#tripledes-cbc. However, because
334        this EncProvider implementation can be over-ridden by setting the com.sun.identity.saml2.xmlenc.EncryptionProvider
335        property, I can't reject the specification of an encryption algorithm not supported by the FMEncProvider, as
336        I don't know whether this property has been over-ridden.
337
338        Note also that I will remove http://www.w3.org/2001/04/xmlenc#tripledes-cbc from the set of choices exposed
339        in the UI. There seems to be a bug in the FMEncProvider - when the tripledes-cbc is chosen, note on line 294 that
340        this string http://www.w3.org/2001/04/xmlenc#tripledes-cbc is passed to XMLCipher.getInstance resulting in the
341        error below:
342        org.apache.xml.security.encryption.XMLEncryptionException: Wrong algorithm: DESede or TripleDES required
343        The correct thing is done in FMEncProvider#generateSecretKey, where the http://www.w3.org/2001/04/xmlenc#tripledes-cbc
344        is translated to 'TripleDES' before being passed to the XMLCipher - and this actually works.
345         */
346        /**
347         * Sets the SAML2Config encryption algorithm.
348         *
349         * @param encryptionAlgorithm the encryption algorithm.
350         * @return the SAML2ConfigBuilder with the specified encryption algorithm.
351         */
352        public SAML2ConfigBuilder encryptionAlgorithm(String encryptionAlgorithm) {
353            this.encryptionAlgorithm = encryptionAlgorithm;
354            return this;
355        }
356
357        /*
358        Note that the encryption of SAML2 assertions, is, by default, delegated to the FMEncProvider class, which supports
359        only encryption algorithm strength values of 128, 192, and 256 for the encryption types XMLCipher.AES_128,
360        XMLCipher.AES_192, and XMLCipher.AES_256, respectively. It does not look like the XMLCipher.TRIPLEDES supports a
361        key encryption strength (see FMEncProvider for details). Given that the encryption strength is directly related
362        to the cipher, it seems a bit silly to set these values. However, because
363        this EncProvider implementation can be over-ridden by setting the com.sun.identity.saml2.xmlenc.EncryptionProvider
364        property, and because the EncProvider specifies an encryption strength parameter, it would seem that I would have
365        to support the setting of this seemingly superfluous parameter, just to support the plug-in interface. For now,
366        I will not expose this value in the UI, as it adds unnecessary complexity, and the encryption algorithms are
367        pre-defined as well. I will simply set this value in the UI context based upon the encryption algorithm. If
368        a customer wants to specify a custom value because they have implemented their own EncryptionProvider, then they
369        can publish a rest-sts instance programmatically.
370         */
371        /**
372         * Sets the SAML2Config encryption strength.
373         *
374         * @param encryptionAlgorithmStrength the encryption strength.
375         * @return the SAML2ConfigBuilder with the specified encryption strength.
376         */
377        public SAML2ConfigBuilder encryptionAlgorithmStrength(int encryptionAlgorithmStrength) {
378            this.encryptionAlgorithmStrength = encryptionAlgorithmStrength;
379            return this;
380        }
381
382        /**
383         * Sets the keystore filename on the SAML2ConfigBuilder.
384         *
385         * @param keystoreFileName the keystore filename.
386         * @return the SAML2Config builder with the specified keystore filename.
387         */
388        public SAML2ConfigBuilder keystoreFile(String keystoreFileName) {
389            this.keystoreFileName = keystoreFileName;
390            return this;
391        }
392
393        /**
394         * Sets the keystore password on the SAML2ConfigBuilder.
395         *
396         * @param keystorePassword the keystore password.
397         * @return the SAML2Config builder with the specified keystore password.
398         */
399        public SAML2ConfigBuilder keystorePassword(byte[] keystorePassword) {
400            this.keystorePassword = keystorePassword;
401            return this;
402        }
403
404        /**
405         * Builds a SAML2Config object.
406         * 
407         * @return a SAML2Config object.
408         */
409        public SAML2Config build() {
410            return new SAML2Config(this);
411        }
412    }
413
414    /*
415    Define the names of fields to aid in json marshalling. Note that these names match the names of the AttributeSchema
416    entries in restSTS.xml and soapSTS.xml, as this aids in marshalling an instance of this class into the attribute map needed for
417    SMS persistence.
418     */
419    static final String NAME_ID_FORMAT = "saml2-name-id-format";
420    static final String ATTRIBUTE_MAP = SharedSTSConstants.SAML2_ATTRIBUTE_MAP;
421    static final String TOKEN_LIFETIME = SharedSTSConstants.SAML2_TOKEN_LIFETIME;
422    static final String CUSTOM_CONDITIONS_PROVIDER_CLASS = "saml2-custom-conditions-provider-class-name";
423    static final String CUSTOM_SUBJECT_PROVIDER_CLASS = "saml2-custom-subject-provider-class-name";
424    static final String CUSTOM_ATTRIBUTE_STATEMENTS_PROVIDER_CLASS = "saml2-custom-attribute-statements-provider-class-name";
425    static final String CUSTOM_AUTHENTICATION_STATEMENTS_PROVIDER_CLASS = "saml2-custom-authentication-statements-provider-class-name";
426    static final String CUSTOM_AUTHZ_DECISION_STATEMENTS_PROVIDER_CLASS = "saml2-custom-authz-decision-statements-provider-class-name";
427    static final String CUSTOM_ATTRIBUTE_MAPPER_CLASS = "saml2-custom-attribute-mapper-class-name";
428    static final String CUSTOM_AUTHN_CONTEXT_MAPPER_CLASS = "saml2-custom-authn-context-mapper-class-name";
429    static final String SIGN_ASSERTION = SharedSTSConstants.SAML2_SIGN_ASSERTION;
430    static final String ENCRYPT_ATTRIBUTES = SharedSTSConstants.SAML2_ENCRYPT_ATTRIBUTES;
431    static final String ENCRYPT_NAME_ID = SharedSTSConstants.SAML2_ENCRYPT_NAME_ID;
432    static final String ENCRYPT_ASSERTION = SharedSTSConstants.SAML2_ENCRYPT_ASSERTION;
433    static final String ENCRYPTION_ALGORITHM = SharedSTSConstants.SAML2_ENCRYPTION_ALGORITHM;
434    static final String ENCRYPTION_ALGORITHM_STRENGTH = SharedSTSConstants.SAML2_ENCRYPTION_ALGORITHM_STRENGTH;
435    static final String KEYSTORE_FILE_NAME = SharedSTSConstants.SAML2_KEYSTORE_FILE_NAME;
436    static final String KEYSTORE_PASSWORD = SharedSTSConstants.SAML2_KEYSTORE_PASSWORD;
437    static final String SP_ENTITY_ID = SharedSTSConstants.SAML2_SP_ENTITY_ID;
438    static final String SP_ACS_URL = SharedSTSConstants.SAML2_SP_ACS_URL;
439    static final String ENCRYPTION_KEY_ALIAS = SharedSTSConstants.SAML2_ENCRYPTION_KEY_ALIAS;
440    static final String SIGNATURE_KEY_ALIAS = SharedSTSConstants.SAML2_SIGNATURE_KEY_ALIAS;
441    static final String SIGNATURE_KEY_PASSWORD = SharedSTSConstants.SAML2_SIGNATURE_KEY_PASSWORD;
442    /*
443    Note that this attribute(issuer-name) was defined in STSInstanceConfig, and thus global to an STS instance. It was
444    used to set the issuer field in issued SAML2 assertions, when the STS only issued SAML2 assertions. Now that
445    OIDC tokens are also issued, the issuer-name must be scoped to the token-specific config. Thus, by convention,
446    the name of the AttributeSchema element would be saml2-issuer-name. However, changing the name of this attribute
447    would involve a schema migration step. This can be avoided by encapsulating this same attribute in the SAML2Config
448    class, and via an update to the AdminUI to describe this attribute as the IDP identifier
449     */
450    static final String ISSUER_NAME = SharedSTSConstants.ISSUER_NAME;
451
452    private final String nameIdFormat;
453    private final Map<String, String> attributeMap;
454    private final long tokenLifetimeInSeconds;
455    private final String customConditionsProviderClassName;
456    private final String customSubjectProviderClassName;
457    private final String customAuthenticationStatementsProviderClassName;
458    private final String customAttributeStatementsProviderClassName;
459    private final String customAuthzDecisionStatementsProviderClassName;
460    private final String customAttributeMapperClassName;
461    private final String customAuthNContextMapperClassName;
462    private final String spEntityId;
463    private final String spAcsUrl;
464    private final boolean signAssertion;
465    private final boolean encryptNameID;
466    private final boolean encryptAttributes;
467    private final boolean encryptAssertion;
468    private final String encryptionAlgorithm;
469    private final int encryptionAlgorithmStrength;
470    private final String keystoreFileName;
471    private final byte[] keystorePassword;
472    private final String signatureKeyAlias;
473    private final byte[] signatureKeyPassword;
474    private final String encryptionKeyAlias;
475    private final String idpId;
476
477    private SAML2Config(SAML2ConfigBuilder builder) {
478        this.nameIdFormat = builder.nameIdFormat; //not required so don't reject if null
479        if (builder.attributeMap != null) {
480            this.attributeMap = Collections.unmodifiableMap(builder.attributeMap);
481        } else {
482            attributeMap = Collections.emptyMap();
483        }
484        tokenLifetimeInSeconds = builder.tokenLifetimeInSeconds; //will be set to default if not explicitly set
485        customConditionsProviderClassName = builder.customConditionsProviderClassName;
486        customSubjectProviderClassName = builder.customSubjectProviderClassName;
487        customAuthenticationStatementsProviderClassName = builder.customAuthenticationStatementsProviderClassName;
488        customAuthzDecisionStatementsProviderClassName = builder.customAuthzDecisionStatementsProviderClassName;
489        customAttributeStatementsProviderClassName = builder.customAttributeStatementsProviderClassName;
490        customAttributeMapperClassName = builder.customAttributeMapperClassName;
491        customAuthNContextMapperClassName = builder.customAuthNContextMapperClassName;
492        this.signAssertion = builder.signAssertion;
493        this.encryptNameID = builder.encryptNameID;
494        this.encryptAttributes = builder.encryptAttributes;
495        this.encryptAssertion = builder.encryptAssertion;
496        this.encryptionAlgorithm = builder.encryptionAlgorithm;
497        this.encryptionAlgorithmStrength = builder.encryptionAlgorithmStrength;
498        this.keystoreFileName = builder.keystoreFileName;
499        this.keystorePassword = builder.keystorePassword;
500        this.spEntityId = builder.spEntityId;
501        this.spAcsUrl = builder.spAcsUrl;
502        this.signatureKeyAlias = builder.signatureKeyAlias;
503        this.signatureKeyPassword = builder.signatureKeyPassword;
504        this.encryptionKeyAlias = builder.encryptionKeyAlias;
505        this.idpId = builder.idpId;
506
507        if (spEntityId ==  null) {
508            throw new IllegalArgumentException("The entity id of the consumer (SP) for issued assertions must be specified.");
509        }
510        if (encryptAssertion || encryptNameID || encryptAttributes) {
511            if (encryptionAlgorithm == null) {
512                throw new IllegalArgumentException("If elements of the assertion are to be encrypted, an encryption " +
513                        "algorithm must be specified.");
514            }
515            if (encryptionAlgorithmStrength == 0 && !XMLCipher.TRIPLEDES.equals(encryptionAlgorithm)) {
516                throw new IllegalArgumentException("If elements of the assertion are to be encrypted, an encryption " +
517                        "algorithm strength must be specified.");
518            }
519            if (encryptionKeyAlias ==  null) {
520                throw new IllegalArgumentException("If elements of the assertion are to be encrypted, an encryption key" +
521                        "alias  must be specified.");
522            }
523        }
524        if (encryptAssertion || encryptNameID || encryptAttributes || signAssertion) {
525            if (keystorePassword == null || keystoreFileName == null) {
526                throw new IllegalArgumentException("If the assertions are to be signed or encrypted, then the keystore " +
527                        "file and password must be specified.");
528            }
529        }
530        if (signAssertion) {
531            if ((signatureKeyPassword == null) || (signatureKeyAlias == null)) {
532                throw new IllegalArgumentException("If the assertion is to be signed, then the signature key alias and" +
533                        " signature key password must be specified.");
534            }
535        }
536
537        if (encryptAssertion && (encryptNameID || encryptAttributes)) {
538            throw new IllegalArgumentException("Either the entire assertion can be encrypted, or the Attributes and/or NameID.");
539        }
540
541        if (idpId == null) {
542            throw new IllegalArgumentException("The Identity Provider id must be set.");
543        }
544    }
545
546    /**
547     * Creates a new {@code SAML2ConfigBuilder}.
548     *
549     * @return a new {@code SAML2ConfigBuilder}.
550     */
551    public static SAML2ConfigBuilder builder() {
552        return new SAML2ConfigBuilder();
553    }
554
555    /**
556     * Gets the name-id format.
557     *
558     * @return the name-id format.
559     */
560    public String getNameIdFormat() {
561        return nameIdFormat;
562    }
563
564    /**
565     * Gets the token lifetime (in seconds).
566     *
567     * @return the token lifetime.
568     */
569    public long getTokenLifetimeInSeconds() {
570        return tokenLifetimeInSeconds;
571    }
572
573    /**
574     * Gets the attribute map.
575     *
576     * @return the attribute map.
577     */
578    public Map<String, String> getAttributeMap() {
579        return attributeMap;
580    }
581
582    /**
583     * Gets the classname of the CustomConditionsProvider.
584     *
585     * @return the classname of the CustomConditionsProvider.
586     */
587    public String getCustomConditionsProviderClassName() {
588        return customConditionsProviderClassName;
589    }
590
591    /**
592     * Gets the classname of the CustomSubjectProvider.
593     *
594     * @return the classname of the CustomSubjectProvider.
595     */
596    public String getCustomSubjectProviderClassName() {
597        return customSubjectProviderClassName;
598    }
599
600    /**
601     * Gets the classname of the CustomAuthenticationStatementsProvider.
602     *
603     * @return the classname of the CustomAuthenticationStatementsProvider.
604     */
605    public String getCustomAuthenticationStatementsProviderClassName() {
606        return customAuthenticationStatementsProviderClassName;
607    }
608
609    /**
610     * Gets the classname of the CustomAttributeMapper.
611     *
612     * @return the classname of the CustomAttributeMapper.
613     */
614    public String getCustomAttributeMapperClassName() {
615        return customAttributeMapperClassName;
616    }
617
618    /**
619     * Gets the classname of the CustomAuthNContextMapper.
620     *
621     * @return the classname of the CustomAuthNContextMapper.
622     */
623    public String getCustomAuthNContextMapperClassName() {
624        return customAuthNContextMapperClassName;
625    }
626
627    /**
628     * Gets the classname of the CustomAttributeStatementsProvider.
629     *
630     * @return the classname of the CustomAttributeStatementsProvider.
631     */
632    public String getCustomAttributeStatementsProviderClassName() {
633        return customAttributeStatementsProviderClassName;
634    }
635
636    /**
637     * Gets the classname of the CustomAuthzDecisionStatementsProvider.
638     *
639     * @return the classname of the CustomAuthzDecisionStatementsProvider.
640     */
641    public String getCustomAuthzDecisionStatementsProviderClassName() {
642        return customAuthzDecisionStatementsProviderClassName;
643    }
644
645    /**
646     * Gets whether the assertion should be signed.
647     *
648     * @return whether the assertion should be signed.
649     */
650    public boolean signAssertion() {
651        return signAssertion;
652    }
653
654    /**
655     * Gets whether the name-id should be encrypted.
656     *
657     * @return whether the name-id should be encrypted.
658     */
659    public boolean encryptNameID() {
660        return encryptNameID;
661    }
662
663    /**
664     * Gets whether the attributes should be encrypted.
665     *
666     * @return whether the attributes should be encrypted.
667     */
668    public boolean encryptAttributes() {
669        return encryptAttributes;
670    }
671
672    /**
673     * Gets whether the assertion should be encrypted.
674     *
675     * @return whether the assertion should be encrypted.
676     */
677    public boolean encryptAssertion() {
678        return encryptAssertion;
679    }
680
681    /**
682     * Gets the encryption algorithm.
683     *
684     * @return the encryption algorithm.
685     */
686    public String getEncryptionAlgorithm() {
687        return encryptionAlgorithm;
688    }
689
690    /**
691     * Gets the encryption algorithm strength.
692     *
693     * @return the encryption algorithm strength.
694     */
695    public int getEncryptionAlgorithmStrength() {
696        return encryptionAlgorithmStrength;
697    }
698
699    /**
700     * Gets the keystore filename.
701     *
702     * @return the keystore filename.
703     */
704    public String getKeystoreFileName() {
705        return keystoreFileName;
706    }
707
708    /**
709     * Gets the keystore password.
710     *
711     * @return they keystore password.
712     */
713    public byte[] getKeystorePassword() {
714        return keystorePassword;
715    }
716
717    /**
718     * Gets the SP entity id.
719     *
720     * @return the SP entity id.
721     */
722    public String getSpEntityId() {
723        return spEntityId;
724    }
725
726    /**
727     * Gets the SP ACS url.
728     *
729     * @return the SP ACS url.
730     */
731    public String getSpAcsUrl() {
732        return spAcsUrl;
733    }
734
735    /**
736     * Gets the encryption key alias.
737     *
738     * @return the encryption key alias.
739     */
740    public String getEncryptionKeyAlias() {
741        return encryptionKeyAlias;
742    }
743
744    /**
745     * Gets the signature key alias.
746     *
747     * @return the signature key alias.
748     */
749    public String getSignatureKeyAlias() {
750        return signatureKeyAlias;
751    }
752
753    /**
754     * Gets the signature key password.
755     *
756     * @return the signature key password.
757     */
758    public byte[] getSignatureKeyPassword() {
759        return signatureKeyPassword;
760    }
761
762    /**
763     * Gets the Identity Provider id.
764     *
765     * @return the Identity Provider id.
766     */
767    public String getIdpId() {
768        return idpId;
769    }
770
771    /**
772     * {@inheritDoc}
773     */
774    @Override
775    public String toString() {
776        StringBuilder sb = new StringBuilder();
777        sb.append("SAML2Config instance:").append('\n');
778        sb.append('\t').append("IDP id: ").append(idpId).append('\n');
779        sb.append('\t').append("nameIDFormat: ").append(nameIdFormat).append('\n');
780        sb.append('\t').append("attributeMap: ").append(attributeMap).append('\n');
781        sb.append('\t').append("tokenLifetimeInSeconds: ").append(tokenLifetimeInSeconds).append('\n');
782        sb.append('\t').append("customConditionsProviderClassName: ").append(customConditionsProviderClassName).append('\n');
783        sb.append('\t').append("customSubjectProviderClassName: ").append(customSubjectProviderClassName).append('\n');
784        sb.append('\t').append("customAttributeStatementsProviderClassName: ").append(customAttributeStatementsProviderClassName).append('\n');
785        sb.append('\t').append("customAttributeMapperClassName: ").append(customAttributeMapperClassName).append('\n');
786        sb.append('\t').append("customAuthNContextMapperClassName: ").append(customAuthNContextMapperClassName).append('\n');
787        sb.append('\t').append("customAuthenticationStatementsProviderClassName: ").append(customAuthenticationStatementsProviderClassName).append('\n');
788        sb.append('\t').append("customAuthzDecisionStatementsProviderClassName: ").append(customAuthzDecisionStatementsProviderClassName).append('\n');
789        sb.append('\t').append("Sign assertion ").append(signAssertion).append('\n');
790        sb.append('\t').append("Encrypt NameID ").append(encryptNameID).append('\n');
791        sb.append('\t').append("Encrypt Attributes ").append(encryptAttributes).append('\n');
792        sb.append('\t').append("Encrypt Assertion ").append(encryptAssertion).append('\n');
793        sb.append('\t').append("Encryption Algorithm ").append(encryptionAlgorithm).append('\n');
794        sb.append('\t').append("Encryption Algorithm Strength ").append(encryptionAlgorithmStrength).append('\n');
795        sb.append('\t').append("Keystore File ").append(keystoreFileName).append('\n');
796        sb.append('\t').append("Keystore Password ").append("xxx").append('\n');
797        sb.append('\t').append("SP Entity Id ").append(spEntityId).append('\n');
798        sb.append('\t').append("SP ACS URL ").append(spAcsUrl).append('\n');
799        sb.append('\t').append("Encryption key alias ").append(encryptionKeyAlias).append('\n');
800        sb.append('\t').append("Signature key alias").append(signatureKeyAlias).append('\n');
801        return sb.toString();
802    }
803
804    /**
805     * {@inheritDoc}
806     */
807    @Override
808    public boolean equals(Object other) {
809        if (other instanceof SAML2Config) {
810            SAML2Config otherConfig = (SAML2Config)other;
811            return  nameIdFormat.equals(otherConfig.nameIdFormat) &&
812                    idpId.equals(otherConfig.idpId) &&
813                    tokenLifetimeInSeconds == otherConfig.tokenLifetimeInSeconds &&
814                    attributeMap.equals(otherConfig.attributeMap) &&
815                    signAssertion == otherConfig.signAssertion &&
816                    encryptAssertion == otherConfig.encryptAssertion &&
817                    encryptAttributes == otherConfig.encryptAttributes &&
818                    encryptNameID == otherConfig.encryptNameID &&
819                    encryptionAlgorithmStrength == otherConfig.encryptionAlgorithmStrength &&
820                    spEntityId.equals(otherConfig.spEntityId) &&
821                    Objects.equal(encryptionAlgorithm, otherConfig.encryptionAlgorithm) &&
822                    Objects.equal(customConditionsProviderClassName, otherConfig.customConditionsProviderClassName) &&
823                    Objects.equal(customSubjectProviderClassName, otherConfig.customSubjectProviderClassName) &&
824                    Objects.equal(customAttributeStatementsProviderClassName, otherConfig.customAttributeStatementsProviderClassName) &&
825                    Objects.equal(customAuthzDecisionStatementsProviderClassName, otherConfig.customAuthzDecisionStatementsProviderClassName) &&
826                    Objects.equal(customAttributeMapperClassName, otherConfig.customAttributeMapperClassName) &&
827                    Objects.equal(customAuthNContextMapperClassName, otherConfig.customAuthNContextMapperClassName) &&
828                    Objects.equal(customAuthenticationStatementsProviderClassName, otherConfig.customAuthenticationStatementsProviderClassName) &&
829                    Objects.equal(keystoreFileName, otherConfig.keystoreFileName) &&
830                    Arrays.equals(keystorePassword, otherConfig.keystorePassword) &&
831                    Objects.equal(spAcsUrl, otherConfig.spAcsUrl) &&
832                    Objects.equal(signatureKeyAlias, otherConfig.signatureKeyAlias) &&
833                    Objects.equal(encryptionKeyAlias, otherConfig.encryptionKeyAlias) &&
834                    Arrays.equals(signatureKeyPassword, otherConfig.signatureKeyPassword);
835        }
836        return false;
837    }
838
839    /**
840     * {@inheritDoc}
841     */
842    @Override
843    public int hashCode() {
844        return (nameIdFormat + attributeMap + spEntityId + Long.toString(tokenLifetimeInSeconds)).hashCode();
845    }
846
847    /**
848     * Gets the {@link JsonValue} representation of the SAML2Config.
849     *
850     * @return The {@link JsonValue} representation of the SAML2Config.
851     */
852    public JsonValue toJson() {
853        /*
854        Because toJson will be used to produce the map that will also be used to marshal to the SMS attribute map
855        format, and because the SMS attribute map format represents all values as Set<String>, I need to represent all
856        of the json values as strings as well.
857        */
858        try {
859            return json(object(
860                    field(ISSUER_NAME, idpId),
861                    field(NAME_ID_FORMAT, nameIdFormat),
862                    field(TOKEN_LIFETIME, String.valueOf(tokenLifetimeInSeconds)),
863                    field(CUSTOM_CONDITIONS_PROVIDER_CLASS, customConditionsProviderClassName),
864                    field(CUSTOM_SUBJECT_PROVIDER_CLASS, customSubjectProviderClassName),
865                    field(CUSTOM_ATTRIBUTE_STATEMENTS_PROVIDER_CLASS, customAttributeStatementsProviderClassName),
866                    field(CUSTOM_ATTRIBUTE_MAPPER_CLASS, customAttributeMapperClassName),
867                    field(CUSTOM_AUTHN_CONTEXT_MAPPER_CLASS, customAuthNContextMapperClassName),
868                    field(CUSTOM_AUTHENTICATION_STATEMENTS_PROVIDER_CLASS, customAuthenticationStatementsProviderClassName),
869                    field(CUSTOM_AUTHZ_DECISION_STATEMENTS_PROVIDER_CLASS, customAuthzDecisionStatementsProviderClassName),
870                    field(SIGN_ASSERTION, String.valueOf(signAssertion)),
871                    field(ENCRYPT_ASSERTION, String.valueOf(encryptAssertion)),
872                    field(ENCRYPT_ATTRIBUTES, String.valueOf(encryptAttributes)),
873                    field(ENCRYPT_NAME_ID, String.valueOf(encryptNameID)),
874                    field(ENCRYPTION_ALGORITHM, encryptionAlgorithm),
875                    field(ENCRYPTION_ALGORITHM_STRENGTH, String.valueOf(encryptionAlgorithmStrength)),
876                    field(ATTRIBUTE_MAP, attributeMap),
877                    field(KEYSTORE_FILE_NAME, keystoreFileName),
878                    field(KEYSTORE_PASSWORD,
879                            keystorePassword != null ? new String(keystorePassword, AMSTSConstants.UTF_8_CHARSET_ID) : null),
880                    field(SP_ACS_URL, spAcsUrl),
881                    field(SP_ENTITY_ID, spEntityId),
882                    field(SIGNATURE_KEY_ALIAS, signatureKeyAlias),
883                    field(SIGNATURE_KEY_PASSWORD,
884                            signatureKeyPassword != null ? new String(signatureKeyPassword, AMSTSConstants.UTF_8_CHARSET_ID) : null),
885                    field(ENCRYPTION_KEY_ALIAS, encryptionKeyAlias)));
886        } catch (UnsupportedEncodingException e) {
887            throw new IllegalStateException("Unsupported encoding when marshalling from String to to byte[]: " + e, e);
888        }
889    }
890
891    /**
892     * Creates a SAML2Config object from a {@link JsonValue} representation
893     *
894     * @param json the {@link JsonValue} representation.
895     * @return a SAML2Config object
896     * @throws IllegalStateException
897     */
898    public static SAML2Config fromJson(JsonValue json) throws IllegalStateException {
899        try {
900            return SAML2Config.builder()
901                    .idpId(json.get(ISSUER_NAME).asString())
902                    .nameIdFormat(json.get(NAME_ID_FORMAT).asString())
903                    //because we have to go to the SMS Map representation, where all values are Set<String>, I need to
904                    // pull the value from Json as a string, and then parse out a Long.
905                    .tokenLifetimeInSeconds(Long.valueOf(json.get(TOKEN_LIFETIME).asString()))
906                    .customConditionsProviderClassName(json.get(CUSTOM_CONDITIONS_PROVIDER_CLASS).asString())
907                    .customSubjectProviderClassName(json.get(CUSTOM_SUBJECT_PROVIDER_CLASS).asString())
908                    .customAttributeStatementsProviderClassName(json.get(CUSTOM_ATTRIBUTE_STATEMENTS_PROVIDER_CLASS).asString())
909                    .customAttributeMapperClassName(json.get(CUSTOM_ATTRIBUTE_MAPPER_CLASS).asString())
910                    .customAuthNContextMapperClassName(json.get(CUSTOM_AUTHN_CONTEXT_MAPPER_CLASS).asString())
911                    .customAuthenticationStatementsProviderClassName(json.get(CUSTOM_AUTHENTICATION_STATEMENTS_PROVIDER_CLASS).asString())
912                    .customAuthzDecisionStatementsProviderClassName(json.get(CUSTOM_AUTHZ_DECISION_STATEMENTS_PROVIDER_CLASS).asString())
913                    .signAssertion(Boolean.valueOf(json.get(SIGN_ASSERTION).asString()))
914                    .encryptAssertion(Boolean.valueOf(json.get(ENCRYPT_ASSERTION).asString()))
915                    .encryptNameID(Boolean.valueOf(json.get(ENCRYPT_NAME_ID).asString()))
916                    .encryptAttributes(Boolean.valueOf(json.get(ENCRYPT_ATTRIBUTES).asString()))
917                    .encryptionAlgorithm(json.get(ENCRYPTION_ALGORITHM).asString())
918                    .encryptionAlgorithmStrength(Integer.valueOf(json.get(ENCRYPTION_ALGORITHM_STRENGTH).asString()))
919                    .attributeMap(json.get(ATTRIBUTE_MAP).asMap(String.class))
920                    .keystoreFile(json.get(KEYSTORE_FILE_NAME).asString())
921                    .keystorePassword(json.get(KEYSTORE_PASSWORD).isString()
922                            ? json.get(KEYSTORE_PASSWORD).asString().getBytes(AMSTSConstants.UTF_8_CHARSET_ID) : null)
923                    .signatureKeyPassword(json.get(SIGNATURE_KEY_PASSWORD).isString()
924                            ? json.get(SIGNATURE_KEY_PASSWORD).asString().getBytes(AMSTSConstants.UTF_8_CHARSET_ID) : null)
925                    .signatureKeyAlias(json.get(SIGNATURE_KEY_ALIAS).asString())
926                    .spAcsUrl(json.get(SP_ACS_URL).asString())
927                    .spEntityId(json.get(SP_ENTITY_ID).asString())
928                    .encryptionKeyAlias(json.get(ENCRYPTION_KEY_ALIAS).asString())
929                    .build();
930        } catch (UnsupportedEncodingException e) {
931            throw new IllegalStateException("Unsupported encoding when marshalling from String to to byte[]: " + e, e);
932        }
933    }
934
935    /**
936     * Marshals the SAML2Config into an attribute map
937     *
938     * @return a map containing the SAML2Config attributes.
939     */
940    public Map<String, Set<String>> marshalToAttributeMap() {
941        /*
942        We need to marshal the SAML2Config instance to a Map<String, Object>. The JsonValue of toJson gets us there,
943        except for the complex types for the audiences and attribute map. These need to be marshaled into aSet<String>,
944        and these entries included in the top-level map, replacing the existing complex entries.
945        */
946        Map<String, Object> preMap = toJson().asMap();
947        Map<String, Set<String>> finalMap = MapMarshallUtils.toSmsMap(preMap);
948        Object attributesObject = preMap.get(ATTRIBUTE_MAP);
949        if (attributesObject instanceof Map) {
950            finalMap.remove(ATTRIBUTE_MAP);
951            Set<String> attributeValues = new LinkedHashSet<>();
952            finalMap.put(ATTRIBUTE_MAP, attributeValues);
953            for (Map.Entry<String, String> entry : ((Map<String, String>)attributesObject).entrySet()) {
954                attributeValues.add(entry.getKey() + EQUALS + entry.getValue());
955            }
956        } else {
957            throw new IllegalStateException("Type corresponding to " + ATTRIBUTE_MAP + " key unexpected. Type: "
958                    + (attributesObject != null ? attributesObject.getClass().getName() :" null"));
959        }
960        return finalMap;
961    }
962
963    /**
964     * Marshals an attribute map into a SAML2Config
965     *
966     * @param smsAttributeMap the attribute map.
967     * @return a SAML2Config object.
968     */
969    public static SAML2Config marshalFromAttributeMap(Map<String, Set<String>> smsAttributeMap) {
970        /*
971        Here we have to modify the ATTRIBUTE_MAP and AUDIENCES entries to match the JsonValue format expected by
972        fromJson, and then call the static fromJson. This method must marshal between the Json representation of a
973        complex object, and the representation expected by the SMS
974        */
975        Set<String> issuerName = smsAttributeMap.get(ISSUER_NAME);
976        /*
977        The STSInstanceConfig may not have SAML2Config, if there are no defined token transformations that result
978        in a SAML2 assertion. So we check for the ISSUER_NAME attribute, which is the IdP id, a mandatory field if
979        SAML2 assertions are to be issued.
980         */
981        if (CollectionUtils.isEmpty(issuerName)) {
982            return null;
983        }
984        Map<String, Object> jsonAttributes = MapMarshallUtils.toJsonValueMap(smsAttributeMap);
985        jsonAttributes.remove(ATTRIBUTE_MAP);
986        Set<String> attributes = smsAttributeMap.get(ATTRIBUTE_MAP);
987        Map<String, Object> jsonAttributeMap = new LinkedHashMap<>();
988        for (String entry : attributes) {
989            String[] breakdown = entry.split(EQUALS);
990            jsonAttributeMap.put(breakdown[0], breakdown[1]);
991        }
992        jsonAttributes.put(ATTRIBUTE_MAP, new JsonValue(jsonAttributeMap));
993
994        return fromJson(new JsonValue(jsonAttributes));
995    }
996
997    /**
998     * Returns an empty attribute map.
999     *
1000     * @return an empty attribute map.
1001     */
1002    public static Map<String, Set<String>> getEmptySMSAttributeState() {
1003        /*
1004        This method is called from Rest/SoapSTSInstanceConfig if the encapsulated SAML2Config reference is null. It
1005        should return a Map<String,Set<String>> for each of the sms attributes defined for the SAML2Config object, with
1006        an empty Set<String> value, so that SMS writes will over-write any previous, non-null values. This will occur
1007        in the AdminUI when a sts instance goes from issuing SAML2 tokens, to not issuing these token types.
1008        */
1009        HashMap<String, Set<String>> emptyAttributeMap = new HashMap<>();
1010        emptyAttributeMap.put(NAME_ID_FORMAT, Collections.<String>emptySet());
1011        emptyAttributeMap.put(ATTRIBUTE_MAP, Collections.<String>emptySet());
1012        emptyAttributeMap.put(TOKEN_LIFETIME, Collections.<String>emptySet());
1013        emptyAttributeMap.put(CUSTOM_CONDITIONS_PROVIDER_CLASS, Collections.<String>emptySet());
1014        emptyAttributeMap.put(CUSTOM_SUBJECT_PROVIDER_CLASS, Collections.<String>emptySet());
1015        emptyAttributeMap.put(CUSTOM_ATTRIBUTE_STATEMENTS_PROVIDER_CLASS, Collections.<String>emptySet());
1016        emptyAttributeMap.put(CUSTOM_AUTHENTICATION_STATEMENTS_PROVIDER_CLASS, Collections.<String>emptySet());
1017        emptyAttributeMap.put(CUSTOM_AUTHZ_DECISION_STATEMENTS_PROVIDER_CLASS, Collections.<String>emptySet());
1018        emptyAttributeMap.put(CUSTOM_ATTRIBUTE_MAPPER_CLASS, Collections.<String>emptySet());
1019        emptyAttributeMap.put(CUSTOM_AUTHN_CONTEXT_MAPPER_CLASS, Collections.<String>emptySet());
1020        emptyAttributeMap.put(SIGN_ASSERTION, Collections.<String>emptySet());
1021        emptyAttributeMap.put(ENCRYPT_ATTRIBUTES, Collections.<String>emptySet());
1022        emptyAttributeMap.put(ENCRYPT_NAME_ID, Collections.<String>emptySet());
1023        emptyAttributeMap.put(ENCRYPT_ASSERTION, Collections.<String>emptySet());
1024        emptyAttributeMap.put(ENCRYPTION_ALGORITHM, Collections.<String>emptySet());
1025        emptyAttributeMap.put(ENCRYPTION_ALGORITHM_STRENGTH, Collections.<String>emptySet());
1026        emptyAttributeMap.put(KEYSTORE_FILE_NAME, Collections.<String>emptySet());
1027        emptyAttributeMap.put(KEYSTORE_PASSWORD, Collections.<String>emptySet());
1028        emptyAttributeMap.put(SP_ENTITY_ID, Collections.<String>emptySet());
1029        emptyAttributeMap.put(SP_ACS_URL, Collections.<String>emptySet());
1030        emptyAttributeMap.put(ENCRYPTION_KEY_ALIAS, Collections.<String>emptySet());
1031        emptyAttributeMap.put(SIGNATURE_KEY_ALIAS, Collections.<String>emptySet());
1032        emptyAttributeMap.put(SIGNATURE_KEY_PASSWORD, Collections.<String>emptySet());
1033        emptyAttributeMap.put(ISSUER_NAME, Collections.<String>emptySet());
1034        return emptyAttributeMap;
1035    }
1036}