2

I have looked at many search results but I am struggling to find a way to programmatically (using C#) create a custom permission and a custom group in Active Directory.

I have an application that will need to have about 50 individual permissions, such as: can encrypt data, can decrypt data, can export private key, can delete keypair, etc. These permissions will be assigned to a custom group. For instance, the group may be called: standard user, security manager, etc.

Users will be assigned one or more of these groups. I need all of this to be managed through Active Directory. The software that is being written is in C#. The users will be in Active Directory.

The software will check that the user has a particular permission when a function on the application is to be executed. If the user does not have permission then they will be required to enter an override. This override is simply a prompt for the credentials of another user who DOES have the relevant permissions.

I want to emphasise that this needs to be managed through Active Directory because the software is running on a domain and the permissions will be managed by the Domain Administrator.

As such, I believe the ASP.Net Roles functionality is not sufficient? In addition, I am not sure if Azure AD is the same as Windows AD.

I would very much appreciate any guidance as to which .NET assembly/namespace will provide the following capability:

  • Create permission
  • Create group
  • Assign permission to group
  • Assign user to group
  • Remove user from group
  • Remove permission from group

I need to to do this programatically because the software will have an installer and will be responsible for adding the application-specific custom permissions and groups during installation if they do not already exist.

It may be possible that I am approaching this wrong so I am open to suggestions otherwise. As long as I am able to perform the above then great!

Thank you!

SolidRegardless
  • 427
  • 3
  • 17

2 Answers2

3

As I understood,

Here you can try below code

Try once

1) Create Group

                PrincipalContext principalContext =
                    new PrincipalContext(ContextType.Domain, LDAPDomain, LDAPContainer,
                        LDAPAdmin, LDAPPassword);

                GroupPrincipal group = GroupPrincipal.FindByIdentity(principalContext, "groupName");

                if (group == null)
                {
                    GroupPrincipal groupPrincipal = new GroupPrincipal(principalContext);
                    groupPrincipal.Name = "groupName";
                    groupPrincipal.SamAccountName = "samAccountName";
                    groupPrincipal.UserPrincipalName = "userPrincipleName";
                    groupPrincipal.GroupScope = GroupScope.Global;
                    groupPrincipal.Description = "groupNameDescription";
                    groupPrincipal.DisplayName = "groupNameDisplayName";
                    groupPrincipal.Save();
                }

2) Add User To Group

            GroupPrincipal group = GroupPrincipal.FindByIdentity(principalContext, "groupName");
            UserPrincipal user = UserPrincipal.FindByIdentity(principalContext, "userName");

            bool isUserAdded = false;


            if (user != null & group != null)
            {
                if (user.IsMemberOf(group))
                {
                    //Do Code
                }
                else
                {
                    group.Members.Add(user);
                    group.Save();
                    isUserAdded = user.IsMemberOf(group);
                }
            }

            if (isUserAdded)
            {
                //Do Code
            }

3) Remove User From Group

                GroupPrincipal group = GroupPrincipal.FindByIdentity(principalContext, "groupName");
                UserPrincipal user = UserPrincipal.FindByIdentity(principalContext, "userName");

                bool isUserRemoved = false;


                if (user != null & group != null)
                {
                    if (user.IsMemberOf(group))
                    {
                        group.Members.Remove(user);
                        group.Save();
                        isUserRemoved = user.IsMemberOf(group);
                    }
                    else
                    {
                        //Do Code

                    }
                }

                if (!isUserRemoved)
                {
                    //Do Code
                }

4) Add or Remove AccessRule(Permission) to Group

From my side, I have no clear idea about what actually your logic or implementation,

But Here I tried to give a solution for adding or remving access rule to group

            //DirectoryEntry for OU Level
            DirectoryEntry directoryEntry = new DirectoryEntry("LDAP://OU=MYOU,DC=MYDC,DC=COM");

            NTAccount account = new NTAccount("MYDC", "groupName");

            ActiveDirectoryAccessRule ruleRead = new ActiveDirectoryAccessRule(
                account,
                ActiveDirectoryRights.ReadProperty,
                AccessControlType.Allow,
                ActiveDirectorySecurityInheritance.None);

            ActiveDirectoryAccessRule ruleWrite = new ActiveDirectoryAccessRule(
                account,
                ActiveDirectoryRights.WriteProperty,
                AccessControlType.Deny,
                ActiveDirectorySecurityInheritance.None);

            if (Permission == "User shall be able to export private key from an RSA keypair")
            {
                directoryEntry.ObjectSecurity.AddAccessRule(ruleRead);

                directoryEntry.ObjectSecurity.AddAccessRule(ruleWrite);

                directoryEntry.Options.SecurityMasks = SecurityMasks.Dacl;

                directoryEntry.CommitChanges();

                Console.WriteLine("Added Deny Access to Read & Write.");
            }

            if (Permission == "User is able to decrypt imported data")
            {
                directoryEntry.ObjectSecurity.RemoveAccessRule(ruleRead);

                directoryEntry.ObjectSecurity.RemoveAccessRule(ruleWrite);

                directoryEntry.Options.SecurityMasks = SecurityMasks.Dacl;

                directoryEntry.CommitChanges();

                Console.WriteLine("Removed Deny Access to Read & Write.");
            }

            directoryEntry.Close();

            directoryEntry.Dispose();

Note: Please test all above code in your test environment first.

er-sho
  • 9,581
  • 2
  • 13
  • 26
  • Thank you for this pointer. If one wishes, how would one assign custom permissions to the GroupPrincipal? – SolidRegardless Jul 20 '18 at 13:04
  • is above code help you? let me allow some time to find code in my project – er-sho Jul 20 '18 at 13:07
  • Yes it is thank you. If I were able to create and assign permissions to this group it would solve my overall question. I appreciate your time. – SolidRegardless Jul 20 '18 at 13:12
  • could you please explain what type of permission do you want to set ? – er-sho Jul 20 '18 at 13:29
  • An example would be for a custom group called "Security Worker". This group shall be able to do a number of tasks. These tasks are defined by the permissions which are assigned to that group. Each task will have an associated permission. One such permission may be "User shall be able to export private key from an RSA keypair". Another permission may be to "User is able to decrypt imported data". These permissions are completely custom. I assumed that the relationship was such that: User -> Group(s) -> Permission(s)? – SolidRegardless Jul 20 '18 at 13:35
  • Please check answer, If it helps then accept answer up to I'll check in my project all about permissions. – er-sho Jul 20 '18 at 14:01
  • The permissions point is at the heart of my question. I will keep monitoring and as soon as this question is answered fully I will mark the answer as complete. Thank you again for your assistance thus far. – SolidRegardless Jul 20 '18 at 14:11
  • Is point no 2 and 3 worked? AD contains an AccessRule to group that we set by Read and Write. Is you want this AccessRule? – er-sho Jul 20 '18 at 14:24
  • Hi, I believe that is correct. I am unsure how to assign them to a group though. – SolidRegardless Jul 20 '18 at 14:28
  • As you are mostly correct and have provided much of the information I will accept answer. Please update answer if you find information on how to add accessrule to group. – SolidRegardless Jul 20 '18 at 14:39
  • I m glad to hear from you. Yes i found the solution I'll update soon bcoz now I leave from my office :) – er-sho Jul 20 '18 at 15:38
1

You're trying to use AD as both your AuthZ store and your AuthZ engine if I follow the question correctly. The former (using it as a data store) makes perfect sense, but, I don't think it's the right tool to evaluate access for your app.

What I would do is layer your groups in two levels:

  • Level 1 - permission groups (e.g. can encrypt, can decrypt, etc.)

  • Level 2 - roles - these are members of various permission groups, and in turn users are added to these groups to grant them the roles. They will inherit the permissions the roles have when their logon token is built by Windows.

Assuming your app uses Windows Authentication, the WindowsTokenRoleProvider (https://msdn.microsoft.com/en-us/library/system.web.security.windowstokenroleprovider(v=vs.110).aspx) will surface all of the group memberships up into your app and you can then check if someone is in a permission group and let them do something (or not)...

Brian Desmond
  • 4,473
  • 1
  • 13
  • 11
  • Ok I see what you mean. The problem is that the permissions (level 1) are very fine grained and need to be dynamically assigned to groups (level 2). The user is able to configure what groups can do what using the applications user interface. I do like the idea of having level 1 and level 2 groups because they can be managed through AD then. However, how can you ensure that only level 1 groups can be assigned to level 2? With a custom application UI this control is possible. – SolidRegardless Jul 27 '18 at 11:16
  • Also, I need to check, but I am hoping that the access rules can be viewed within the GroupPrincipal object. Using the ObjectSecurity property maybe. It seems like the suggestion above would keep the access rules away from usual AD perusal, because they are really no concern to anything other than the application. Keeping it in AD also means that the same permissions applied to the groups are in sync domain wide for other instances of the same application (i.e. on a different box). – SolidRegardless Jul 27 '18 at 11:19
  • The ObjectSecurity property gives you the ACL for the group itself. This defines permissions to perform operations on the group in AD. Given your description of needing to keep this in sync, what I would consider is creating a custom application partition in AD along with some custom schema to represent your data model. You can use security groups to assign permissions and link them to the permission definitions stored in the app partition. You'd give your app access to modify that data and have a UI in the app for managing it. – Brian Desmond Jul 28 '18 at 14:15
  • Yes that sounds reasonable. If you have any reference for doing this I may actually consider changing the best answer to your suggestion. I tried the suggestion from the currently selected best answer and it does not work. ObjectSecurity doesn't seem to work correctly which I understand the reasons for now. – SolidRegardless Jul 28 '18 at 19:17
  • There's not a lot but here's a couple links: https://learn.microsoft.com/en-us/windows/desktop/AD/application-directory-partitions and https://learn.microsoft.com/en-us/windows/desktop/AD/active-directory-schema. Shameless plug, my book Active Directory 5th Ed from O'Reilly has some good content on the schema as well although not much on app partitions. – Brian Desmond Jul 29 '18 at 20:17