/* * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except * in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.wso2.carbon.identity.provisioning.connector.spml; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openspml.v2.client.Spml2Client; import org.openspml.v2.msg.spml.AddRequest; import org.openspml.v2.msg.spml.AddResponse; import org.openspml.v2.msg.spml.DeleteRequest; import org.openspml.v2.msg.spml.DeleteResponse; import org.openspml.v2.msg.spml.Extensible; import org.openspml.v2.msg.spml.Modification; import org.openspml.v2.msg.spml.ModifyRequest; import org.openspml.v2.msg.spml.ModifyResponse; import org.openspml.v2.msg.spml.PSO; import org.openspml.v2.msg.spml.PSOIdentifier; import org.openspml.v2.msg.spml.ReturnData; import org.openspml.v2.msg.spml.StatusCode; import org.openspml.v2.profiles.dsml.DSMLAttr; import org.openspml.v2.util.Spml2Exception; import org.openspml.v2.util.xml.ReflectiveXMLMarshaller; import org.wso2.carbon.identity.application.common.model.Property; import org.wso2.carbon.identity.provisioning.AbstractOutboundProvisioningConnector; import org.wso2.carbon.identity.provisioning.IdentityProvisioningConstants; import org.wso2.carbon.identity.provisioning.IdentityProvisioningException; import org.wso2.carbon.identity.provisioning.ProvisionedIdentifier; import org.wso2.carbon.identity.provisioning.ProvisioningEntity; import org.wso2.carbon.identity.provisioning.ProvisioningEntityType; import org.wso2.carbon.identity.provisioning.ProvisioningOperation; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.UUID; public class SPMLProvisioningConnector extends AbstractOutboundProvisioningConnector { private static final long serialVersionUID = -1046148327813739881L; private static final Log log = LogFactory.getLog(SPMLProvisioningConnector.class); private SPMLProvisioningConnectorConfig configHolder; @Override public void init(Property[] provisioningProperties) throws IdentityProvisioningException { Properties configs = new Properties(); if (provisioningProperties != null && provisioningProperties.length > 0) { for (Property property : provisioningProperties) { configs.put(property.getName(), property.getValue()); if (IdentityProvisioningConstants.JIT_PROVISIONING_ENABLED.equals(property .getName()) && "1".equals(property.getValue())){ jitProvisioningEnabled = true; } } } configHolder = new SPMLProvisioningConnectorConfig(configs); } @Override public ProvisionedIdentifier provision(ProvisioningEntity provisioningEntity) throws IdentityProvisioningException { String provisionedId = null; if (provisioningEntity.isJitProvisioning() && !isJitProvisioningEnabled()) { log.debug("JIT provisioning disabled for SPML connector"); return null; } if (provisioningEntity != null) { if (provisioningEntity.getEntityType() == ProvisioningEntityType.USER) { if (provisioningEntity.getOperation() == ProvisioningOperation.DELETE) { deleteUser(provisioningEntity); } else if (provisioningEntity.getOperation() == ProvisioningOperation.PUT) { updateUser(provisioningEntity); } else if (provisioningEntity.getOperation() == ProvisioningOperation.POST) { provisionedId = createUser(provisioningEntity); } else { log.warn("Unsupported provisioning opertaion."); } } else { log.warn("Unsupported provisioning opertaion."); } } // creates a provisioned identifier for the provisioned user. ProvisionedIdentifier identifier = new ProvisionedIdentifier(); identifier.setIdentifier(provisionedId); return identifier; } /** * @param provisioningEntity */ private void updateUser(ProvisioningEntity provisioningEntity) { boolean isDebugEnabled = log.isDebugEnabled(); String provisioningIdentifier = null; try { ReflectiveXMLMarshaller marshaller = new ReflectiveXMLMarshaller(); Spml2Client spml2Client = new Spml2Client(configHolder.getValue("spml-ep")); spml2Client.setTrace(log.isDebugEnabled()); spml2Client.setSOAPAction("SPMLModifyRequest"); if (provisioningEntity != null && provisioningEntity.getIdentifier() != null) { provisioningIdentifier = provisioningEntity.getIdentifier().getIdentifier(); } else { if (isDebugEnabled) { log.debug("User updating faild. No provisioning identifier"); } return; } PSOIdentifier psoId = new PSOIdentifier(provisioningIdentifier, null, null); ModifyRequest modifyRequest = new ModifyRequest(); modifyRequest.setPsoID(psoId); Modification modification = new Modification(); Map<String, String> claims = getSingleValuedClaims(provisioningEntity.getAttributes()); Iterator claimsKeySet = claims.entrySet().iterator(); while (claimsKeySet.hasNext()) { Map.Entry pairs = (Map.Entry) claimsKeySet.next(); modification.addOpenContentElement(new DSMLAttr(pairs.getKey().toString(), pairs.getValue().toString())); } modifyRequest.addModification(modification); if (isDebugEnabled) { log.debug("Sent SPML request:" + modifyRequest.toXML(marshaller)); } ModifyResponse modifyResponse = (ModifyResponse) spml2Client.send(modifyRequest); if (modifyResponse.getStatus().equals(StatusCode.SUCCESS)) { if (isDebugEnabled) { log.debug("User updated successfully."); } } else { log.warn("SPML user update failed."); } } catch (Spml2Exception e) { log.error("Error while SPML user updating", e); } if (log.isTraceEnabled()) { log.trace("SPML user updated."); } } /** * @param provisioningEntity * @return * @throws IdentityProvisioningException */ private String createUser(ProvisioningEntity provisioningEntity) throws IdentityProvisioningException { boolean isDebugEnabled = log.isDebugEnabled(); String psoIdString = null; List<String> userNames = getUserNames(provisioningEntity.getAttributes()); String userName = null; if (CollectionUtils.isNotEmpty(userNames)) { // first element must be the user name. userName = userNames.get(0); } try { ReflectiveXMLMarshaller marshaller = new ReflectiveXMLMarshaller(); Spml2Client spml2Client = new Spml2Client(configHolder.getValue("spml-ep")); spml2Client.setTrace(log.isDebugEnabled()); AddRequest req = new AddRequest(); req.setReturnData(ReturnData.IDENTIFIER); Extensible attrs = new Extensible(); attrs.addOpenContentElement(new DSMLAttr("objectclass", configHolder .getValue("spml-oc"))); attrs.addOpenContentElement(new DSMLAttr("accountId", userName)); attrs.addOpenContentElement(new DSMLAttr("credentials", UUID.randomUUID().toString())); List<String> extractAttributes = configHolder.extractAttributes(); // get user attributes. Map<String, String> claims = getSingleValuedClaims(provisioningEntity.getAttributes()); Iterator claimsKeySet = claims.entrySet().iterator(); while (claimsKeySet.hasNext()) { Map.Entry pairs = (Map.Entry) claimsKeySet.next(); attrs.addOpenContentElement(new DSMLAttr(pairs.getKey().toString(), pairs.getValue().toString())); } req.setData(attrs); if (isDebugEnabled) { log.debug("Sent SPML request:" + req.toXML(marshaller)); } spml2Client.setSOAPAction("SPMLAddRequest"); AddResponse res = (AddResponse) spml2Client.send(req); if (res != null && res.getStatus().equals(StatusCode.SUCCESS)) { if (isDebugEnabled) { log.debug("Recived positive add response of " + userName); } PSO pso = res.getPso(); PSOIdentifier psoId = pso.getPsoID(); psoIdString = psoId.getID(); } else { throw new IdentityProvisioningException( "SPML provisioning failed. Invalid Response."); } } catch (Spml2Exception e) { log.error("Error while SPML provisioning", e); } if (log.isTraceEnabled()) { log.trace("SPML user provisioned."); } return psoIdString; } /** * @param provisioningEntity */ private void deleteUser(ProvisioningEntity provisioningEntity) { boolean isDebugEnabled = log.isDebugEnabled(); String provisioningIdentifier = null; try { ReflectiveXMLMarshaller marshaller = new ReflectiveXMLMarshaller(); Spml2Client spml2Client = new Spml2Client(configHolder.getValue("spml-ep")); spml2Client.setTrace(log.isDebugEnabled()); spml2Client.setSOAPAction("SPMLDeleteRequest"); if (provisioningEntity != null && provisioningEntity.getIdentifier() != null) { provisioningIdentifier = provisioningEntity.getIdentifier().getIdentifier(); } else { if (isDebugEnabled) { log.debug("User de-provisioned faild. No provisioning identifier"); } return; } PSOIdentifier psoId = new PSOIdentifier(provisioningIdentifier, null, null); DeleteRequest deleteRequest = new DeleteRequest(); deleteRequest.setPsoID(psoId); if (isDebugEnabled) { log.debug("Sent SPML request:" + deleteRequest.toXML(marshaller)); } DeleteResponse deleteResponse = (DeleteResponse) spml2Client.send(deleteRequest); if (deleteResponse.getStatus().equals(StatusCode.SUCCESS)) { if (isDebugEnabled) { log.debug("User de-provisioned successfully."); } } else { log.warn("SPML user provisioning failed."); } } catch (Spml2Exception e) { log.error("Error while SPML de-provisioning", e); } if (log.isTraceEnabled()) { log.trace("SPML user de-provisioned."); } } }