Created
February 2, 2022 00:44
-
-
Save jborean93/85641e43877a969fc297ebcfab4b3680 to your computer and use it in GitHub Desktop.
APIS that wrap the LMAccess Net*ServiceAccount APIS for Managed Service Accounts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add-Type -Namespace LmAccess -Name Native -MemberDefinition @' | |
[DllImport("Netapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "NetAddServiceAccount")] | |
private static extern int NativeNetAddServiceAccount( | |
IntPtr ServerName, | |
string AccountName, | |
IntPtr Password, | |
AddServiceFlags Flags); | |
/// <summary>Add a sMSA or gMSA to the current host.</summary> | |
/// <param name="accountName">The name of the MSA to install.</param> | |
/// <param name="flags">Optional flags for the install - currently these do not apply to gMSA accounts.</param> | |
public static void NetAddServiceAccount(string accountName, AddServiceFlags flags) | |
{ | |
int errCode = NativeNetAddServiceAccount(IntPtr.Zero, accountName, IntPtr.Zero, flags); | |
if (errCode != 0) | |
throw new System.ComponentModel.Win32Exception(RtlNtStatusToDosError(errCode)); | |
} | |
[DllImport("Netapi32.dll")] | |
private static extern int NetApiBufferFree( | |
IntPtr Buffer); | |
[DllImport("Netapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "NetEnumerateServiceAccounts")] | |
private static extern int NativeNetEnumerateServiceAccounts( | |
IntPtr ServerName, | |
int Flags, | |
out int AccountsCount, | |
out IntPtr Accounts); | |
/// <summary>Enumerates all the managed service accounts installed on the host.</summary> | |
/// <returns>The names of all the managed service accounts that are installed.</returns> | |
public static string[] NetEnumerateServiceAccounts() | |
{ | |
int count = 0; | |
IntPtr buffer = IntPtr.Zero; | |
int errCode = NativeNetEnumerateServiceAccounts(IntPtr.Zero, 0, out count, out buffer); | |
if (errCode != 0) | |
throw new System.ComponentModel.Win32Exception(RtlNtStatusToDosError(errCode)); | |
try | |
{ | |
if (count == 0) | |
{ | |
return Array.Empty<string>(); | |
} | |
IntPtr[] strptrs = new IntPtr[count]; | |
Marshal.Copy(buffer, strptrs, 0, count); | |
string[] accounts = new string[count]; | |
for (int i = 0; i < strptrs.Length; i++) | |
{ | |
accounts[i] = Marshal.PtrToStringUni(strptrs[i]); | |
} | |
return accounts; | |
} | |
finally | |
{ | |
NetApiBufferFree(buffer); | |
} | |
} | |
[DllImport("Netapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "NetIsServiceAccount")] | |
private static extern int NativeNetIsServiceAccount( | |
IntPtr ServerName, | |
string AccountName, | |
out bool IsService); | |
/// <summary>Tests whether a managed service account is installed on the current server.</summary> | |
/// <param name="accountName">The name of the MSA to test.</param> | |
/// <returns>True if it is installed otherwise False</returns> | |
public static bool NetIsServiceAccount(string accountName) | |
{ | |
bool isService = false; | |
int errCode = NativeNetIsServiceAccount(IntPtr.Zero, accountName, out isService); | |
if (errCode != 0) | |
throw new System.ComponentModel.Win32Exception(RtlNtStatusToDosError(errCode)); | |
return isService; | |
} | |
[DllImport("Netapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "NetQueryServiceAccount")] | |
private static extern int NativeNetQueryServiceAccount( | |
IntPtr ServerName, | |
string AccountName, | |
int InfoLevel, | |
out IntPtr Buffer); | |
/// <summary>Gets information about the specified managed service account.</summary> | |
/// <param name="accountName">The service account to query.</param> | |
/// <returns>The state of the service account specified.</returns> | |
public static MsaInfoState NetQueryServiceAccount(string accountName) | |
{ | |
IntPtr buffer = IntPtr.Zero; | |
int errCode = NativeNetQueryServiceAccount(IntPtr.Zero, accountName, 0, out buffer); | |
if (errCode != 0) | |
throw new System.ComponentModel.Win32Exception(RtlNtStatusToDosError(errCode)); | |
try | |
{ | |
return (MsaInfoState)Marshal.ReadInt32(buffer); | |
} | |
finally | |
{ | |
NetApiBufferFree(buffer); | |
} | |
} | |
[DllImport("Netapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "NetRemoveServiceAccount")] | |
private static extern int NativeNetRemoveServiceAccount( | |
IntPtr ServerName, | |
string AccountName, | |
RemoveServiceFlags Flags); | |
/// <summary>Removes a sMSA or gMSA from the current host.</summary> | |
/// <param name="accountName">The name of the MSA account to remove.</param> | |
/// <param name="flags">Optional flags for the removal - currently these do not apply to gMSA accounts.</param> | |
public static void NetRemoveServiceAccount(string accountName, RemoveServiceFlags flags) | |
{ | |
int errCode = NativeNetRemoveServiceAccount(IntPtr.Zero, accountName, flags); | |
if (errCode != 0) | |
throw new System.ComponentModel.Win32Exception(RtlNtStatusToDosError(errCode)); | |
} | |
[DllImport("Ntdll.dll")] | |
private static extern int RtlNtStatusToDosError( | |
int Status); | |
[Flags] | |
public enum AddServiceFlags : uint | |
{ | |
None = 0x00000000, | |
/// <summary>Do not create the sMSA in AD, only link to the host if it already exists.</summary> | |
LinkToHostOnly = 0x00000001, | |
} | |
[Flags] | |
public enum RemoveServiceFlags : uint | |
{ | |
None = 0x00000000, | |
/// <summary>Only unlink the sMSA from the host, do not delete in AD.</summary> | |
UnlinkFromHostOnly = 0x00000001, | |
} | |
public enum MsaInfoState | |
{ | |
/// <summary>The account does not exist or the gMSA is not installed.</summary> | |
NotExist = 1, | |
/// <summary>The account exists but is not an MSA.</summary> | |
NotService, | |
/// <summary>The credential cannot be fetched from AD.</summary> | |
CannotInstall, | |
/// <summary>The sMSA can be installed.</summary> | |
CanInstall, | |
/// <summary>The MSA account is installed.</summary> | |
Installed, | |
} | |
'@ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment