// 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;
///
/// Contains methods for User Group verification
///
public static class UserGroupVerifier
{
///
/// Create a local group on the machine
///
///
/// Has to be run as an Admin
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();
}
///
/// Deletes a local group from the machine
///
/// group name to delete
/// Has to be run as an Admin
public static void DeleteLocalGroup(string groupName)
{
GroupPrincipal newGroup = GetGroup(String.Empty, groupName);
if (null != newGroup)
{
newGroup.Delete();
}
}
///
/// Verifies that a group exists or not
///
/// domain name for the group, empty for local groups
/// the group name
public static bool GroupExists(string domainName, string groupName)
{
GroupPrincipal group = GetGroup(domainName, groupName);
return null != group;
}
///
/// Sets the group comment for a given group
///
/// domain name for the group, empty for local users
/// the group name
/// comment to be set for the group
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();
}
///
/// Adds the specified group to the specified local group
///
/// Member to add
/// Group to add too
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() });
}
///
/// Find the specified group in AD
///
/// group name to lookup
/// DirectoryEntry of the group
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;
}
///
/// Verifies the group comment for a given group
///
/// domain name for the group, empty for local users
/// the group name
/// the comment to be verified
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));
}
///
/// Verify that a given group is member of a local group
///
/// domain name for the group, empty for local groups
/// the member name
/// list of groups to check for membership
public static void VerifyIsMemberOf(string domainName, string memberName, params string[] groupNames)
{
IsMemberOf(domainName, memberName, true, groupNames);
}
///
/// Verify that a given group is NOT member of a local group
///
/// domain name for the group, empty for local groups
/// the member name
/// list of groups to check for membership
public static void VerifyIsNotMemberOf(string domainName, string memberName, params string[] groupNames)
{
IsMemberOf(domainName, memberName, false, groupNames);
}
///
/// Verify that a given user is member of a local group
///
/// domain name for the group, empty for local groups
/// the member name
/// whether the group is expected to be a member of the groups or not
/// list of groups to check for membership
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);
}
///
/// Returns the GroupPrincipal object for a given group
///
/// Domain name to look under, if Empty the LocalMachine is assumed as the domain
///
/// UserPrincipal Object for the group if found, or null other wise
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);
}
}
///
/// Returns the Principal object for a given name
///
/// Domain name to look under, if Empty the LocalMachine is assumed as the domain
///
/// Principal Object if found, or null other wise
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);
}
}
}
}