/// <summary> /// Helper method: Sets attribute value in the attribute collection /// </summary> /// <param name="attName">attribute name</param> /// <param name="attValue">attribute value (if null, we will remove the attribute from the collection)</param> /// <param name="attributes">collection of attribute</param> /// <exception cref="ArgumentNullException">If some of the params is null</exception> internal static void SetAttValue(string attName, object attValue, ICollection <ConnectorAttribute> attributes) { Assertions.NullCheck(attName, "attName"); Assertions.NullCheck(attributes, "attributes"); ConnectorAttribute attribute = ConnectorAttributeUtil.Find(attName, attributes); if (attribute != null) { attributes.Remove(attribute); } if (attValue != null) { attributes.Add(ConnectorAttributeBuilder.Build(attName, new object[] { attValue })); } }
public void MergeDeleteToExistingAttributeCompletely() { UpdateImpl up = new UpdateImpl(null, null); ICollection <ConnectorAttribute> actual; ICollection <ConnectorAttribute> baseAttrs = CollectionUtil.NewSet <ConnectorAttribute>(); ICollection <ConnectorAttribute> expected = CollectionUtil.NewSet <ConnectorAttribute>(); ICollection <ConnectorAttribute> changeset = CollectionUtil.NewSet <ConnectorAttribute>(); // attempt to add a value to an attribute.. ConnectorAttribute battr = ConnectorAttributeBuilder.Build("abc", 1, 2); ConnectorAttribute cattr = ConnectorAttributeBuilder.Build("abc", 1, 2); baseAttrs.Add(battr); changeset.Add(cattr); expected.Add(ConnectorAttributeBuilder.Build("abc")); actual = up.Merge(changeset, baseAttrs, false); Assert.IsTrue(AreEqual(expected, actual)); }
/// <summary> /// Attribute normalizer /// </summary> /// <param name="oclass">Object class</param> /// <param name="attribute">Attribute to be normalized</param> /// <returns>Normalized attribute</returns> public ConnectorAttribute NormalizeAttribute(ObjectClass oclass, ConnectorAttribute attribute) { // normalize the attribute using AD connector first // attribute = base.NormalizeAttribute(oclass, attribute); // normalize mail-related attributes if (attribute.Is(ExchangeConnectorAttributes.AttExternalEmailAddress) || attribute.Is(ExchangeConnectorAttributes.AttForwardingSmtpAddress)) { return(NormalizeSmtpAddressAttribute(attribute)); } else { return(attribute); } // TODO: what with EmailAddresses? (we should not remove SMTP/smpt prefix, because it carries information on primary/secondary address type) // TODO: and other attributes? }
public void TestGetSingleValue() { object TEST_VALUE = 1L; ConnectorAttribute attr = ConnectorAttributeBuilder.Build("long", TEST_VALUE); object value = ConnectorAttributeUtil.GetSingleValue(attr); Assert.AreEqual(TEST_VALUE, value); // test null attr = ConnectorAttributeBuilder.Build("long"); value = ConnectorAttributeUtil.GetSingleValue(attr); Assert.IsNull(value); // test empty attr = ConnectorAttributeBuilder.Build("long", new List <object>()); value = ConnectorAttributeUtil.GetSingleValue(attr); Assert.IsNull(value); // test illegal argument exception ConnectorAttributeUtil.GetSingleValue(ConnectorAttributeBuilder.Build("bob", 1, 2, 3)); }
private IList <object> ValuesSorted(ConnectorObject resource, string field) { ConnectorAttribute value = resource.GetAttributeByName(field); if (value == null || value.Value == null || value.Value.Count == 0) { return(new List <object>()); } else if (value.Value.Count > 1) { List <object> results = new List <object>(value.Value); results.Sort(VALUE_COMPARATOR); return(results); } else { return(value.Value); } }
/// <summary> /// Helper method: Gets attribute value from the attribute collection /// </summary> /// <param name="attName">attribute name</param> /// <param name="attributes">collection of attribute</param> /// <returns>Attribute value as object, null if not found</returns> /// <exception cref="ArgumentNullException">If some of the params is null</exception> internal static object GetAttValue(string attName, ICollection <ConnectorAttribute> attributes) { Assertions.NullCheck(attName, "attName"); if (attributes == null) { return(null); } object value = null; ConnectorAttribute attribute = ConnectorAttributeUtil.Find(attName, attributes); if (attribute != null) { value = ConnectorAttributeUtil.GetSingleValue(attribute) ?? string.Empty; } return(value); }
/// <summary> /// Translates the connector attribute name to LDAP name /// </summary> /// <param name="attr">Connector attribute name</param> /// <returns>Translated string array</returns> protected override string[] GetLdapNamesForAttribute(ConnectorAttribute attr) { if (attr.Is(AttDatabase)) { return(new[] { AttDatabaseADName }); } if (attr.Is(AttExternalMail)) { return(new[] { AttExternalMailADName }); } if (attr.Is(AttRecipientType)) { return(null); } return(base.GetLdapNamesForAttribute(attr)); }
/// <summary> /// Helper method: Gets attribute values from the attribute collection /// </summary> /// <param name="attName">attribute name</param> /// <param name="attributes">collection of attribute</param> /// <returns>Attribute value as collection of objects, null if not found</returns> /// <exception cref="ArgumentNullException">If some of the params is null</exception> internal static IList <object> GetAttValues(string attName, ICollection <ConnectorAttribute> attributes) { Assertions.NullCheck(attName, "attName"); if (attributes == null) { return(null); } ConnectorAttribute attribute = ConnectorAttributeUtil.Find(attName, attributes); if (attribute != null) { return(attribute.Value); } else { return(null); } }
private ConnectorAttribute NormalizeSmtpAddressAttribute(ConnectorAttribute attribute) { if (attribute.Value == null) { return(attribute); } IList <object> normValues = new List <object>(); bool normalized = false; foreach (object val in attribute.Value) { string strVal = val as string; if (strVal != null) { string[] split = strVal.Split(':'); if (split.Length == 2) { // it contains delimiter, use the second part normValues.Add(split[1]); normalized = true; } else { // put the original value normValues.Add(val); } } } if (normalized) { // build the attribute again return(ConnectorAttributeBuilder.Build(attribute.Name, normValues)); } else { return(attribute); } }
/// <summary> /// Attribute normalizer /// </summary> /// <param name="oclass">Object class</param> /// <param name="attribute">Attribute to be normalized</param> /// <returns>Normalized attribute</returns> public override ConnectorAttribute NormalizeAttribute(ObjectClass oclass, ConnectorAttribute attribute) { // normalize the attribute using AD connector first attribute = base.NormalizeAttribute(oclass, attribute); // normalize external mail value if (attribute.Name == AttExternalMail && attribute.Value != null) { IList <object> normAttributes = new List <object>(); bool normalized = false; foreach (object val in attribute.Value) { string strVal = val as string; if (strVal != null) { string[] split = strVal.Split(':'); if (split.Length == 2) { // it contains delimiter, use the second part normAttributes.Add(split[1]); normalized = true; } else { // put the original value normAttributes.Add(val); } } } if (normalized) { // build the attribute again return(ConnectorAttributeBuilder.Build(attribute.Name, normAttributes)); } } // return the original attribute return(attribute); }
/// <summary> /// Renames the connector attribute to new name; transforms value by keeping Common Name only /// </summary> /// <param name="cattribute">ConnectorAttribute to be renamed</param> /// <param name="newName">New attribute name</param> /// <returns>Renamed and transformed ConnectorAttribute</returns> /// <exception cref="ArgumentNullException">If some of the params is null</exception> internal static ConnectorAttribute ExtractCommonName(ConnectorAttribute cattribute, string newName) { Assertions.NullCheck(cattribute, "cattribute"); Assertions.NullCheck(newName, "newName"); var attBuilder = new ConnectorAttributeBuilder(); if (cattribute.Value != null) { ICollection <object> convertedValues = new List <object>(); foreach (object oldValue in cattribute.Value) { if (oldValue != null) // should be always the case { convertedValues.Add(ExtractCommonName(oldValue.ToString())); } } attBuilder.AddValue(convertedValues); } attBuilder.Name = newName; return(attBuilder.Build()); }
/** * Get the LDAP name or names for a given connector attribute used in a * search filter. * * @param attr The connector attribute used in a search filter. * * @return The name or names of the corresponding LDAP attribute. * Returns null if the attribute cannot be specified in an LDAP * filter. */ protected virtual String[] GetLdapNamesForAttribute(ConnectorAttribute attr) { // Special processing for certain connector attributes. String[] attrNames = null; if (attr is Uid) { /* * attrNames = new String[] { * configCache.getConfiguration().getUuidAttribute() }; */ attrNames = new String[] { "objectGUID" }; } else if (attr is Name) { /* * attrNames = configCache.getNamingAttributes(); */ attrNames = new String [] { "distinguishedName" }; } else if (attr.Is(OperationalAttributes.PASSWORD_NAME)) { /* * attrNames = new String[] { * configCache.getConfiguration().getPasswordAttribute() * }; */ attrNames = new String[] { "userPassword" }; } else if (ConnectorAttributeUtil.IsSpecial(attr)) { return(null); } else { attrNames = new String[] { attr.Name }; } return(attrNames); }
private String CreateContainsAllValuesExpressionInternal(AttributeFilter filter, Boolean not) { if (not) { return(null); } ConnectorAttribute attr = filter.GetAttribute(); if (attr is Uid) { return(((Uid)attr).GetUidValue()); } else if (attr is Name) { return(((Name)attr).GetNameValue()); } else { return(null); } }
public Uid Create(ObjectClass objClass, ICollection <ConnectorAttribute> attrs, OperationOptions options) { StringBuilder sb = new StringBuilder(); ConnectorAttribute NameAttribute = ConnectorAttributeUtil.Find(Name.NAME, attrs); if (NameAttribute == null) { throw new ConnectorException("The name operational attribute cannot be null"); } string parameter = ConnectorAttributeUtil.GetAsStringValue(NameAttribute); string[] login = parameter.Split('@'); PowerShell PowerShellInstance = PowerShell.Create(); PowerShellInstance.AddCommand(this.config.createScript + "create.ps1"); PowerShellInstance.AddArgument(login[0]); Collection <PSObject> results; Collection <ErrorRecord> errors; results = PowerShellInstance.Invoke(); errors = PowerShellInstance.Streams.Error.ReadAll(); if (errors.Count > 0) { foreach (ErrorRecord error in errors) { sb.AppendLine(error.ToString()); } throw new ConnectorException(sb.ToString()); } else { return(new Uid(ConnectorAttributeUtil.GetAsStringValue(NameAttribute))); } }
/// <summary> /// Translates the connector attribute name to LDAP name /// </summary> /// <param name="attr">Connector attribute name</param> /// <returns>Translated string array</returns> protected override string[] GetLdapNamesForAttribute(ConnectorAttribute attr) { // Exchange attributes with known mappings to AD foreach (string attrNameInExchange in ExchangeConnectorAttributes.AttMap2AD.Keys) { if (attr.Is(attrNameInExchange)) { return(new[] { ExchangeConnectorAttributes.AttMap2AD[attrNameInExchange] }); } } // Other Exchange attributes have no mapping to AD ones. // This means that some attributes with more complicated mappings, // like RecipientType or EmailAddressPolicyEnabled, cannot be // used in search queries. if (ExchangeConnectorAttributes.IsExchangeAttribute(attr)) { return(null); } else { return(base.GetLdapNamesForAttribute(attr)); } }
/// <summary> /// Updates an AD object (also called by create after object is created) /// </summary> /// <param name="oclass"></param> /// <param name="directoryEntry"></param> /// <param name="attributes"></param> /// <param name="type"></param> /// <param name="config"></param> internal void UpdateADObject(ObjectClass oclass, DirectoryEntry directoryEntry, ICollection <ConnectorAttribute> attributes, UpdateType type, ActiveDirectoryConfiguration config) { if (oclass.Equals(ObjectClass.ACCOUNT)) { // translate attribute passed in foreach (ConnectorAttribute attribute in attributes) { // encountered problems when processing change password at the same time // as setting expired. It would be set to expired, but the change would // clear that. So we must ensure that expired comes last. if (OperationalAttributes.PASSWORD_EXPIRED_NAME.Equals(attribute.Name)) { continue; } AddConnectorAttributeToADProperties(oclass, directoryEntry, attribute, type); // Uncommenting the next line is very helpful in // finding mysterious errors. // Trace.TraceInformation("Committing after setting attribute {0} to {1}", attribute.Name, attribute.Value); // directoryEntry.CommitChanges(); } directoryEntry.CommitChanges(); // now do the password change. This is handled separately, because // it might be a user changing his own password, or it might be an // administrative change. GuardedString gsNewPassword = ConnectorAttributeUtil.GetPasswordValue(attributes); if (gsNewPassword != null) { GuardedString gsCurrentPassword = ConnectorAttributeUtil.GetCurrentPasswordValue(attributes); PasswordChangeHandler changeHandler = new PasswordChangeHandler(_configuration); if (gsCurrentPassword == null) { // just a normal password change changeHandler.changePassword(directoryEntry, gsNewPassword); } else { changeHandler.changePassword(directoryEntry, gsCurrentPassword, gsNewPassword); } UserAccountControl.Set(directoryEntry.Properties[ActiveDirectoryConnector.ATT_USER_ACOUNT_CONTROL], UserAccountControl.PASSWD_NOTREQD, false); directoryEntry.CommitChanges(); } // see note in loop above for explaination of this ConnectorAttribute expirePasswordAttribute = ConnectorAttributeUtil.Find( OperationalAttributes.PASSWORD_EXPIRED_NAME, attributes); if (expirePasswordAttribute != null) { AddConnectorAttributeToADProperties(oclass, directoryEntry, expirePasswordAttribute, type); directoryEntry.CommitChanges(); } /* * UserAccountControl.Set(directoryEntry.Properties[ActiveDirectoryConnector.ATT_USER_ACOUNT_CONTROL], * UserAccountControl.PASSWD_NOTREQD, false); */ directoryEntry.CommitChanges(); HandleNameAndContainerChange(type, directoryEntry, attributes, config); } else if (oclass.Equals(ActiveDirectoryConnector.groupObjectClass)) { // translate attribute passed in foreach (ConnectorAttribute attribute in attributes) { // Temporary // Trace.TraceInformation(String.Format("Setting attribute {0} to {1}", // attribute.Name, attribute.Value)); AddConnectorAttributeToADProperties(oclass, directoryEntry, attribute, type); // Uncommenting the next line is very helpful in // finding mysterious errors. // directoryEntry.CommitChanges(); } directoryEntry.CommitChanges(); HandleNameAndContainerChange(type, directoryEntry, attributes, config); } else if (oclass.Equals(ActiveDirectoryConnector.ouObjectClass)) { // translate attribute passed in foreach (ConnectorAttribute attribute in attributes) { // Temporary // Trace.TraceInformation(String.Format("Setting attribute {0} to {1}", // attribute.Name, attribute.Value)); AddConnectorAttributeToADProperties(oclass, directoryEntry, attribute, type); // Uncommenting the next line is very helpful in // finding mysterious errors. // directoryEntry.CommitChanges(); } directoryEntry.CommitChanges(); HandleNameAndContainerChange(type, directoryEntry, attributes, config); } else { String objectClassName = GetADObjectClass(oclass); // translate attribute passed in foreach (ConnectorAttribute attribute in attributes) { // Temporary // Trace.TraceInformation(String.Format("Setting attribute {0} to {1}", // attribute.Name, attribute.Value)); AddConnectorAttributeToADProperties(oclass, directoryEntry, attribute, type); // Uncommenting the next line is very helpful in // finding mysterious errors. // directoryEntry.CommitChanges(); } directoryEntry.CommitChanges(); HandleNameAndContainerChange(type, directoryEntry, attributes, config); } }
/// <summary> /// Gets Recipient Type/Database from Exchange database, this method can be more general, but it is ok /// for out needs /// </summary> /// <param name="oc">object class, currently the moethod works for <see cref="ObjectClass.ACCOUNT"/> only</param> /// <param name="cobject">connector object to get the recipient type/database for</param> /// <param name="attToGet">attributes to get</param> /// <returns>Connector Object with recipient type added</returns> /// <exception cref="ConnectorException">In case of some troubles in powershell (if the /// user is not found we get this exception too)</exception> private ConnectorObject AddExchangeAttributes(ObjectClass oc, ConnectorObject cobject, IEnumerable <string> attToGet) { ExchangeUtility.NullCheck(oc, "name", this.configuration); ExchangeUtility.NullCheck(oc, "cobject", this.configuration); // we support ACCOUNT only or there is nothing to add if (!oc.Is(ObjectClass.ACCOUNT_NAME) || attToGet == null) { return(cobject); } // check it is not deleted object bool?deleted = ExchangeUtility.GetAttValue(AttIsDeleted, cobject.GetAttributes()) as bool?; if (deleted != null && deleted == true) { // do nothing, it is deleted object return(cobject); } ICollection <string> lattToGet = CollectionUtil.NewCaseInsensitiveSet(); CollectionUtil.AddAll(lattToGet, attToGet); foreach (string att in attToGet) { if (cobject.GetAttributeByName(att) != null && att != AttDatabase) { lattToGet.Remove(att); } } if (lattToGet.Count == 0) { return(cobject); } ConnectorObjectBuilder cobjBuilder = new ConnectorObjectBuilder(); cobjBuilder.AddAttributes(cobject.GetAttributes()); PSExchangeConnector.CommandInfo cmdInfo = PSExchangeConnector.CommandInfo.GetUser; // prepare the connector attribute list to get the command ICollection <ConnectorAttribute> attributes = new Collection <ConnectorAttribute> { cobject.Name }; // get the command Command cmd = ExchangeUtility.GetCommand(cmdInfo, attributes, this.configuration); ICollection <PSObject> foundObjects = this.InvokePipeline(cmd); PSObject user = null; if (foundObjects != null && foundObjects.Count == 1) { user = GetFirstElement(foundObjects); foreach (var info in user.Properties) { ConnectorAttribute att = GetAsAttribute(info); if (att != null && lattToGet.Contains(att.Name)) { cobjBuilder.AddAttribute(att); lattToGet.Remove(att.Name); } } if (lattToGet.Count == 0) { return(cobjBuilder.Build()); } } if (user == null) { // nothing to do return(cobject); } string rcptType = user.Members[AttRecipientType].Value.ToString(); foundObjects = null; // get detailed information if (rcptType == RcptTypeMailBox) { foundObjects = this.InvokePipeline(ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.GetMailbox, attributes, this.configuration)); } else if (rcptType == RcptTypeMailUser) { foundObjects = this.InvokePipeline(ExchangeUtility.GetCommand(PSExchangeConnector.CommandInfo.GetMailUser, attributes, this.configuration)); } if (foundObjects != null && foundObjects.Count == 1) { PSObject userDetails = GetFirstElement(foundObjects); foreach (var info in userDetails.Properties) { ConnectorAttribute att = GetAsAttribute(info); if (att != null && lattToGet.Contains(att.Name)) { cobjBuilder.AddAttribute(att); lattToGet.Remove(att.Name); } } } return(cobjBuilder.Build()); }
public void TestBasics() { ConnectorAttribute attribute = ConnectorAttributeBuilder.Build("att-name", "att-value"); ConnectorAttribute attribute2 = ConnectorAttributeBuilder.Build("att-name2", "att-value2"); AllFiltersTranslator translator = new AllFiltersTranslator(); { Filter filter = FilterBuilder.Contains(attribute); String expected = "( CONTAINS att-name att-value )"; String actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); filter = FilterBuilder.Not(filter); expected = "( ! " + expected + " )"; actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); } { Filter filter = FilterBuilder.EndsWith(attribute); String expected = "( ENDS-WITH att-name att-value )"; String actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); filter = FilterBuilder.Not(filter); expected = "( ! " + expected + " )"; actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); } { Filter filter = FilterBuilder.EqualTo(attribute); String expected = "( = att-name [att-value] )"; String actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); filter = FilterBuilder.Not(filter); expected = "( ! " + expected + " )"; actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); } { Filter filter = FilterBuilder.GreaterThan(attribute); String expected = "( > att-name att-value )"; String actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); filter = FilterBuilder.Not(filter); expected = "( ! " + expected + " )"; actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); } { Filter filter = FilterBuilder.GreaterThanOrEqualTo(attribute); String expected = "( >= att-name att-value )"; String actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); filter = FilterBuilder.Not(filter); expected = "( ! " + expected + " )"; actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); } { Filter filter = FilterBuilder.LessThan(attribute); String expected = "( < att-name att-value )"; String actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); filter = FilterBuilder.Not(filter); expected = "( ! " + expected + " )"; actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); } { Filter filter = FilterBuilder.LessThanOrEqualTo(attribute); String expected = "( <= att-name att-value )"; String actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); filter = FilterBuilder.Not(filter); expected = "( ! " + expected + " )"; actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); } { Filter filter = FilterBuilder.StartsWith(attribute); String expected = "( STARTS-WITH att-name att-value )"; String actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); filter = FilterBuilder.Not(filter); expected = "( ! " + expected + " )"; actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); } { Filter filter = FilterBuilder.ContainsAllValues(attribute); String expected = "( CONTAINS-ALL-VALUES " + attribute + " )"; String actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); filter = FilterBuilder.Not(filter); expected = "( ! " + expected + " )"; actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); } //and { Filter left = FilterBuilder.Contains(attribute); Filter right = FilterBuilder.Contains(attribute2); String expectedLeft = "( CONTAINS att-name att-value )"; String expectedRight = "( CONTAINS att-name2 att-value2 )"; Filter filter = FilterBuilder.And(left, right); String expected = "( & " + expectedLeft + " " + expectedRight + " )"; String actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); filter = FilterBuilder.Not(filter); expectedLeft = "( ! " + expectedLeft + " )"; expectedRight = "( ! " + expectedRight + " )"; expected = "( | " + expectedLeft + " " + expectedRight + " )"; actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); } //or { Filter left = FilterBuilder.Contains(attribute); Filter right = FilterBuilder.Contains(attribute2); String expectedLeft = "( CONTAINS att-name att-value )"; String expectedRight = "( CONTAINS att-name2 att-value2 )"; Filter filter = FilterBuilder.Or(left, right); String expected = "( | " + expectedLeft + " " + expectedRight + " )"; String actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); filter = FilterBuilder.Not(filter); expectedLeft = "( ! " + expectedLeft + " )"; expectedRight = "( ! " + expectedRight + " )"; expected = "( & " + expectedLeft + " " + expectedRight + " )"; actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); } //double-negative { Filter filter = FilterBuilder.Contains(attribute); filter = FilterBuilder.Not(filter); filter = FilterBuilder.Not(filter); String expected = "( CONTAINS att-name att-value )"; String actual = TranslateSingle(translator, filter); Assert.AreEqual(expected, actual); } }
internal static bool IsExchangeAttribute(ConnectorAttribute attr) { return(IsExchangeAttribute(attr.Name)); }
// creates a collection of attributes that correspond to the original ones, but resolves ADD/DELETE using existing values of psuser public ICollection <ConnectorAttribute> DetermineNewAttributeValues(UpdateOpContext context, ConnectorObject originalObject) { if (context.UpdateType == UpdateType.REPLACE) { // TODO check multivaluedness and updateability (as below) return(new List <ConnectorAttribute>(context.Attributes)); } else { Boolean add; if (context.UpdateType == UpdateType.ADD) { add = true; } else if (context.UpdateType == UpdateType.DELETE) { add = false; } else { throw new ArgumentException("Unsupported update type: " + context.UpdateType); } Schema schema = null; ICollection <ConnectorAttribute> rv = new List <ConnectorAttribute>(context.Attributes.Count); foreach (ConnectorAttribute attribute in context.Attributes) { ConnectorAttribute originalAttribute = originalObject.GetAttributeByName(attribute.Name); IList <object> newValues = originalAttribute != null && originalAttribute.Value != null ? new List <object>(originalAttribute.Value) : new List <object>(); Boolean changed = false; if (attribute.Value != null) { foreach (object item in attribute.Value) { if (add) { if (newValues.Contains(item)) { LOG.Warn("Trying to add value from " + attribute.Name + " that is already there: " + item); } else { newValues.Add(item); changed = true; } } else { if (!newValues.Contains(item)) { LOG.Warn("Trying to remove value from " + attribute.Name + " that is not there: " + item); } else { newValues.Remove(item); changed = true; } } } } if (changed) { ConnectorAttributeBuilder b = new ConnectorAttributeBuilder(); b.Name = attribute.Name; b.AddValue(newValues); ConnectorAttribute modified = b.Build(); if (schema == null) { ExchangeConnector connector = (ExchangeConnector)context.Connector; schema = connector.Schema(); } ObjectClassInfo oci = schema.FindObjectClassInfo(context.ObjectClass.Type); if (oci == null) { throw new InvalidOperationException("No object class info for " + context.ObjectClass.Type + " in the schema"); } var cai = ConnectorAttributeInfoUtil.Find(attribute.Name, oci.ConnectorAttributeInfos); if (cai == null) { throw new InvalidOperationException("No connector attribute info for " + context.ObjectClass.Type + " in the schema"); } if (!cai.IsUpdateable) { throw new ConnectorSecurityException("Attempt to update a non-updateable attribute (" + attribute.Name + "): " + CollectionUtil.Dump(newValues)); } if (newValues.Count > 1 && !cai.IsMultiValued) { throw new InvalidAttributeValueException("More than one value in a single-valued attribute (" + attribute.Name + "): " + CollectionUtil.Dump(newValues)); } rv.Add(modified); } } return(rv); } }
protected override String CreateEqualsExpression(EqualsFilter filter, Boolean not) { // The LDAP equality filter matches any one attribute value, // whereas the connector EqualsFilter matches an attribute and // its values exactly. if (not) { return(null); } ConnectorAttribute attr = filter.GetAttribute(); // if there is only one thing to search on, and it's // a uid we need to convert the uid to something we // can search on. NOTE: only handling the case where // we are doing an equality search, and only one item // is in the equality search ... It's all that makes // sense for uid. if (attr is Uid) { String attrValue = ((Uid)attr).GetUidValue(); if (LooksLikeGUID(attrValue)) { String searchGuid = GetUidSearchString(((Uid)attr).GetUidValue()); attr = new Uid(searchGuid); } else { attr = new Name(attrValue); } } String[] attrNames = GetLdapNamesForAttribute(attr); if (attrNames == null) { return(null); } StringBuilder builder = new StringBuilder(); if (attr.Value == null) { return(null); } if (attr.Value.Count == 1) { BuildEqualityFilter(builder, attrNames, attr.Value[0]); } else { builder.Append("(&"); foreach (Object value in attr.Value) { BuildEqualityFilter(builder, attrNames, value); } builder.Append(')'); } return(builder.ToString()); }
public void TestScripting() { ConnectorInfoManager manager = GetConnectorInfoManager(); ConnectorInfo info = FindConnectorInfo(manager, "1.0.0.0", "org.identityconnectors.testconnector.TstConnector"); Assert.IsNotNull(info); APIConfiguration api = info.CreateDefaultAPIConfiguration(); ConnectorFacadeFactory facf = ConnectorFacadeFactory.GetInstance(); ConnectorFacade facade = facf.NewInstance(api); ScriptContextBuilder builder = new ScriptContextBuilder(); builder.AddScriptArgument("arg1", "value1"); builder.AddScriptArgument("arg2", "value2"); builder.ScriptLanguage = ("BOO"); //test that they can run the script and access the //connector object { String SCRIPT = "connector.concat(arg1,arg2)"; builder.ScriptText = (SCRIPT); String result = (String)facade.RunScriptOnConnector(builder.Build(), null); Assert.AreEqual("value1value2", result); } //test that they can access a class in the class loader { String SCRIPT = "import org.identityconnectors.testconnector\n" + "TstConnector.GetVersion()"; builder.ScriptText = (SCRIPT); String result = (String)facade.RunScriptOnConnector(builder.Build(), null); Assert.AreEqual("1.0", result); } //test that they cannot access a class in internal { Type clazz = typeof(ConfigurationPropertyImpl); String SCRIPT = "import " + clazz.Namespace + "\n" + clazz.Name + "()"; builder.ScriptText = (SCRIPT); try { facade.RunScriptOnConnector(builder.Build(), null); Assert.Fail("exception expected"); } catch (Exception e) { String msg = e.Message; String expectedMessage = "Namespace '" + clazz.Namespace + "' not found"; Assert.IsTrue( msg.Contains(expectedMessage), "Unexpected message: " + msg); } } // test that they can access a class in common { Type clazz = typeof(ConnectorAttributeBuilder); String SCRIPT = "import " + clazz.Namespace + "\n" + clazz.Name + ".Build(\"myattr\")"; builder.ScriptText = (SCRIPT); ConnectorAttribute attr = (ConnectorAttribute)facade.RunScriptOnConnector(builder.Build(), null); Assert.AreEqual("myattr", attr.Name); } }
internal void AddConnectorAttributeToADProperties(ObjectClass oclass, DirectoryEntry directoryEntry, ConnectorAttribute attribute, UpdateType type) { // Boolean translated = false; if (directoryEntry == null) { throw new ConnectorException(_configuration.ConnectorMessages.Format( "ex_CouldNotAddNullAttributeToDe", "Could not add connector attribute to <null> directory entry")); } _customHandlers.UpdateDeFromCa(oclass, type, directoryEntry, attribute); }
/// <summary> /// DeduplicatesEmailAddresses. /// - on REPLACE (i.e. update/replace or create) the situation is easy: we just remove duplicate entries (SMTP:x & smtp:x result in SMTP:x) /// - on DELETE we currently do nothing /// - on ADD we have one additional rule: /// "If we are adding SMTP:x, we first convert all SMTP:y in existing records to smtp:y because we see the intent of having x to be a new primary" /// /// </summary> /// <param name="context"></param> /// <param name="attributes">these are attributes to be set (already resolved if we have update of type ADD or DELETE)</param> /// <returns></returns> private ICollection <ConnectorAttribute> DeduplicateEmailAddresses(CreateUpdateOpContext context, ICollection <ConnectorAttribute> attributes) { // trivial cases if (context is UpdateOpContext && ((UpdateOpContext)context).UpdateType == UpdateType.DELETE) { return(attributes); } ConnectorAttribute attribute = ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddresses, attributes); if (attribute == null || attribute.Value == null) { return(attributes); // missing or empty EmailAddresses - nothing to deduplicate } ConnectorAttribute attributeDelta = ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddresses, context.Attributes); if (attributeDelta == null || attributeDelta.Value == null) { return(attributes); // missing or empty changed EmailAddresses - nothing to deduplicate } // now the main part IList <string> valuesToDeduplicate = new List <string>(); foreach (object o in attribute.Value) { if (o != null) { valuesToDeduplicate.Add(o.ToString()); } } bool changed = false; // special rule: if ADD with SMTP:, let us change all other "SMTP:x" to "smtp:x" Boolean isUpdateAdd = context is UpdateOpContext && ((UpdateOpContext)context).UpdateType == UpdateType.ADD; if (isUpdateAdd) { string newPrimary = null; foreach (object o in attributeDelta.Value) { if (((string)o).StartsWith("SMTP:")) { newPrimary = (string)o; break; } } if (newPrimary != null) { foreach (string address in new List <string>(valuesToDeduplicate)) // to eliminate concurrent access { if (address.StartsWith("SMTP:") && !address.Equals(newPrimary)) { string replacement = "smtp:" + address.Substring(5); LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Changing duplicate primary-candidate address {0} to {1}", address, replacement); valuesToDeduplicate.Remove(address); valuesToDeduplicate.Add(replacement); changed = true; } } } } IDictionary <string, string> values = new Dictionary <string, string>(); // normalized->most-recent-original e.g. SMTP:[email protected] -> SMTP:[email protected] (if primary is present) foreach (object v in valuesToDeduplicate) { string address = (string)v; string normalized = address.ToUpper(); if (values.ContainsKey(normalized)) { changed = true; string existing = values[normalized]; if (address.StartsWith("SMTP:") && existing.StartsWith("smtp:")) { LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Removing redundant address {0}, keeping {1}", existing, address); values[normalized] = address; } else { LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Removing redundant address {0}, keeping {1}", address, existing); } } else { values.Add(normalized, address); } } if (changed) { ConnectorAttributeBuilder cab = new ConnectorAttributeBuilder(); cab.Name = ExchangeConnectorAttributes.AttEmailAddresses; foreach (string value in values.Values) { cab.AddValue(value); } ICollection <ConnectorAttribute> rv = new List <ConnectorAttribute>(attributes); // the original is (sometimes) a read-only collection rv.Remove(attribute); rv.Add(cab.Build()); return(rv); } else { return(attributes); } }
private void AddOrReplaceDatabase(ObjectClass oclass, Uid uid, ICollection <ConnectorAttribute> attributes, OperationOptions options, AbstractConfiguration connectorConfiguration) { if (!ObjectClass.ACCOUNT.Equals(oclass)) { LOG.Info("Nothing to do"); return; } // вычисляем значение атрибута Database только если он не был передан // и дополнительно пришёл атрибут RecipientType со значением UserMailbox ConnectorAttribute database = GetAttribute(attributes, "Database"); ConnectorAttribute recipientType = GetAttribute(attributes, "RecipientType"); if (database != null || recipientType == null || !recipientType.Value.First().ToString().Equals("UserMailbox")) { LOG.Info("Nothing to do"); return; } DirectoryEntry container = null; try { ActiveDirectoryConfiguration config = (ActiveDirectoryConfiguration)connectorConfiguration; // вычисляем dn, для update'а находим по uid string dn = ""; if (uid != null) { DirectoryEntry entry = new DirectoryEntry(ActiveDirectoryUtils.GetLDAPPath(config.LDAPHostName, uid.GetUidValue()), config.DirectoryAdminName, config.DirectoryAdminPassword); dn = (string)entry.Properties["distinguishedName"][0]; entry.Dispose(); } else { dn = GetAttribute(attributes, "__NAME__").Value.First().ToString(); } string parentDn = ActiveDirectoryUtils.GetParentDn(dn); string ldapContainerPath = ActiveDirectoryUtils.GetLDAPPath(config.LDAPHostName, parentDn); container = new DirectoryEntry(ldapContainerPath, config.DirectoryAdminName, config.DirectoryAdminPassword); // поиск значения Database в родительских OU string defaultHomeMdb = null; while (defaultHomeMdb == null && container != null) { LOG.Info("Looking for DefaultHomeMdb in {0}", container.Path); defaultHomeMdb = GetDefaultHomeMdb(container); if (defaultHomeMdb != null) { LOG.Info("Found! DefaultHomeMdb = {0} (in container {1})", defaultHomeMdb, container.Path); } else { LOG.Info("Did not found DefaultHomeMdb in container {0}", container.Path); } try { container = container.Parent; } catch (Exception e) { LOG.Info("Error: " + e.Message); container = null; } } // установка значения атрибута, если не нашли указываем значение по умолчанию if (defaultHomeMdb != null) { LOG.Info("Setting DefaultHomeMdb: " + defaultHomeMdb); AddOrReplaceAttribute(attributes, "Database", defaultHomeMdb); } else { LOG.Info("Did not found DefaultHomeMdb, will set default value"); AddOrReplaceAttribute(attributes, "Database", "MSK-RN-DAG01-1GB-02"); } } finally { if (container != null) { container.Dispose(); } } }
/// <summary> /// Creates command based on the commanf info, reading the calues from attributes /// </summary> /// <param name="cmdInfo">Command defition</param> /// <param name="attributes">Attribute values - UID in these is ignored! It should be passed as a separate parameter</param> /// <param name="config">Configuration object</param> /// <returns> /// Ready to execute Command /// </returns> /// <exception cref="ArgumentNullException">if some of the param is null</exception> internal static Command GetCommand(PSExchangeConnector.CommandInfo cmdInfo, ICollection <ConnectorAttribute> attributes, Uid uidAttribute, Name nameAttribute, ExchangeConfiguration config) { Assertions.NullCheck(cmdInfo, "cmdInfo"); LOG.Trace("GetCommand: cmdInfo name = {0}", cmdInfo.Name); ISet <string> parametersSet = new HashSet <string>(); // create command Command cmd = new Command(cmdInfo.Name); if (!string.IsNullOrEmpty(cmdInfo.UidParameter) && !parametersSet.Contains(cmdInfo.UidParameter)) { Uid uidAttr = uidAttribute != null ? uidAttribute : ConnectorAttributeUtil.GetUidAttribute(attributes); string uid = uidAttr != null?uidAttr.GetUidValue() : null; if (uid != null) { cmd.Parameters.Add(cmdInfo.UidParameter, ActiveDirectoryUtils.ConvertADGUIDtoObjectGUID(uid)); parametersSet.Add(cmdInfo.UidParameter); } } // map name attribute, if mapping specified if (!string.IsNullOrEmpty(cmdInfo.NameParameter) && !parametersSet.Contains(cmdInfo.NameParameter)) { Name nameAttr = nameAttribute != null ? nameAttribute : ConnectorAttributeUtil.GetNameFromAttributes(attributes); string name = nameAttr != null?nameAttr.GetNameValue() : null;; if (name != null) { cmd.Parameters.Add(cmdInfo.NameParameter, name); parametersSet.Add(cmdInfo.NameParameter); } } if (cmdInfo.UsesConfirm) { cmd.Parameters.Add("confirm", false); parametersSet.Add("confirm"); } if (cmdInfo.UsesDomainController) { cmd.Parameters.Add("DomainController", ActiveDirectoryUtils.GetDomainControllerName(config)); parametersSet.Add("DomainController"); } // TODO check this only for user-related operations bool emailAddressesPresent = GetAttValues(ExchangeConnectorAttributes.AttEmailAddresses, attributes) != null; bool primarySmtpAddressPresent = GetAttValues(ExchangeConnectorAttributes.AttPrimarySmtpAddress, attributes) != null; if (emailAddressesPresent && primarySmtpAddressPresent) { throw new ArgumentException(ExchangeConnectorAttributes.AttEmailAddresses + " and " + ExchangeConnectorAttributes.AttPrimarySmtpAddress + " cannot be both set."); } if (attributes != null) { foreach (string attName in cmdInfo.Parameters) { object valueToSet = null; ConnectorAttribute attribute = ConnectorAttributeUtil.Find(attName, attributes); if (attribute != null) { if (attribute.Value != null && attribute.Value.Count > 1) { List <string> stringValues = new List <string>(); foreach (object val in attribute.Value) { stringValues.Add(val.ToString()); } valueToSet = stringValues.ToArray(); } else { valueToSet = ConnectorAttributeUtil.GetSingleValue(attribute); } if (parametersSet.Contains(attName)) { throw new InvalidOperationException("Parameter " + attName + " is already defined for command " + cmdInfo.Name); } cmd.Parameters.Add(attName, valueToSet); parametersSet.Add(attName); } } } LOG.Trace("GetCommand exit: cmdInfo name = {0}", cmdInfo.Name); return(cmd); }
public Uid Update(ObjectClass objclass, Uid uid, ICollection <ConnectorAttribute> replaceAttributes, OperationOptions options) { StringBuilder sb = new StringBuilder(); PowerShell PowerShellInstance = PowerShell.Create(); ConnectorAttribute StatusAttribute = ConnectorAttributeUtil.Find(OperationalAttributes.ENABLE_NAME, replaceAttributes); String enable = ConnectorAttributeUtil.GetAsStringValue(StatusAttribute).ToLower(); string parameter = ConnectorAttributeUtil.GetAsStringValue(uid); string[] login = parameter.Split('@'); if (enable.Equals("false")) { PowerShellInstance.AddCommand(this.config.createScript + "disable.ps1"); PowerShellInstance.AddArgument(login[0]); Collection <PSObject> results; Collection <ErrorRecord> errors; results = PowerShellInstance.Invoke(); errors = PowerShellInstance.Streams.Error.ReadAll(); if (errors.Count > 0) { foreach (ErrorRecord error in errors) { sb.AppendLine(error.ToString()); } throw new ConnectorException(sb.ToString()); } else { return(uid); } } else if (enable.Equals("true")) { PowerShellInstance.AddCommand(this.config.createScript + "enable.ps1"); PowerShellInstance.AddArgument(login[0]); Collection <PSObject> results; Collection <ErrorRecord> errors; results = PowerShellInstance.Invoke(); errors = PowerShellInstance.Streams.Error.ReadAll(); if (errors.Count > 0) { foreach (ErrorRecord error in errors) { sb.AppendLine(error.ToString()); } throw new ConnectorException(sb.ToString()); } else { return(uid); } } else { return(uid); } }
public void Create(CreateOpContext context) { context.Attributes = DeduplicateEmailAddresses(context, context.Attributes); // get recipient type string rcptType = ExchangeUtility.GetAttValue(ExchangeConnectorAttributes.AttRecipientType, context.Attributes) as string; if (rcptType == null || rcptType.Equals("")) { rcptType = ExchangeConnectorAttributes.RcptTypeUser; } ExchangeConnector exconn = (ExchangeConnector)context.Connector; ActiveDirectoryConnector adconn = exconn.ActiveDirectoryConnector; PSExchangeConnector.CommandInfo cmdInfoEnable = null; PSExchangeConnector.CommandInfo cmdInfoSet = null; switch (rcptType) { case ExchangeConnectorAttributes.RcptTypeMailBox: cmdInfoEnable = PSExchangeConnector.CommandInfo.EnableMailbox; cmdInfoSet = PSExchangeConnector.CommandInfo.SetMailbox; break; case ExchangeConnectorAttributes.RcptTypeMailUser: cmdInfoEnable = PSExchangeConnector.CommandInfo.EnableMailUser; cmdInfoSet = PSExchangeConnector.CommandInfo.SetMailUser; break; case ExchangeConnectorAttributes.RcptTypeUser: break; default: throw new ArgumentException( context.ConnectorConfiguration.ConnectorMessages.Format( "ex_bad_rcpt", "Recipient type [{0}] is not supported", rcptType)); } // first create the object in AD ICollection <ConnectorAttribute> adAttributes = ExchangeUtility.FilterOut(context.Attributes, PSExchangeConnector.CommandInfo.EnableMailbox, PSExchangeConnector.CommandInfo.SetMailbox, PSExchangeConnector.CommandInfo.EnableMailUser, PSExchangeConnector.CommandInfo.SetMailUser); Uid uid = adconn.Create(context.ObjectClass, adAttributes, context.Options); if (rcptType == ExchangeConnectorAttributes.RcptTypeUser) { // AD account only, we do nothing context.Uid = uid; return; } // add a empty "EmailAddresses" attribute if needed (address policy is disabled and no addresses are provided) ICollection <ConnectorAttribute> enhancedAttributes; ConnectorAttribute policyEnabledAttribute = ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddressPolicyEnabled, context.Attributes); if (policyEnabledAttribute != null && ConnectorAttributeUtil.GetBooleanValue(policyEnabledAttribute).HasValue&& ConnectorAttributeUtil.GetBooleanValue(policyEnabledAttribute).Value == false && ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttPrimarySmtpAddress, context.Attributes) == null && ConnectorAttributeUtil.Find(ExchangeConnectorAttributes.AttEmailAddresses, context.Attributes) == null) { enhancedAttributes = new HashSet <ConnectorAttribute>(context.Attributes); enhancedAttributes.Add(ConnectorAttributeBuilder.Build(ExchangeConnectorAttributes.AttEmailAddresses)); LOGGER.TraceEvent(TraceEventType.Verbose, CAT_DEFAULT, "Added empty EmailAddresses attribute because address policy use is disabled and no addresses were provided"); } else { enhancedAttributes = context.Attributes; // no change } // prepare the command Command cmdEnable = ExchangeUtility.GetCommand(cmdInfoEnable, enhancedAttributes, uid, (ExchangeConfiguration)context.ConnectorConfiguration); Command cmdSet = ExchangeUtility.GetCommand(cmdInfoSet, enhancedAttributes, uid, (ExchangeConfiguration)context.ConnectorConfiguration); try { _helper.InvokePipeline(exconn, cmdEnable); _helper.InvokePipeline(exconn, cmdSet); } catch { LOGGER.TraceEvent(TraceEventType.Information, CAT_DEFAULT, "Rolling back AD create for UID: " + uid.GetUidValue()); // rollback AD create try { adconn.Delete(context.ObjectClass, uid, context.Options); } catch { LOGGER.TraceEvent(TraceEventType.Warning, CAT_DEFAULT, "Not able to rollback AD create for UID: " + uid.GetUidValue()); // note: this is not perfect, we hide the original exception throw; } // rethrow original exception throw; } context.Uid = uid; }