Reputation: 1098
I want to bind to to a Directory Object on Active Directory using gMSA in a C# service.
What I am aware (... and able to do ):
If the C# service is running in the context of the gMSA, then following code works fine (this is password less bind):
DirectoryEntry entry = new DirectoryEntry("LDAP://172.5.25.5:389/CN=MyUser,OU=MyOU,DC=Example,DC=lab");
_log.info("Authentication Type: " + entry.AuthenticationType.GetTypeCode());
_log.info("Name is: " + entry.Name);
Question 1
(Before actually asking the question, I will try to give the background and provide the code for my attempts)
But what I actually want to do is to bind to the Directory Object like a normal User/ Service account!
Reasons:
Why gMSA:
Assumptions and Prerequisites
principalsAllowedToRetrivePassword
for all the local/cross domain/ cross forest gMSAs of the domains to which the service needs to bind for LDAP connectionFor a normal User account, this is how we usually bind to a Directory Object using its username and password:
DirectoryEntry entry = new DirectoryEntry("LDAP://172.5.25.5:389/CN=MyUser,OU=MyOU,DC=Example,DC=lab",
"[email protected]", "P@ssw0rd!", AuthenticationTypes.Secure);
But when I do the same with gMSA it fails with error: Username or password is incorrect
Here are more details in to the code:
Retrieve the gMSA Password:
using (PowerShell ps = PowerShell.Create())
{
// This will succeed since the C# service is running under the context of
//Administrator and is been added to principalsAllowedToRetrievePassword for the concerned gMSA
ps.AddCommand("Get-ADServiceAccount")
.AddParameter("Identity", gMSA)
.AddParameter("Properties", "msds-ManagedPassword");
Collection<PSObject> results = ps.Invoke();
foreach (PSObject result in results)
{
Object managedPasswordBlob = result.Properties["msds-ManagedPassword"].Value;
ps.Commands.Clear();
// This is a DS-Internals hack to get the password for gMSA in clear text
// I have installed their package on my machine...
// This code is pretty straight forward can can directly incorporated in code
// without the need for the package installation...
ps.AddCommand("ConvertFrom-ADManagedPasswordBlob")
.AddParameter("Blob", managedPasswordBlob);
Collection<PSObject> passwordResults = ps.Invoke();
if (passwordResults.Count > 0)
{
string currentPassword = passwordResults[0].Properties["CurrentPassword"].Value.ToString();
}
}
}
This code perfectly works fine and I get the cleartext password for the gMSA. But when I use the same in following piece of code, I get an error saying: username or password is incorrect
The code that fails:
// note: currentPassword is what I got through the above snippet!
DirectoryEntry entry = new DirectoryEntry("LDAP://172.5.25.5:389/CN=MyUser,OU=MyOU,DC=Example,DC=lab",
"[email protected]", currentPassword, AuthenticationTypes.Secure);
Note: I tried this with following LDAP URLS but with no luck:
a. LDAP://example.lab:389/CN=MyUser,OU=MyOU,DC=Example,DC=lab
b. LDAP://hostname.example.lab:389/CN=MyUser,OU=MyOU,DC=Example,DC=lab
Now, getting back to the actual question: What am I doing wrong here? Is this even possible?
Question 2
What worked for me?
I was able to form the LdapConnection using the gMSA and its retrieved password:
LdapConnection connection = new LdapConnection(new LdapDirectoryIdentifier("hostname.example.lab", 389, false, false));
NetworkCredential cred = new NetworkCredential("gMSA", currentPassword, "example.lab");
connection.SessionOptions.Sealing = true;
connection.SessionOptions.SaslMethod = "GSSAPI";
connection.Credential = cred;
try
{
connection.Bind();
SearchRequest searchRequest = new SearchRequest();
searchRequest.DistinguishedName = "CN=My,OU=MyOU,DC=Example,DC=lab";
searchRequest.Scope = System.DirectoryServices.Protocols.SearchScope.Subtree;
searchRequest.Attributes.Add("SamAccountName");
DirectoryResponse response = connection.SendRequest(searchRequest);
}
catch(Exception e)
{
//....
}
This code works perfectly fine!
So:
LdapConnection
using the gMSA's password, then why can't I for the DirectoryEntry
using the same?DirectoryEntry
object, either from the LdapConnection
object/ DirectoryResponse
object?Question 3: Security Considerations
Thanks in Advance!
Update 1: Trying to reduce the confusion of the complicated ask.
We have a solution where:
Now the ask is to avoid taking password as input. We cannot use keytab files and also don't want to use certificates as at some point they may get expired. So, we want to use something that can go for ever!
Naturally gMSA came to our mind and we are now exploring of using it!
I hope this clears the doubts further and makes sense to my questions and ask
Upvotes: 2
Views: 515