aboutsummaryrefslogtreecommitdiff
path: root/src/test/burn/WixTestTools/UserGroupVerifier.cs
blob: 8c2da46ef707c341399c7576e9a55dc1b0ba3a72 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.

namespace WixTestTools
{
    using System;
    using System.Text;
    using System.DirectoryServices;
    using System.DirectoryServices.AccountManagement;
    using System.Security.Principal;
    using Xunit;

    /// <summary>
    /// Contains methods for User Group verification
    /// </summary>
    public static class UserGroupVerifier
    {
        /// <summary>
        /// Create a local group on the machine
        /// </summary>
        /// <param name="groupName"></param>
        /// <remarks>Has to be run as an Admin</remarks>
        public static void CreateLocalGroup(string groupName)
        {
            DeleteLocalGroup(groupName);
            GroupPrincipal newGroup = new GroupPrincipal(new PrincipalContext(ContextType.Machine));
            newGroup.Name = groupName;
            newGroup.Description = String.Empty;
            newGroup.Save();
        }

        /// <summary>
        /// Deletes a local group from the machine
        /// </summary>
        /// <param name="groupName">group name to delete</param>
        /// <remarks>Has to be run as an Admin</remarks>
        public static void DeleteLocalGroup(string groupName)
        {
            GroupPrincipal newGroup = GetGroup(String.Empty, groupName);
            if (null != newGroup)
            {
                newGroup.Delete();
            }
        }

        /// <summary>
        /// Verifies that a group exists or not
        /// </summary>
        /// <param name="domainName">domain name for the group, empty for local groups</param>
        /// <param name="groupName">the group name</param>
        public static bool GroupExists(string domainName, string groupName)
        {
            GroupPrincipal group = GetGroup(domainName, groupName);

            return null != group;
        }

        /// <summary>
        /// Sets the group comment for a given group
        /// </summary>
        /// <param name="domainName">domain name for the group, empty for local users</param>
        /// <param name="groupName">the group name</param>
        /// <param name="comment">comment to be set for the group</param>
        public static void SetGroupComment(string domainName, string groupName, string comment)
        {
            GroupPrincipal group = GetGroup(domainName, groupName);

            Assert.False(null == group, String.Format("Group '{0}' was not found under domain '{1}'.", groupName, domainName));

            var directoryEntry = group.GetUnderlyingObject() as DirectoryEntry;
            Assert.False(null == directoryEntry);
            directoryEntry.Properties["Description"].Value = comment;
            group.Save();
        }

        /// <summary>
        /// Adds the specified group to the specified local group
        /// </summary>
        /// <param name="memberName">Member to add</param>
        /// <param name="groupName">Group to add too</param>
        public static void AddGroupToGroup(string memberName, string groupName)
        {
            DirectoryEntry localMachine;
            DirectoryEntry localGroup;

            localMachine = new DirectoryEntry("WinNT://" + Environment.MachineName.ToString());
            localGroup = localMachine.Children.Find(groupName, "group");
            Assert.False(null == localGroup, String.Format("Group '{0}' was not found.", groupName));
            DirectoryEntry group = FindActiveDirectoryGroup(memberName);
            localGroup.Invoke("Add", new object[] { group.Path.ToString() });
        }

        /// <summary>
        /// Find the specified group in AD
        /// </summary>
        /// <param name="groupName">group name to lookup</param>
        /// <returns>DirectoryEntry of the group</returns>
        private static DirectoryEntry FindActiveDirectoryGroup(string groupName)
        {
            var mLocalMachine = new DirectoryEntry("WinNT://" + Environment.MachineName.ToString());
            var mLocalEntries = mLocalMachine.Children;

            var theGroup = mLocalEntries.Find(groupName);
            return theGroup;
        }

        /// <summary>
        /// Verifies the group comment for a given group
        /// </summary>
        /// <param name="domainName">domain name for the group, empty for local users</param>
        /// <param name="groupName">the group name</param>
        /// <param name="comment">the comment to be verified</param>
        public static void VerifyGroupComment(string domainName, string groupName, string comment)
        {
            GroupPrincipal group = GetGroup(domainName, groupName);

            Assert.False(null == group, String.Format("Group '{0}' was not found under domain '{1}'.", groupName, domainName));

            var directoryEntry = group.GetUnderlyingObject() as DirectoryEntry;
            Assert.False(null == directoryEntry);
            Assert.True(comment == (string)(directoryEntry.Properties["Description"].Value));
        }

        /// <summary>
        /// Verify that a given group is member of a local group
        /// </summary>
        /// <param name="domainName">domain name for the group, empty for local groups</param>
        /// <param name="memberName">the member name</param>
        /// <param name="groupNames">list of groups to check for membership</param>
        public static void VerifyIsMemberOf(string domainName, string memberName, params string[] groupNames)
        {
            IsMemberOf(domainName, memberName, true, groupNames);
        }

        /// <summary>
        /// Verify that a given group is NOT member of a local group
        /// </summary>
        /// <param name="domainName">domain name for the group, empty for local groups</param>
        /// <param name="memberName">the member name</param>
        /// <param name="groupNames">list of groups to check for membership</param>
        public static void VerifyIsNotMemberOf(string domainName, string memberName, params string[] groupNames)
        {
            IsMemberOf(domainName, memberName, false, groupNames);
        }

        /// <summary>
        /// Verify that a given user is member of a local group
        /// </summary>
        /// <param name="domainName">domain name for the group, empty for local groups</param>
        /// <param name="memberName">the member name</param>
        /// <param name="shouldBeMember">whether the group is expected to be a member of the groups or not</param>
        /// <param name="groupNames">list of groups to check for membership</param>
        private static void IsMemberOf(string domainName, string memberName, bool shouldBeMember, params string[] groupNames)
        {
            Principal group = GetPrincipal(domainName, memberName);
            Assert.False(null == group, String.Format("Group '{0}' was not found under domain '{1}'.", memberName, domainName));

            bool missedAGroup = false;
            string message = String.Empty;
            foreach (string groupName in groupNames)
            {
                try
                {
                    bool found = group.IsMemberOf(new PrincipalContext(ContextType.Machine), IdentityType.Name, groupName);
                    if (found != shouldBeMember)
                    {
                        missedAGroup = true;
                        message += String.Format("Group '{0}/{1}' is {2} a member of local group '{3}'. \r\n", domainName, memberName, found ? String.Empty : "NOT", groupName);
                    }
                }
                catch (System.DirectoryServices.AccountManagement.PrincipalOperationException)
                {
                    missedAGroup = true;
                    message += String.Format("Local group '{0}' was not found. \r\n", groupName);
                }
            }
            Assert.False(missedAGroup, message);
        }

        /// <summary>
        /// Returns the GroupPrincipal object for a given group
        /// </summary>
        /// <param name="domainName">Domain name to look under, if Empty the LocalMachine is assumed as the domain</param>
        /// <param name="groupName"></param>
        /// <returns>UserPrincipal Object for the group if found, or null other wise</returns>
        private static GroupPrincipal GetGroup(string domainName, string groupName)
        {
            if (String.IsNullOrEmpty(domainName))
            {
                return GroupPrincipal.FindByIdentity(new PrincipalContext(ContextType.Machine), groupName);
            }
            else
            {
                return GroupPrincipal.FindByIdentity(new PrincipalContext(ContextType.Domain,domainName), groupName);
            }
        }

        /// <summary>
        /// Returns the Principal object for a given name
        /// </summary>
        /// <param name="domainName">Domain name to look under, if Empty the LocalMachine is assumed as the domain</param>
        /// <param name="name"></param>
        /// <returns>Principal Object if found, or null other wise</returns>
        private static Principal GetPrincipal(string domainName, string name)
        {
            if (String.IsNullOrEmpty(domainName))
            {
                return Principal.FindByIdentity(new PrincipalContext(ContextType.Machine), name);
            }
            else
            {
                return Principal.FindByIdentity(new PrincipalContext(ContextType.Domain, domainName), name);
            }
        }
    }
}