/** * Updates signing or encryption key info for SP or IDP. This will update both signing/encryption * alias on extended metadata and certificates in standard metadata. * * @param realm Realm the entity resides. * @param entityID ID of the entity to be updated. * @param certAlias Alias of the certificate to be set to the entity. If null, will remove * existing key information from the SP or IDP. * @param isSigning true if this is signing certificate alias, false if this is encryption * certification alias. * @param isIDP true if this is for IDP signing/encryption alias, false if this is for SP * signing/encryption alias * @param encAlgo Encryption algorithm URI, this is applicable for encryption cert only. * @param keySize Encryption key size, this is applicable for encryption cert only. * @throws SAML2MetaException if failed to update the certificate alias for the entity. */ public static void updateProviderKeyInfo( String realm, String entityID, String certAlias, boolean isSigning, boolean isIDP, String encAlgo, int keySize) throws SAML2MetaException { SAML2MetaManager metaManager = new SAML2MetaManager(); EntityConfigElement config = metaManager.getEntityConfig(realm, entityID); if (!config.isHosted()) { String[] args = {entityID, realm}; throw new SAML2MetaException("entityNotHosted", args); } EntityDescriptorElement desp = metaManager.getEntityDescriptor(realm, entityID); if (isIDP) { IDPSSOConfigElement idpConfig = SAML2MetaUtils.getIDPSSOConfig(config); IDPSSODescriptorElement idpDesp = SAML2MetaUtils.getIDPSSODescriptor(desp); if ((idpConfig == null) || (idpDesp == null)) { String[] args = {entityID, realm}; throw new SAML2MetaException("entityNotIDP", args); } // update standard metadata if ((certAlias == null) || (certAlias.length() == 0)) { // remove key info removeKeyDescriptor(idpDesp, isSigning); if (isSigning) { setExtendedAttributeValue(idpConfig, SAML2Constants.SIGNING_CERT_ALIAS, null); } else { setExtendedAttributeValue(idpConfig, SAML2Constants.ENCRYPTION_CERT_ALIAS, null); } } else { KeyDescriptorElement kde = getKeyDescriptor(certAlias, isSigning, encAlgo, keySize); updateKeyDescriptor(idpDesp, kde); // update extended metadata Set value = new HashSet(); value.add(certAlias); if (isSigning) { setExtendedAttributeValue(idpConfig, SAML2Constants.SIGNING_CERT_ALIAS, value); } else { setExtendedAttributeValue(idpConfig, SAML2Constants.ENCRYPTION_CERT_ALIAS, value); } } metaManager.setEntityDescriptor(realm, desp); metaManager.setEntityConfig(realm, config); } else { SPSSOConfigElement spConfig = SAML2MetaUtils.getSPSSOConfig(config); SPSSODescriptorElement spDesp = SAML2MetaUtils.getSPSSODescriptor(desp); if ((spConfig == null) || (spDesp == null)) { String[] args = {entityID, realm}; throw new SAML2MetaException("entityNotSP", args); } // update standard metadata if ((certAlias == null) || (certAlias.length() == 0)) { // remove key info removeKeyDescriptor(spDesp, isSigning); if (isSigning) { setExtendedAttributeValue(spConfig, SAML2Constants.SIGNING_CERT_ALIAS, null); } else { setExtendedAttributeValue(spConfig, SAML2Constants.ENCRYPTION_CERT_ALIAS, null); } } else { KeyDescriptorElement kde = getKeyDescriptor(certAlias, isSigning, encAlgo, keySize); updateKeyDescriptor(spDesp, kde); // update extended metadata Set value = new HashSet(); value.add(certAlias); if (isSigning) { setExtendedAttributeValue(spConfig, SAML2Constants.SIGNING_CERT_ALIAS, value); } else { setExtendedAttributeValue(spConfig, SAML2Constants.ENCRYPTION_CERT_ALIAS, value); } } metaManager.setEntityDescriptor(realm, desp); metaManager.setEntityConfig(realm, config); } }
/** * Signs the entity descriptor root element by the following rules: * * <ul> * <li>Hosted Entity * <ul> * <li>If there is a signature already on the EntityDescriptor, removes it, then signs the * EntityDescriptor. * <li>Simply signs the EntityDescriptor otherwise. * </ul> * <li>Remote Entity * <ul> * <li>If there is a signature already on the EntityDescriptor, then does not change it, * but returns the Document with the original signature. * <li>Simply signs the EntityDescriptor otherwise * </ul> * </ul> * * If there is no extended metadata for the entity, the entity is considered as remote. * * @param realm The realm where the EntityDescriptor belongs to. * @param descriptor The entity descriptor. * @return Signed <code>Document</code> for the entity descriptor or null if no metadata signing * key is found in the configuration. * @throws SAML2MetaException if unable to sign the entity descriptor. * @throws JAXBException if the entity descriptor is invalid. */ public static Document sign(String realm, EntityDescriptorElement descriptor) throws JAXBException, SAML2MetaException { if (descriptor == null) { throw new SAML2MetaException("Unable to sign null descriptor"); } SAML2MetaManager metaManager = new SAML2MetaManager(); EntityConfigElement cfgElem = metaManager.getEntityConfig(realm, descriptor.getEntityID()); boolean isHosted; if (cfgElem == null) { // if there is no EntityConfig, this is considered as a remote entity isHosted = false; } else { isHosted = cfgElem.isHosted(); } String signingCert = getRealmSetting(METADATA_SIGNING_KEY, realm); if (signingCert == null) { return null; } initializeKeyStore(); String xmlstr = SAML2MetaUtils.convertJAXBToString(descriptor); xmlstr = formatBase64BinaryElement(xmlstr); Document doc = XMLUtils.toDOMDocument(xmlstr, debug); NodeList childNodes = doc.getDocumentElement().getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node node = childNodes.item(i); if (node.getLocalName() != null && node.getLocalName().equals("Signature") && node.getNamespaceURI().equals(NS_XMLSIG)) { if (isHosted) { node.getParentNode().removeChild(node); break; } else { // one signature found for this remote entity on the root element, // in this case returning the entry with the original signature // as that may be judged more accurately return doc; } } } // we need to sign or re-sign the document, let's generate a new ID String descriptorId = SAMLUtils.generateID(); doc.getDocumentElement().setAttribute(ATTR_ID, descriptorId); XMLSignatureManager sigManager = XMLSignatureManager.getInstance(); try { String xpath = "//*[local-name()=\"" + TAG_ENTITY_DESCRIPTOR + "\" and namespace-uri()=\"" + NS_META + "\"]/*[1]"; sigManager.signXMLUsingKeyPass( doc, signingCert, getRealmSetting(METADATA_SIGNING_KEY_PASS, realm), null, SAML2Constants.ID, descriptorId, true, xpath); } catch (XMLSignatureException xmlse) { if (debug.messageEnabled()) { debug.message("SAML2MetaSecurityUtils.sign:", xmlse); } } return doc; }