sorengranfeldt / psma

Powershell Management Agent for FIM2010 and MIM2016
MIT License
34 stars 11 forks source link

Ability to set Schema Attributes as ImportOnly or ExportOnly #23

Closed benzekat75 closed 2 years ago

benzekat75 commented 2 years ago

Hello,

I have a need for a customer to replace the MS PowerShell MA but something better :) In a custom MA of my own, I recall exploring attribute definitions when building the Schema and ability to create ImportOnly and ExportOnly attributes.

In particular here, my need is to have ExportOnly attributes that are used at provisioning time only, and therefore do not need to be available (and is actually NOT available) when doing the Delta Import confirmation.

For this matter I propose the following:

1) add the ImportOnly/ExportOnly properties to the AttributeDefinition class 2) when reading the attribute, search for ImportOnly-/ExportOnly- keyword as it's the case for Anchor- and set the properties accodingly 3) when creating SchemaAttribute objects, set the AttributeOperation property accordingly

Now given the way the flag is defined in the name:

1) technically speaking and attribute can only be ImportOnly or ExportOnly and is by default ImportExport 2) anchor attribute is by designed excluded from the feature

Codes changes are quite minor but benefits are great, I think :)

1) change in the AttributeDefinition class (add two properties) 2) change in the GetSchema method to read the flag from the name + to create the SchemaAttribute objects using the 3rd parameter (of enum type AttributeOperation)

Let me know what you think. If you don't want to make it to the main codebase I'll fork my own version.

Thanks, Benoit.

sorengranfeldt commented 2 years ago

Hi. Any reason why you cannot just set the attributes only on provision? Currently I don't have the time to expand the PSMA with the things you suggest. Also, documentation and samples need to be updated if the functionality is changed and backwards compatibility needs to be tested and maintained as this MA is just very much around the world. If you're in a hurry and really need this, I think you should run your own fork. If I get the time, I could consider similar features for futures versions of the MA.

benzekat75 commented 2 years ago

Hello, Søren and best wishes for 2022.

I already have made the change in the code, it was quite easy and it’s being tested extensively in my development lab. I’m a good writer too, I could even document the feature too, even provide samples.

Reason for the request is historical but also mostly because it’s a built-in feature of some MA, and I’m saying to myself “why isn’t it supported here…?”

Anyway, setting the attribute at provisioning is indeed what’s done, but that doesn’t change the fact that MIM needs to confirm the export. Which doesn’t happen with an ExportOnly attribute typically, since it’s not expected to be read back from the Datasource. I prefer not having an “exported-change-not-reimported” warning, neither, worse, having to disable Confirms (and I think there’s not way to do so in your PSMA). ExportOnly attributes are the best approach for such scenarios.

Anyway, thanks anyway for taking the time to respond. If you need contributors, you have my contact info now, I’ve coded a lot for MIM and even my own MAs too.

Cheers, Benoit.

From: Søren Granfeldt @.> Sent: Monday, January 3, 2022 9:04 AM To: sorengranfeldt/psma @.> Cc: Benoit Boudeville @.>; Author @.> Subject: Re: [sorengranfeldt/psma] Ability to set Schema Attributes as ImportOnly or ExportOnly (Issue #23)

Hi. Any reason why you cannot just set the attributes only on provision? Currently I don't have the time to expand the PSMA with the things you suggest. Also, documentation and samples need to be updated if the functionality is changed and backwards compatibility needs to be tested and maintained as this MA is just very much around the world. If you're in a hurry and really need this, I think you should run your own fork. If I get the time, I could consider similar features for futures versions of the MA.

— Reply to this email directly, view it on GitHubhttps://github.com/sorengranfeldt/psma/issues/23#issuecomment-1003922718, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AEWQCY2DJEP3KYOZOSI46BTUUFJ7ZANCNFSM5LBDWD7Q. Triage notifications on the go with GitHub Mobile for iOShttps://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Androidhttps://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub. You are receiving this because you authored the thread.Message ID: @.***>

sorengranfeldt commented 2 years ago

I would be happy to check out a pull request at some point in time, also for the documentation. I can review when I get the time. I cannot promise, however, when I'll get the time.

benzekat75 commented 2 years ago

I’m suck with git but I think I managed to create my own branch and you should be able to compare ==> benoitboudeville75:master Added ImportOnly/ExportOnly specifiers for Schema Attributes by benoitboudeville75 · Pull Request #24 · sorengranfeldt/psma (github.com)https://github.com/sorengranfeldt/psma/pull/24/commits/09bcf67f99ef7e9076540cab320a8e6cf6a40cb0

For the doc it will take me a little more time as, just like you, I must work for my company and customers, too 😉 I’ll certainly should be able to work on the doc later today or tomorrow.

Cheers, Benoit

From: Søren Granfeldt @.> Sent: Monday, January 3, 2022 10:14 AM To: sorengranfeldt/psma @.> Cc: Benoit Boudeville @.>; Author @.> Subject: Re: [sorengranfeldt/psma] Ability to set Schema Attributes as ImportOnly or ExportOnly (Issue #23)

I would be happy to check out a pull request at some point in time, also for the documentation. I can review when I get the time. I cannot promise, however, when I'll get the time.

— Reply to this email directly, view it on GitHubhttps://github.com/sorengranfeldt/psma/issues/23#issuecomment-1003956856, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AEWQCY6OIVSBHHVZOKAAFPLUUFSEDANCNFSM5LBDWD7Q. Triage notifications on the go with GitHub Mobile for iOShttps://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Androidhttps://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub. You are receiving this because you authored the thread.Message ID: @.**@.>>

using Microsoft.MetadirectoryServices; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Text.RegularExpressions;

namespace Granfeldt { public partial class PowerShellManagementAgent : IDisposable, IMAExtensible2GetCapabilities, IMAExtensible2GetSchema, IMAExtensible2GetParameters, IMAExtensible2CallImport, IMAExtensible2CallExport, IMAExtensible2Password { Collection schemaResults; string SchemaScript = null;

    class AttributeDefinition
    {
        public string Name { get; set; }
        public AttributeType Type { get; set; }
        public bool IsMultiValue { get; set; }
        public bool IsAnchor { get; set; }
        public bool ImportOnly { get; set; }
        public bool ExportOnly { get; set; }
    }

    Schema IMAExtensible2GetSchema.GetSchema(KeyedCollection<string, ConfigParameter> configParameters)
    {
        Tracer.Enter("getschema");
        try
        {
            Schema schema = Schema.Create();
            InitializeConfigParameters(configParameters);

            OpenRunspace();
            Command cmd = new Command(Path.GetFullPath(SchemaScript));
            cmd.Parameters.Add(new CommandParameter("Username", Username));
            cmd.Parameters.Add(new CommandParameter("Password", Password));
            cmd.Parameters.Add(new CommandParameter("Credentials", GetSecureCredentials(Username, SecureStringPassword)));

            cmd.Parameters.Add(new CommandParameter("AuxUsername", UsernameAux));
            cmd.Parameters.Add(new CommandParameter("AuxPassword", PasswordAux));
            cmd.Parameters.Add(new CommandParameter("AuxCredentials", GetSecureCredentials(UsernameAux, SecureStringPasswordAux)));

            cmd.Parameters.Add(new CommandParameter("ConfigurationParameter", ConfigurationParameter));

            schemaResults = InvokePowerShellScript(cmd, null);
            CloseRunspace();

            if (schemaResults != null)
            {
                foreach (PSObject obj in schemaResults)
                {
                    string objectTypeName = null;
                    HashSet<AttributeDefinition> attrs = new HashSet<AttributeDefinition>();

                    foreach (PSPropertyInfo p in obj.Properties)
                    {
                        string[] elements = p.Name.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                        string attrName = elements[0].Trim();
                        string attrType = elements[1].Trim();

                        if (string.Equals(attrName, Constants.ControlValues.ObjectClass, StringComparison.OrdinalIgnoreCase))
                        {
                            objectTypeName = p.Value.ToString();
                            Tracer.TraceInformation("object-class '{0}'", objectTypeName);
                        }
                        else
                        {
                            AttributeDefinition ad = new AttributeDefinition();
                            ad.Name = Regex.Replace(attrName, "^Anchor-", "", RegexOptions.IgnoreCase);
                            ad.Name = Regex.Replace(ad.Name, "^ImportOnly-", "", RegexOptions.IgnoreCase);
                            ad.Name = Regex.Replace(ad.Name, "^ExportOnly-", "", RegexOptions.IgnoreCase);
                            ad.IsAnchor = p.Name.StartsWith("anchor-", StringComparison.OrdinalIgnoreCase);
                            ad.ImportOnly = p.Name.StartsWith("importonly-", StringComparison.OrdinalIgnoreCase);
                            ad.ExportOnly = p.Name.StartsWith("exportonly-", StringComparison.OrdinalIgnoreCase);
                            ad.IsMultiValue = p.Name.EndsWith("[]", StringComparison.OrdinalIgnoreCase);
                            switch (attrType.Replace("[]", "").ToLower())
                            {
                                case "boolean":
                                    ad.Type = AttributeType.Boolean;
                                    break;
                                case "binary":
                                    ad.Type = AttributeType.Binary;
                                    break;
                                case "integer":
                                    ad.Type = AttributeType.Integer;
                                    break;
                                case "reference":
                                    ad.Type = AttributeType.Reference;
                                    break;
                                case "string":
                                    ad.Type = AttributeType.String;
                                    break;
                                default:
                                    ad.Type = AttributeType.String;
                                    break;
                            }
                            Tracer.TraceInformation("name '{0}', isanchor: {1}, ismultivalue: {2}, importonly: {3}, exportonly: {4}, type: {5}", ad.Name, ad.IsAnchor, ad.IsMultiValue, ad.ImportOnly, ad.ExportOnly, ad.Type.ToString());
                            attrs.Add(ad);
                        }
                    }
                    if (string.IsNullOrEmpty(objectTypeName))
                    {
                        Tracer.TraceError("missing-object-class");
                        throw new Microsoft.MetadirectoryServices.NoSuchObjectTypeException();
                    }

                    SchemaType objectClass = SchemaType.Create(objectTypeName, true);
                    foreach (AttributeDefinition def in attrs)
                    {
                        if (def.IsAnchor)
                        {
                            objectClass.Attributes.Add(SchemaAttribute.CreateAnchorAttribute(def.Name, def.Type));
                        }
                        else
                        {
                            var attrOperation = def.ExportOnly ? AttributeOperation.ExportOnly :
                                                def.ImportOnly ? AttributeOperation.ImportOnly : AttributeOperation.ImportExport;

                            if (def.IsMultiValue)
                            {
                                objectClass.Attributes.Add(SchemaAttribute.CreateMultiValuedAttribute(def.Name, def.Type, attrOperation));
                            }
                            else
                            {
                                objectClass.Attributes.Add(SchemaAttribute.CreateSingleValuedAttribute(def.Name, def.Type, attrOperation));
                            }
                        }
                    }
                    if (objectClass.AnchorAttributes.Count == 1)
                    {
                        schema.Types.Add(objectClass);
                    }
                    else
                    {
                        Tracer.TraceError("missing-anchor-definition-on-object");
                        throw new Microsoft.MetadirectoryServices.AttributeNotPresentException();
                    }
                }
            }
            schemaResults.Clear();
            return schema;
        }
        catch (Exception ex)
        {
            Tracer.TraceError("getschema", ex);
            throw;
        }
        finally
        {
            Tracer.Exit("getschema");
        }
    }

}

}

sorengranfeldt commented 2 years ago

Added in PR #24

benzekat75 commented 2 years ago

Hi Søren, I saw you merged the changes ! Wow that was fast. Indeed, as I told you, changes were quite minor overall ;) I saw you also changed the flexible schema documentation too. Thanks!

Cheers, Benoit.

From: Søren Granfeldt @.> Sent: Monday, January 3, 2022 9:18 PM To: sorengranfeldt/psma @.> Cc: Benoit Boudeville @.>; Author @.> Subject: Re: [sorengranfeldt/psma] Ability to set Schema Attributes as ImportOnly or ExportOnly (Issue #23)

Added in PR #24https://github.com/sorengranfeldt/psma/pull/24

— Reply to this email directly, view it on GitHubhttps://github.com/sorengranfeldt/psma/issues/23#issuecomment-1004333842, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AEWQCY4JCRHA7HIKSYLUMY3UUIAAHANCNFSM5LBDWD7Q. Triage notifications on the go with GitHub Mobile for iOShttps://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Androidhttps://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub. You are receiving this because you authored the thread.Message ID: @.**@.>>