DSC update registry in HKEY_CURRENT_USER to enable lock screen saver - windows

I have a DSC pull server that work great but lately I expirance issues to update registey value on HKEY_CURRENT_USER in order to enable screen saver.
DCS Resource:
Registry ScreenSaveActive
{
Ensure = "Present"
Key = "HKEY_CURRENT_USER\Control Panel\Desktop"
ValueName = "ScreenSaveActive"
ValueData = "1"
Force = $True
}
When I am trying to any value in "HKEY_LOCAL_MACHINE" it worked.
any Idea how to resolved it or alternative way.
Thanks,
Cfir.

DSC runs in the context of local system. You will have to use RunAs with the desired user in order to access HKCU. This blog explains the feature in detail http://nanalakshmanan.com/blog/Understanding-RunAs/

Related

Issue with authenticating to google api or app misonfiguration

So, just a heads up, this is my first time working with google's apis and developer console, so forgive me if I missed something obvious that a more seasoned google developer would deem common sense. That being said. I am trying to create an installed application which will upload a video to youtube under my account. I am writing the application in powershell, so I am importing the appropriate google .Net libraries when the script is launched. From there, I essentially used the sample located here and just converted the content to powershell:
Add-Type -AssemblyName mscorlib
Add-Type -AssemblyName System.Net.Http
Add-Type -AssemblyName System
Add-Type -AssemblyName System.Core
Add-Type -AssemblyName System.Numerics
Add-Type -AssemblyName System.Xml
Add-Type -AssemblyName System.Xml.Linq
Add-Type -AssemblyName System.Data
Add-Type -AssemblyName System.Runtime.Serialization
#the below command imports the following assemblies: Google.Apis.Auth.dll, Google.Apis.Auth.PlatformServices.dll, Google.Apis.Core.dll, Google.Apis.dll, Google.Apis.PlatformServices.dll, Google.Apis.YouTube.v3.dll
Get-ChildItem 'C:\Users\whiggs\Documents\SAPIEN\PowerShell Studio\Projects\youtube\*.dll' | % {[reflection.assembly]::LoadFrom($_.FullName)}
$vid = "C:\Users\whiggs\Documents\gery2.mp4"
#$file = [System.IO.File]::OpenRead("C:\Users\whiggs\Documents\SAPIEN\PowerShell Studio\Projects\youtube\client_id.json")
$filemode = [System.IO.FileMode]::Open
$fileaccess = [System.IO.FileAccess]::Read
$stream = New-object System.IO.FileStream -ArgumentList "C:\Users\whiggs\Documents\SAPIEN\PowerShell Studio\Projects\youtube\client_secret.json", $filemode, $fileaccess
$googlebroker = New-object Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker
$thing = [Google.Apis.Auth.OAuth2.GoogleClientSecrets]::Load($stream)
[string[]]$scope = [Google.Apis.YouTube.v3.YouTubeService+ScopeConstants]::YoutubeUpload
#$scope = [Google.Apis.YouTube.v3.YouTubeService+Scope]::YoutubeUpload
$cancellation = [System.Threading.CancellationToken]::None
$googlebroker = [Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker]::AuthorizeAsync($thing.Secrets, $scope, "<google_username>", $cancellation)
$googlebroker.Wait()
[Google.Apis.Auth.OAuth2.UserCredential]$cred = $googlebroker.Result
$baseclient = new-object Google.Apis.Services.BaseClientService+Initializer
$baseclient.HttpClientInitializer = $cred
$baseclient.ApplicationName = "Contacts Tool"
$service = New-Object Google.Apis.YouTube.v3.YouTubeService($baseclient)
$video = New-Object Google.Apis.YouTube.v3.Data.Video
$video.Snippet = New-Object Google.Apis.YouTube.v3.Data.VideoSnippet
$video.Snippet.Title = "test"
$video.Snippet.Description = "none"
$video.Status = New-Object Google.Apis.YouTube.v3.Data.VideoStatus
$video.Status.PrivacyStatus = "public"
$vidstream = New-Object System.IO.FileStream -ArgumentList $vid, $filemode
$request = $service.Videos.Insert($video, "public", $vidstream, "video/*")
$task = $request.UploadAsync()
$task.Wait()
$vidstream.close()
$vidstream.Dispose()
Don't really need to include the code, because I know it is written correctly as no exception is generated. When I run the above code, it runs to completion without generating an exception, but if I take a look at the object stored in $task (type System.Threading.Tasks.Task), while the overall object reports that it ran to completion, digging deeper into the object's "Result" property reveals the task actually failed, and digging even further into the "exception" property provides the below error message:
The service youtube has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
Access Not Configured. YouTube Data API has not been used in project <snip> before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/youtube.googleapis.com/overview?project=<snip> then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry. [403]
Errors [
Message[Access Not Configured. YouTube Data API has not been used in project <snip> before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/youtube.googleapis.com/overview?project=<snip> then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.] Location[ - ] Reason[accessNotConfigured] Domain[usageLimits]
]
at Google.Apis.Upload.ResumableUpload`1.<InitiateSessionAsync>d__25.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Google.Apis.Upload.ResumableUpload.<UploadAsync>d__70.MoveNext()
So, it is clear that there is some kind of issue with the app as it is configured or the way in which I am authenticating to it. However, I know that the app is at least receiving the requests, as you can see here. So, after doing so research, I have a couple of educated guesses as to what the problem might be, and need some input as to a) which of these (if any) is the actual problem and b) what needs to be done to correct it. My first educated guess involves the parameters I passed to the "AuthorizeAsync" method of the Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker class. According to this document:
"In this sample code a new UserCredential instance is created by calling the GoogleWebAuthorizationBroker.AuthorizeAsync method. This static method gets the client secret (or a stream to the client secret), the required scopes, the user identifier, the cancellation token for cancelling an operation, and an optional data store. If the data store is not specified, the default is a FileDataStore with a default Google.Apis.Auth folder. The folder is created in Environment.SpecialFolder.ApplicationData."
The part I want to focus on in the above statement is "the user identifier", as that is all the information that provided as to this parameter's description.
The value that I put in was a string containing the user name for the google account that the app is registered under and the account that would upload the youtube videos, but I don't know if that was the value that was needed, as I had to login to the account anyway via a web browser as part of this process. If this is indeed the problem, what is "the user identifier" as far as this parameter is concerned. A little more detail in the documentation can go a long way. My second educated guess as to what is causing this has to do with the configuration of the application, but more specifically, the generated oauth credentials. The scopes that the app would need access to are apparently considered sensitive, and, if I am understanding this correctly, I have to authenticate from a verified domain and configure a bunch of advanced settings that, as someone writing this project for myself and not a company, I just do not have access to. I just want to upload a youtube video to my account, so why do I need to authenticate from a verified domain? What can I do to get around this? Any info would be great.

Issue with authenticating to google api or issue with app

So, just a heads up, this is my first time working with google's apis and developer console, so forgive me if I missed something obvious that a more seasoned google developer would deem common sense. That being said. I am trying to create an installed application which will upload a video to youtube under my account. I am writing the application in powershell, so I am importing the appropriate google .Net libraries when the script is launched. From there, I essentially used the sample located here and just converted the content to powershell:
Add-Type -AssemblyName mscorlib
Add-Type -AssemblyName System.Net.Http
Add-Type -AssemblyName System
Add-Type -AssemblyName System.Core
Add-Type -AssemblyName System.Numerics
Add-Type -AssemblyName System.Xml
Add-Type -AssemblyName System.Xml.Linq
Add-Type -AssemblyName System.Data
Add-Type -AssemblyName System.Runtime.Serialization
#the below command imports the following assemblies: Google.Apis.Auth.dll, Google.Apis.Auth.PlatformServices.dll, Google.Apis.Core.dll, Google.Apis.dll, Google.Apis.PlatformServices.dll, Google.Apis.YouTube.v3.dll
Get-ChildItem 'C:\Users\whiggs\Documents\SAPIEN\PowerShell Studio\Projects\youtube\*.dll' | % {[reflection.assembly]::LoadFrom($_.FullName)}
$vid = "C:\Users\whiggs\Documents\gery2.mp4"
#$file = [System.IO.File]::OpenRead("C:\Users\whiggs\Documents\SAPIEN\PowerShell Studio\Projects\youtube\client_id.json")
$filemode = [System.IO.FileMode]::Open
$fileaccess = [System.IO.FileAccess]::Read
$stream = New-object System.IO.FileStream -ArgumentList "C:\Users\whiggs\Documents\SAPIEN\PowerShell Studio\Projects\youtube\client_secret.json", $filemode, $fileaccess
$googlebroker = New-object Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker
$thing = [Google.Apis.Auth.OAuth2.GoogleClientSecrets]::Load($stream)
[string[]]$scope = [Google.Apis.YouTube.v3.YouTubeService+ScopeConstants]::YoutubeUpload
#$scope = [Google.Apis.YouTube.v3.YouTubeService+Scope]::YoutubeUpload
$cancellation = [System.Threading.CancellationToken]::None
$googlebroker = [Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker]::AuthorizeAsync($thing.Secrets, $scope, "<google_username>", $cancellation)
$googlebroker.Wait()
[Google.Apis.Auth.OAuth2.UserCredential]$cred = $googlebroker.Result
$baseclient = new-object Google.Apis.Services.BaseClientService+Initializer
$baseclient.HttpClientInitializer = $cred
$baseclient.ApplicationName = "Contacts Tool"
$service = New-Object Google.Apis.YouTube.v3.YouTubeService($baseclient)
$video = New-Object Google.Apis.YouTube.v3.Data.Video
$video.Snippet = New-Object Google.Apis.YouTube.v3.Data.VideoSnippet
$video.Snippet.Title = "test"
$video.Snippet.Description = "none"
$video.Status = New-Object Google.Apis.YouTube.v3.Data.VideoStatus
$video.Status.PrivacyStatus = "public"
$vidstream = New-Object System.IO.FileStream -ArgumentList $vid, $filemode
$request = $service.Videos.Insert($video, "public", $vidstream, "video/*")
$task = $request.UploadAsync()
$task.Wait()
$vidstream.close()
$vidstream.Dispose()
Don't really need to include the code, because I know it is written correctly as no exception is generated. When I run the above code, it runs to completion without generating an exception, but if I take a look at the object stored in $task (type System.Threading.Tasks.Task), while the overall object reports that it ran to completion, digging deeper into the object's "Result" property reveals the task actually failed, and digging even further into the "exception" property provides the below error message:
The service youtube has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
Access Not Configured. YouTube Data API has not been used in project <snip> before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/youtube.googleapis.com/overview?project=<snip> then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry. [403]
Errors [
Message[Access Not Configured. YouTube Data API has not been used in project <snip> before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/youtube.googleapis.com/overview?project=<snip> then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.] Location[ - ] Reason[accessNotConfigured] Domain[usageLimits]
]
at Google.Apis.Upload.ResumableUpload`1.<InitiateSessionAsync>d__25.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Google.Apis.Upload.ResumableUpload.<UploadAsync>d__70.MoveNext()
So, it is clear that there is some kind of issue with the app as it is configured or the way in which I am authenticating to it. However, I know that the app is at least receiving the requests, as you can see here. So, after doing so research, I have a couple of educated guesses as to what the problem might be, and need some input as to a) which of these (if any) is the actual problem and b) what needs to be done to correct it. My first educated guess involves the parameters I passed to the "AuthorizeAsync" method of the Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker class. According to this document:
"In this sample code a new UserCredential instance is created by calling the GoogleWebAuthorizationBroker.AuthorizeAsync method. This static method gets the client secret (or a stream to the client secret), the required scopes, the user identifier, the cancellation token for cancelling an operation, and an optional data store. If the data store is not specified, the default is a FileDataStore with a default Google.Apis.Auth folder. The folder is created in Environment.SpecialFolder.ApplicationData."
The part I want to focus on in the above statement is "the user identifier", as that is all the information that provided as to this parameter's description.
The value that I put in was a string containing the user name for the google account that the app is registered under and the account that would upload the youtube videos, but I don't know if that was the value that was needed, as I had to login to the account anyway via a web browser as part of this process. If this is indeed the problem, what is "the user identifier" as far as this parameter is concerned. A little more detail in the documentation can go a long way. My second educated guess as to what is causing this has to do with the configuration of the application, but more specifically, the generated oauth credentials. The scopes that the app would need access to are apparently considered sensitive, and, if I am understanding this correctly, I have to authenticate from a verified domain and configure a bunch of advanced settings that, as someone writing this project for myself and not a company, I just do not have access to. I just want to upload a youtube video to my account, so why do I need to authenticate from a verified domain? What can I do to get around this? Any info would be great.
Correcting error in your understanding
"<google_username>" is used by filedatastore to store the credeitals for the user once they have consented access to your client. If you want to understand more about this then you should try and read my tutorial on file datastore
$googlebroker = [Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker]::AuthorizeAsync($thing.Secrets, $scope, "<google_username>", $cancellation)
Answer for your issue
YouTube Data API has not been used in project before or it is disabled.
Means that you have not enabled the YouTube api in your project on google Developer console or you have not applied and been granted any quota to this api yet. In Google developer console go to API Library -> YouTube Data API v3 and enable it. Once you have done that click manage then go to Quota. If you have not previously enabled it which i suspect you hadn't then now you will have 0 quota.
click the penile icon and apply for a quota for this api. It can take a while to get a response.
That error message simply means that you have not enabled the API in the Cloud Console. Can you post the error message you get, after you enabled the API? Also, make sure you're running the script with the credentials for the right project. You can run glcoud config list to see which project you're using.

Assigning Permission to Certificate's Private Key via Powershell (Win 2012 R2)

On a Windows Server 2012 R2 machine attached to a domain, I am running the following statements:
$target_machine_fqdn = [System.Net.Dns]::GetHostByName($env:computerName)
$certificate_request = Get-Certificate `
-Template 'AcmeComputer' `
-DnsName $target_machine_fqdn `
-CertStoreLocation 'Cert:\LocalMachine\My'
I'm requesting a certificate for the host from the domain's CA. The statement returns with no error. A certificate is generated for the machine and placed in it's "Cert:\LocalMachine\My" as requested.
Problem: I can't figure out how to grant a service account rights to the certificate's private key.
Now, there are about 1,000 articles instructing people how to grant permission by retrieving the UniqueKeyContainerName with code that starts like the following:
$certificate.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName
That won't work here. While the certificate has a private key, the private key data member is null:
In the cases where the solution I just eluded to works, the private key is on the file system. However, in this case, the private key is in the registry at the following:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SystemCertificates\MY\Keys
When using the Certificates MMC-snapin, I can see the certificate. I can manage permissions on the private key. So, I know it's there. Unfortunately, I need to automate the permission assignment so using the Certificates MMC-snapin isn't an option. I need to do this through Powershell some how.
I recently went through automating access to certificate private key myself. I too found a number of places telling me to modify the ACLs of the key data on the hard drive, but that was not satisfying since when I checked the permissions to the private key using PowerShell the user I added wasn't listed. So much web searching, a few articles, and a fair bit of trial and error led me to this.
I start by defining the user object, and the access that I want to grant them:
# Create NTAccount object to represent the account
$AccountName = 'Domain\UserName'
$User = New-Object System.Security.Principal.NTAccount($AccountName)
# Define AccessRule to be added to the private key, could use 'GenericRead' if all you need is read access
$AccessRule = New-Object System.Security.AccessControl.CryptoKeyAccessRule($User, 'FullControl', 'Allow')
Then I open the local machine certificate store as Read/Write, and find the certificate that I'm looking for:
# Define the thumbprint of the certificate we are interested in
$Thumb = '63CFDDE9A748345CD77C106DAA09B805B33951BF'
# Open Certificate store as read/write
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("My","LocalMachine")
$store.Open("ReadWrite")
# Look up the certificate's reference object in the store
$RWcert = $store.Certificates | where {$_.Thumbprint -eq $Thumb}
Then I make a new CSP (Crypto Service Provider) parameter set, based off the existing certificate, add the new access rule to the parameter set.
# Create new CSP parameter object based on existing certificate provider and key name
$csp = New-Object System.Security.Cryptography.CspParameters($RWcert.PrivateKey.CspKeyContainerInfo.ProviderType, $RWcert.PrivateKey.CspKeyContainerInfo.ProviderName, $RWcert.PrivateKey.CspKeyContainerInfo.KeyContainerName)
# Set flags and key security based on existing cert
$csp.Flags = "UseExistingKey","UseMachineKeyStore"
$csp.CryptoKeySecurity = $RWcert.PrivateKey.CspKeyContainerInfo.CryptoKeySecurity
$csp.KeyNumber = $RWcert.PrivateKey.CspKeyContainerInfo.KeyNumber
# Add access rule to CSP object
$csp.CryptoKeySecurity.AddAccessRule($AccessRule)
Then we instantiate a new CSP, with those parameters, which will apply the new access rule to the existing certificate based off the flags we defined, and the key info we gave it.
# Create new CryptoServiceProvider object which updates Key with CSP information created/modified above
$rsa2 = New-Object System.Security.Cryptography.RSACryptoServiceProvider($csp)
Then we just close the certificate store, and we're all done.
# Close certificate store
$store.Close()
Edit: After looking around I realized that I had a couple certs that are the same. I believe that this is due to a non-RSA cipher being used to encrypt the private key. I used some of the info from this answer that explains how to work with a third party CNG crypto provider. I didn't like having to download an assembly to do the things in that answer, but I used a little bit of the code to get the path to the key (yes, there is a key on the drive), and added an ACL to the file, which did work for delegating rights to the private key. So here's what I did...
First, we verify that the certificate has a CNG based key:
[Security.Cryptography.X509Certificates.X509CertificateExtensionMethods]::HasCngKey($Certificate)
If that returns True then we're a go to move on past that. Mine did, I'm guessing yours will too. Then we find that key on the hard drive by reading the PrivateKey data (which is missing from $Certificate), and getting the UniqueName for it, and then searching the Crypto folder for that file.
$privateKey = [Security.Cryptography.X509Certificates.X509Certificate2ExtensionMethods]::GetCngPrivateKey($Certificate)
$keyContainerName = $privateKey.UniqueName
$keyMaterialFile = gci $env:ALLUSERSPROFILE\Microsoft\Crypto\*Keys\$keyContainerName
Then I grabbed the current ACLs for the file, made up a new AccessRule to give the desired user access to the file, added the rule to the ACLs I just grabbed, and applied the updated ACL back to the file.
$ACL = Get-Acl $keyMaterialFile
$AccountName = 'Domain\User'
$User = New-Object System.Security.Principal.NTAccount($AccountName)
$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($User,'FullControl','None','None','Allow')
$ACL.AddAccessRule($AccessRule)
Set-Acl -Path $keyMaterialFile -AclObject $ACL
After that I was able to look in certlm.msc and verify that the user had rights to the private key.
Dependency Update: Looks like Microsoft now publishes Security.Cryptography.dll, so you don't have to compile it off GitHub. If you have the AzureRM module installed you can find the DLL in a number of the component modules (I grabbed it from AzureRM.SiteRecovery).
The TheMadTechnician answered this question like a mf'n champ. Should he ever need me to help him bury a body, he need only call. I am adding to his answer with details for folks that cannot build/deploy the assembly
NOTE: The clrsecurity project had been posted to CodePlex, which was shutdown in 2017. The project was moved to github where it can be downloaded. The clrsecurity assembly referenced in the post is no longer supported.
Also, credit to Vadims Podāns (Crypt32) who wrote the article
Retrieve CNG key container name and unique name, which helps readers access the CNG private key using unmanaged code in Powershell.
If you are like me and cannot use the clrsecurity assembly, the .NET 4.5.6 framework introduced a elements we can leverage. Consider the following:
## Identify the certificate who's private key you want to grant
## permission to
$certificate = $(ls 'cert:\LocalMachine\My\C51280CE3AD1FEA848308B764DDCFA7F43D4AB1A')
## Identify the user you'll be granting permission to
$grantee_name = 'foo\lordAdam'
$grantee = New-Object System.Security.Principal.NTAccount($grantee_name)
## Get the location and permission-of the cert's private key
$privatekey_rsa = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($certificate)
$privatekey_file_name = $privatekey_rsa.key.UniqueName
$privatekey_path = "${env:ALLUSERSPROFILE}\Microsoft\Crypto\Keys\${privatekey_file_name}"
$privatekey_file_permissions = Get-Acl -Path $privatekey_path
## Grant the user 'read' access to the key
$access_rule = New-Object System.Security.AccessControl.FileSystemAccessRule($grantee, 'Read', 'None', 'None', 'Allow')
$privatekey_file_permissions.AddAccessRule($access_rule)
Set-Acl -Path $privatekey_path -AclObject $privatekey_file_permissions
We're using the GetRSAPrivateKey() method of the System.Security.Cryptography.X509Certificates.RSACertificateExtensions static class to return us the private key. We then grab the UniqueName (Key property has a UniqueName property). We use that to deduce the key file's location. The rest is granting file permissions.
If you want to see where private keys are stored, check out Key Storage and Retrieval.

Using Pgp.exe from a MVC application

I've been tasked with converting a legacy application to mvc. The app used pgp.exe to pgp sign user input and send it as an email. The application works locally and on a test server but won't run on a live server. I've had to jump though hoops such as running a specified user in the application pool so that we can set the keys in the users profile BUT it worked.
For some reason on the live server which is windows 2003 IIS 6 and identical to the testing server it fails. The problem is pgp.exe just wont seem to sign and create files the message I get from the console out put is. "Signature Error"?? When I put the command into a shell window logged in as the app pool user it runs no problem (after a fight with some permissions) but when running through the mvc application/IIS server it fails. The code used to call the process is below.
var startInfo = new ProcessStartInfo();
startInfo.FileName = _pgpexeLocation;
//startInfo.FileName = "pgp.exe";
startInfo.Arguments = string.Format("-sta \"{0}\" -u keyuser-z keypass +COMPATIBLE +FORCE", _tempFilePath);
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.LoadUserProfile = true;
using (Process exeProcess = Process.Start(startInfo))
{
// TODO: set limit to wait for and deal with exit
exeProcess.WaitForExit();
//var stringItem = exeProcess.StandardOutput.ReadToEnd();
//Logger.Info(stringItem);
}
I'm clutching at straws here hoping somebody has done something similar before and can help. I'm guessing it's key location or file location not being picked up somewhere but not sure what else to try?
Turns out that even though the app pool was using a specific user and I'd set the keys up in that users appdata folder when I checked the underlying process call it was actually trying to pick the keys up from the Default User profile. Not sure if this was an IIS config or something similar but moving the keys and pgp folder to this appdata instead worked?

What default credential Directory Entry binds to if it is running as a service on Windows

If I bind to a DirectoryEntry ( without any arguments) on the application mode to search all the users at my current domain, I could see the logged in in user is the default credential for DirectoryEntry since it finds all the users for my domain. With that, I would expect that this won't work if the application is run at service mode since account for service is SYSTEM which is not a user of my domain. However the code still works and it could get all the users of my logged in user domain.
I did some search on internet, I didn't find any answer on this when running as a service. Any idea? Any way I could get that default credential at power shell?
At service mode, the default credential for directory entry would be the credential which computer is used to login into the domain (called computer login). See this link: https://serverfault.com/questions/61191/what-happens-when-a-computer-joins-an-active-directory-domain.
I first tried to use System.Net.CredentialCache::DefaultNetworkCredentials
to try to get the default credential, however I found out the user and domain are all blank. It is confirmed from MSDN that we could not view those info with the returned NetworkCredentials.
So I added the following vb script (got the base code from this link: http://blogs.technet.com/b/heyscriptingguy/archive/2008/05/12/how-can-i-determine-the-distinguished-name-of-the-ou-where-the-logged-on-user-s-user-account-resides.aspx) to be called from power shell to get the dn of the current user
and save it to a file.
Set objSysInfo = CreateObject("ADSystemInfo")
strUserName = objSysInfo.UserName
Set objUser = GetObject("LDAP://" & strUserName)
Wscript.Echo objUser.distinguishedName
Set objFS = CreateObject("Scripting.FileSystemObject")
strTemp = "c:\temp\dn.txt"
Set objOutFile = objFS.CreateTextFile(strTemp,True)
objOutFile.Write(objUser.distinguishedName)
objOutFile.Close
Then when I ran it in service context, I found out that user is my computer itself, like this:
CN=my computer name,OU=Domain computer accounts,DC=domain,DC=local

Resources