use of org.apache.syncope.common.lib.to.AttrTO in project syncope by apache.
the class PullTaskITCase method issueSYNCOPE1062.
@Test
public void issueSYNCOPE1062() {
GroupTO propagationGroup = null;
PullTaskTO pullTask = null;
UserTO user = null;
GroupTO group = null;
try {
// 1. create group with resource for propagation
propagationGroup = GroupITCase.getBasicSampleTO("SYNCOPE1062");
propagationGroup.getResources().add(RESOURCE_NAME_DBPULL);
propagationGroup = createGroup(propagationGroup).getEntity();
// 2. create pull task for another resource, with user template assigning the group above
pullTask = new PullTaskTO();
pullTask.setDestinationRealm(SyncopeConstants.ROOT_REALM);
pullTask.setName("SYNCOPE1062");
pullTask.setActive(true);
pullTask.setPerformCreate(true);
pullTask.setPerformUpdate(true);
pullTask.setPullMode(PullMode.FULL_RECONCILIATION);
pullTask.setResource(RESOURCE_NAME_LDAP);
UserTO template = new UserTO();
template.getAuxClasses().add("minimal group");
template.getMemberships().add(new MembershipTO.Builder().group(propagationGroup.getKey()).build());
template.getPlainAttrs().add(attrTO("firstname", "'fixed'"));
pullTask.getTemplates().put(AnyTypeKind.USER.name(), template);
Response taskResponse = taskService.create(TaskType.PULL, pullTask);
pullTask = getObject(taskResponse.getLocation(), TaskService.class, PullTaskTO.class);
assertNotNull(pullTask);
assertFalse(pullTask.getTemplates().isEmpty());
// 3. exec the pull task
ExecTO execution = execProvisioningTask(taskService, TaskType.PULL, pullTask.getKey(), 50, false);
assertEquals(PropagationTaskExecStatus.SUCCESS, PropagationTaskExecStatus.valueOf(execution.getStatus()));
// the user is successfully pulled...
user = userService.read("pullFromLDAP");
assertNotNull(user);
assertEquals("pullFromLDAP@syncope.apache.org", user.getPlainAttr("email").get().getValues().get(0));
group = groupService.read("testLDAPGroup");
assertNotNull(group);
ConnObjectTO connObject = resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.USER.name(), user.getKey());
assertNotNull(connObject);
assertEquals("pullFromLDAP@syncope.apache.org", connObject.getAttr("mail").get().getValues().get(0));
AttrTO userDn = connObject.getAttr(Name.NAME).get();
assertNotNull(userDn);
assertEquals(1, userDn.getValues().size());
assertNotNull(getLdapRemoteObject(RESOURCE_LDAP_ADMIN_DN, RESOURCE_LDAP_ADMIN_PWD, userDn.getValues().get(0)));
// ...and propagated
PagedResult<TaskTO> propagationTasks = taskService.search(new TaskQuery.Builder(TaskType.PROPAGATION).resource(RESOURCE_NAME_DBPULL).anyTypeKind(AnyTypeKind.USER).entityKey(user.getKey()).build());
assertEquals(1, propagationTasks.getSize());
// 4. update the user on the external resource
updateLdapRemoteObject(RESOURCE_LDAP_ADMIN_DN, RESOURCE_LDAP_ADMIN_PWD, userDn.getValues().get(0), Pair.of("mail", "pullFromLDAP2@syncope.apache.org"));
connObject = resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.USER.name(), user.getKey());
assertNotNull(connObject);
assertEquals("pullFromLDAP2@syncope.apache.org", connObject.getAttr("mail").get().getValues().get(0));
// 5. exec the pull task again
execution = execProvisioningTask(taskService, TaskType.PULL, pullTask.getKey(), 50, false);
assertEquals(PropagationTaskExecStatus.SUCCESS, PropagationTaskExecStatus.valueOf(execution.getStatus()));
// the internal is updated...
user = userService.read("pullFromLDAP");
assertNotNull(user);
assertEquals("pullFromLDAP2@syncope.apache.org", user.getPlainAttr("email").get().getValues().get(0));
// ...and propagated
propagationTasks = taskService.search(new TaskQuery.Builder(TaskType.PROPAGATION).resource(RESOURCE_NAME_DBPULL).anyTypeKind(AnyTypeKind.USER).entityKey(user.getKey()).build());
assertEquals(2, propagationTasks.getSize());
} catch (Exception e) {
LOG.error("Unexpected during issueSYNCOPE1062()", e);
fail(e.getMessage());
} finally {
if (pullTask != null) {
taskService.delete(TaskType.PULL, pullTask.getKey());
}
if (propagationGroup != null) {
groupService.delete(propagationGroup.getKey());
}
if (group != null) {
groupService.delete(group.getKey());
}
if (user != null) {
userService.delete(user.getKey());
}
}
}
use of org.apache.syncope.common.lib.to.AttrTO in project syncope by apache.
the class GroupReportlet method doExtractAttributes.
private void doExtractAttributes(final ContentHandler handler, final AnyTO anyTO, final Collection<String> attrs, final Collection<String> derAttrs, final Collection<String> virAttrs) throws SAXException {
AttributesImpl atts = new AttributesImpl();
if (!attrs.isEmpty()) {
Map<String, AttrTO> attrMap = EntityTOUtils.buildAttrMap(anyTO.getPlainAttrs());
handler.startElement("", "", "attributes", null);
for (String attrName : attrs) {
atts.clear();
atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
handler.startElement("", "", "attribute", atts);
if (attrMap.containsKey(attrName)) {
for (String value : attrMap.get(attrName).getValues()) {
handler.startElement("", "", "value", null);
handler.characters(value.toCharArray(), 0, value.length());
handler.endElement("", "", "value");
}
} else {
LOG.debug("{} not found for {}[{}]", attrName, anyTO.getClass().getSimpleName(), anyTO.getKey());
}
handler.endElement("", "", "attribute");
}
handler.endElement("", "", "attributes");
}
if (!derAttrs.isEmpty()) {
Map<String, AttrTO> derAttrMap = EntityTOUtils.buildAttrMap(anyTO.getDerAttrs());
handler.startElement("", "", "derivedAttributes", null);
for (String attrName : derAttrs) {
atts.clear();
atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
handler.startElement("", "", "derivedAttribute", atts);
if (derAttrMap.containsKey(attrName)) {
for (String value : derAttrMap.get(attrName).getValues()) {
handler.startElement("", "", "value", null);
handler.characters(value.toCharArray(), 0, value.length());
handler.endElement("", "", "value");
}
} else {
LOG.debug("{} not found for {}[{}]", attrName, anyTO.getClass().getSimpleName(), anyTO.getKey());
}
handler.endElement("", "", "derivedAttribute");
}
handler.endElement("", "", "derivedAttributes");
}
if (!virAttrs.isEmpty()) {
Map<String, AttrTO> virAttrMap = EntityTOUtils.buildAttrMap(anyTO.getVirAttrs());
handler.startElement("", "", "virtualAttributes", null);
for (String attrName : virAttrs) {
atts.clear();
atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
handler.startElement("", "", "virtualAttribute", atts);
if (virAttrMap.containsKey(attrName)) {
for (String value : virAttrMap.get(attrName).getValues()) {
handler.startElement("", "", "value", null);
handler.characters(value.toCharArray(), 0, value.length());
handler.endElement("", "", "value");
}
} else {
LOG.debug("{} not found for {}[{}]", attrName, anyTO.getClass().getSimpleName(), anyTO.getKey());
}
handler.endElement("", "", "virtualAttribute");
}
handler.endElement("", "", "virtualAttributes");
}
}
use of org.apache.syncope.common.lib.to.AttrTO in project syncope by apache.
the class UserReportlet method doExtractAttributes.
private void doExtractAttributes(final ContentHandler handler, final AnyTO anyTO, final Collection<String> attrs, final Collection<String> derAttrs, final Collection<String> virAttrs) throws SAXException {
AttributesImpl atts = new AttributesImpl();
if (!attrs.isEmpty()) {
Map<String, AttrTO> attrMap = EntityTOUtils.buildAttrMap(anyTO.getPlainAttrs());
handler.startElement("", "", "attributes", null);
for (String attrName : attrs) {
atts.clear();
atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
handler.startElement("", "", "attribute", atts);
if (attrMap.containsKey(attrName)) {
for (String value : attrMap.get(attrName).getValues()) {
handler.startElement("", "", "value", null);
handler.characters(value.toCharArray(), 0, value.length());
handler.endElement("", "", "value");
}
} else {
LOG.debug("{} not found for {}[{}]", attrName, anyTO.getClass().getSimpleName(), anyTO.getKey());
}
handler.endElement("", "", "attribute");
}
handler.endElement("", "", "attributes");
}
if (!derAttrs.isEmpty()) {
Map<String, AttrTO> derAttrMap = EntityTOUtils.buildAttrMap(anyTO.getDerAttrs());
handler.startElement("", "", "derivedAttributes", null);
for (String attrName : derAttrs) {
atts.clear();
atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
handler.startElement("", "", "derivedAttribute", atts);
if (derAttrMap.containsKey(attrName)) {
for (String value : derAttrMap.get(attrName).getValues()) {
handler.startElement("", "", "value", null);
handler.characters(value.toCharArray(), 0, value.length());
handler.endElement("", "", "value");
}
} else {
LOG.debug("{} not found for {}[{}]", attrName, anyTO.getClass().getSimpleName(), anyTO.getKey());
}
handler.endElement("", "", "derivedAttribute");
}
handler.endElement("", "", "derivedAttributes");
}
if (!virAttrs.isEmpty()) {
Map<String, AttrTO> virAttrMap = EntityTOUtils.buildAttrMap(anyTO.getVirAttrs());
handler.startElement("", "", "virtualAttributes", null);
for (String attrName : virAttrs) {
atts.clear();
atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
handler.startElement("", "", "virtualAttribute", atts);
if (virAttrMap.containsKey(attrName)) {
for (String value : virAttrMap.get(attrName).getValues()) {
handler.startElement("", "", "value", null);
handler.characters(value.toCharArray(), 0, value.length());
handler.endElement("", "", "value");
}
} else {
LOG.debug("{} not found for {}[{}]", attrName, anyTO.getClass().getSimpleName(), anyTO.getKey());
}
handler.endElement("", "", "virtualAttribute");
}
handler.endElement("", "", "virtualAttributes");
}
}
use of org.apache.syncope.common.lib.to.AttrTO in project syncope by apache.
the class SAML2SPLogic method validateLoginResponse.
@PreAuthorize("hasRole('" + StandardEntitlement.ANONYMOUS + "')")
public SAML2LoginResponseTO validateLoginResponse(final SAML2ReceivedResponseTO response) {
check();
// 1. first checks for the provided relay state
if (response.getRelayState() == null) {
throw new IllegalArgumentException("No Relay State was provided");
}
Boolean useDeflateEncoding = false;
String requestId = null;
if (!IDP_INITIATED_RELAY_STATE.equals(response.getRelayState())) {
JwsJwtCompactConsumer relayState = new JwsJwtCompactConsumer(response.getRelayState());
if (!relayState.verifySignatureWith(jwsSignatureVerifier)) {
throw new IllegalArgumentException("Invalid signature found in Relay State");
}
useDeflateEncoding = Boolean.valueOf(relayState.getJwtClaims().getClaim(JWT_CLAIM_IDP_DEFLATE).toString());
requestId = relayState.getJwtClaims().getSubject();
Long expiryTime = relayState.getJwtClaims().getExpiryTime();
if (expiryTime == null || (expiryTime * 1000L) < new Date().getTime()) {
throw new IllegalArgumentException("Relay State is expired");
}
}
// 2. parse the provided SAML response
if (response.getSamlResponse() == null) {
throw new IllegalArgumentException("No SAML Response was provided");
}
Response samlResponse;
try {
XMLObject responseObject = saml2rw.read(useDeflateEncoding, response.getSamlResponse());
if (!(responseObject instanceof Response)) {
throw new IllegalArgumentException("Expected " + Response.class.getName() + ", got " + responseObject.getClass().getName());
}
samlResponse = (Response) responseObject;
} catch (Exception e) {
LOG.error("While parsing AuthnResponse", e);
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
sce.getElements().add(e.getMessage());
throw sce;
}
// 3. validate the SAML response and, if needed, decrypt the provided assertion(s)
if (samlResponse.getIssuer() == null || samlResponse.getIssuer().getValue() == null) {
throw new IllegalArgumentException("The SAML Response must contain an Issuer");
}
final SAML2IdPEntity idp = getIdP(samlResponse.getIssuer().getValue());
if (idp.getConnObjectKeyItem() == null) {
throw new IllegalArgumentException("No mapping provided for SAML 2.0 IdP '" + idp.getId() + "'");
}
if (IDP_INITIATED_RELAY_STATE.equals(response.getRelayState()) && !idp.isSupportUnsolicited()) {
throw new IllegalArgumentException("An unsolicited request is not allowed for idp: " + idp.getId());
}
SSOValidatorResponse validatorResponse = null;
try {
validatorResponse = saml2rw.validate(samlResponse, idp, getAssertionConsumerURL(response.getSpEntityID(), response.getUrlContext()), requestId, response.getSpEntityID());
} catch (Exception e) {
LOG.error("While validating AuthnResponse", e);
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
sce.getElements().add(e.getMessage());
throw sce;
}
// 4. prepare the result: find matching user (if any) and return the received attributes
final SAML2LoginResponseTO responseTO = new SAML2LoginResponseTO();
responseTO.setIdp(idp.getId());
responseTO.setSloSupported(idp.getSLOLocation(idp.getBindingType()) != null);
Assertion assertion = validatorResponse.getOpensamlAssertion();
NameID nameID = assertion.getSubject().getNameID();
if (nameID == null) {
throw new IllegalArgumentException("NameID not found");
}
String keyValue = null;
if (StringUtils.isNotBlank(nameID.getValue()) && idp.getConnObjectKeyItem().getExtAttrName().equals("NameID")) {
keyValue = nameID.getValue();
}
if (assertion.getConditions().getNotOnOrAfter() != null) {
responseTO.setNotOnOrAfter(assertion.getConditions().getNotOnOrAfter().toDate());
}
assertion.getAuthnStatements().forEach(authnStmt -> {
responseTO.setSessionIndex(authnStmt.getSessionIndex());
responseTO.setAuthInstant(authnStmt.getAuthnInstant().toDate());
if (authnStmt.getSessionNotOnOrAfter() != null) {
responseTO.setNotOnOrAfter(authnStmt.getSessionNotOnOrAfter().toDate());
}
});
for (AttributeStatement attrStmt : assertion.getAttributeStatements()) {
for (Attribute attr : attrStmt.getAttributes()) {
if (!attr.getAttributeValues().isEmpty()) {
String attrName = attr.getFriendlyName() == null ? attr.getName() : attr.getFriendlyName();
if (attrName.equals(idp.getConnObjectKeyItem().getExtAttrName())) {
if (attr.getAttributeValues().get(0) instanceof XSString) {
keyValue = ((XSString) attr.getAttributeValues().get(0)).getValue();
} else if (attr.getAttributeValues().get(0) instanceof XSAny) {
keyValue = ((XSAny) attr.getAttributeValues().get(0)).getTextContent();
}
}
AttrTO attrTO = new AttrTO();
attrTO.setSchema(attrName);
attr.getAttributeValues().stream().filter(value -> value.getDOM() != null).forEachOrdered(value -> {
attrTO.getValues().add(value.getDOM().getTextContent());
});
responseTO.getAttrs().add(attrTO);
}
}
}
final List<String> matchingUsers = keyValue == null ? Collections.<String>emptyList() : userManager.findMatchingUser(keyValue, idp.getKey());
LOG.debug("Found {} matching users for {}", matchingUsers.size(), keyValue);
String username;
if (matchingUsers.isEmpty()) {
if (idp.isCreateUnmatching()) {
LOG.debug("No user matching {}, about to create", keyValue);
username = AuthContextUtils.execWithAuthContext(AuthContextUtils.getDomain(), () -> userManager.create(idp, responseTO, nameID.getValue()));
} else if (idp.isSelfRegUnmatching()) {
responseTO.setNameID(nameID.getValue());
UserTO userTO = new UserTO();
userManager.fill(idp.getKey(), responseTO, userTO);
responseTO.getAttrs().clear();
responseTO.getAttrs().addAll(userTO.getPlainAttrs());
responseTO.getAttrs().addAll(userTO.getVirAttrs());
if (StringUtils.isNotBlank(userTO.getUsername())) {
responseTO.setUsername(userTO.getUsername());
}
responseTO.setSelfReg(true);
return responseTO;
} else {
throw new NotFoundException("User matching the provided value " + keyValue);
}
} else if (matchingUsers.size() > 1) {
throw new IllegalArgumentException("Several users match the provided value " + keyValue);
} else {
if (idp.isUpdateMatching()) {
LOG.debug("About to update {} for {}", matchingUsers.get(0), keyValue);
username = AuthContextUtils.execWithAuthContext(AuthContextUtils.getDomain(), () -> userManager.update(matchingUsers.get(0), idp, responseTO));
} else {
username = matchingUsers.get(0);
}
}
responseTO.setUsername(username);
responseTO.setNameID(nameID.getValue());
// 5. generate JWT for further access
Map<String, Object> claims = new HashMap<>();
claims.put(JWT_CLAIM_IDP_ENTITYID, idp.getId());
claims.put(JWT_CLAIM_NAMEID_FORMAT, nameID.getFormat());
claims.put(JWT_CLAIM_NAMEID_VALUE, nameID.getValue());
claims.put(JWT_CLAIM_SESSIONINDEX, responseTO.getSessionIndex());
byte[] authorities = null;
try {
authorities = ENCRYPTOR.encode(POJOHelper.serialize(authDataAccessor.getAuthorities(responseTO.getUsername())), CipherAlgorithm.AES).getBytes();
} catch (Exception e) {
LOG.error("Could not fetch authorities", e);
}
Pair<String, Date> accessTokenInfo = accessTokenDataBinder.create(responseTO.getUsername(), claims, authorities, true);
responseTO.setAccessToken(accessTokenInfo.getLeft());
responseTO.setAccessTokenExpiryTime(accessTokenInfo.getRight());
return responseTO;
}
use of org.apache.syncope.common.lib.to.AttrTO in project syncope by apache.
the class SAML2UserManager method fill.
public void fill(final String idpKey, final SAML2LoginResponseTO responseTO, final UserTO userTO) {
SAML2IdP idp = idpDAO.find(idpKey);
if (idp == null) {
LOG.warn("Invalid IdP: {}", idpKey);
return;
}
idp.getItems().forEach(item -> {
List<String> values = Collections.emptyList();
Optional<AttrTO> samlAttr = responseTO.getAttr(item.getExtAttrName());
if (samlAttr.isPresent() && !samlAttr.get().getValues().isEmpty()) {
values = samlAttr.get().getValues();
List<Object> transformed = new ArrayList<>(values);
for (ItemTransformer transformer : MappingUtils.getItemTransformers(item)) {
transformed = transformer.beforePull(null, userTO, transformed);
}
values.clear();
for (Object value : transformed) {
values.add(value.toString());
}
}
IntAttrName intAttrName = null;
try {
intAttrName = intAttrNameParser.parse(item.getIntAttrName(), AnyTypeKind.USER);
} catch (ParseException e) {
LOG.error("Invalid intAttrName '{}' specified, ignoring", item.getIntAttrName(), e);
}
if (intAttrName != null && intAttrName.getField() != null) {
switch(intAttrName.getField()) {
case "username":
if (!values.isEmpty()) {
userTO.setUsername(values.get(0));
}
break;
default:
LOG.warn("Unsupported: {}", intAttrName.getField());
}
} else if (intAttrName != null && intAttrName.getSchemaType() != null) {
switch(intAttrName.getSchemaType()) {
case PLAIN:
Optional<AttrTO> attr = userTO.getPlainAttr(intAttrName.getSchemaName());
if (!attr.isPresent()) {
attr = Optional.of(new AttrTO.Builder().schema(intAttrName.getSchemaName()).build());
userTO.getPlainAttrs().add(attr.get());
} else {
attr.get().getValues().clear();
}
attr.get().getValues().addAll(values);
break;
default:
LOG.warn("Unsupported: {} {}", intAttrName.getSchemaType(), intAttrName.getSchemaName());
}
}
});
}
Aggregations