Using MsDeploy to deploy Windows Services with preSync command - windows-services

Is anyone successfully using MsDeploy for deploying windows services with a preSync runCommand? I've got it working using an Administrator account, but can't for the life of me get it working on a standard user account. Unfortunately I can't use integrated authentication (we're deploying to an external box), and the thought of our Administrator password sitting in plaintext in logs on our build server doesn't exactly make me feel too comfortable. For that matter, neither does any user credentials - but I can't see a way around that.
The command I'm using is this:
"tools/deploy/msdeploy.exe" -verb:sync
-preSync:runCommand="tools\Deploy\PreSyncCommand.cmd",waitInterval=30000
-source:dirPath="C:\BuiltSourcePath"
-dest:computerName=https://server:8172/msdeploy.axd?site=dummysitename,userName=service-deploy,password=service-deploy-pass,authType=basic,dirPath="C:\DeployPath\"
-allowUntrusted
with rules set up in IIS for the dummy site to allow the authentication for the service-deploy windows account, with contentPath and runCommand permissions (for the moment set to C:\ as it's not entirely clear whether this needs to be set to the temporary path that MsDeploy streams to, or the deployment path?). The service-deploy account also has full control of the target directory. I get the following back:
Performing '-preSync'...
Info: Using ID '7a7d34a1-b5d8-49f1-960a-31c9cf825868' for connections to the remote server.
Info: Using ID '4d0b910c-aca4-4640-84bd-3597d22d99d1' for connections to the remote server.
Info: Updating runCommand (C:\TeamCity\buildAgent\work\aec989676b349656\tools\De
ploy\PreSyncCommand.cmd).
Warning: Access is denied.
Warning: The process 'C:\Windows\system32\cmd.exe' (command line '/c "C:\Windows
\ServiceProfiles\LocalService\AppData\Local\Temp\giz2t0kb.0ay.cmd"') exited with
code '0x1'.
This happens even if the contents of PreSyncCommand.cmd is blank. The same command runs fine if I pass in Administrator credentials. I've tried using ProcessMonitor to check if anything's being denied access but can't see any - so I'm guessing it's still a MsDeploy authentication rule. There's nothing in WmSvc.log (debugging is enabled), nor in the event log.
Any ideas? Thanks!

Since you're using Web Deploy via WmSvc, you need to setup appropriate delegation rules on the destination server:
Within IIS Manager, open the "Management Service Delegation" feature. Add a new rule which at least specifies the runCommand provider. In the Run As section, choose Specific User and provide credentials for a local administrator account on that machine. This is the identity under which your runCommand scripts will be executed. Finally, the user which you're specifying for the destination dirPath provider needs to be added to the delegation rule.
That allows you to invoke a deployment using a non-privileged account, and yet have it executed on the target machine under administrative credentials.
More information on IIS feature delegation: http://learn.iis.net/page.aspx/516/configure-the-web-deployment-handler/

Related

TFS Release, running PowerShell, cannot create DtlDownloads

I am trying to get some automatic deployments up and running using TFS 15 (on-premise). I have a powershell script on the deployment target to call.
The deployments starts fine by downloading the artifact. But when the agent runs the script it wants to create a folder C:\Windows\DtlDownloads (thats not part of my script but part of preparing things for TFS I guess). That fails:
##[debug]System.AggregateException: Failed to install 'VisualStudioRemoteDeployer20597940-38b2-4ba8-9a4d-fcc894308730' from service executable path VisualStudioRemoteDeployer.exe . Consult the logs below:
Access to the path 'DtlDownloads' is denied.
CategoryInfo :PermissionDenied: (C:\Windows\DtlDownloads:String) [New-Item], UnauthorizedAccessException
FullyQualifiedErrorId :CreateDirectoryUnauthorizedAccessError,Microsoft.PowerShell.Commands.NewItemCommand
The user used to logon is a server-local user named deploy who is also a local administrator on that machine. I also checked the effective access for that user on the windows folder and it should be able to create directories.
Something similar happens with the copy step. Robocopy signals two errors:
2017/03/16 08:57:21 ERROR 5 (0x00000005) Getting File System Type of Destination \\server.domain.com\c$\abc\def\
Access is denied.
and
2017/03/16 08:57:21 ERROR 5 (0x00000005) Creating Destination Directory \\server.domain.com\c$\abc\def\
Access is denied.
The second is a bit unexpected as the folder def already exists but I guess it is a follow up because getting the type failed beforehand.
The user itself must have been recognized because I get different errors when using invalid credentials. I have enabled WinRM using Enable-PSRemoting and ConfigureWinRM.ps1 from WinRM-Http-Https-Without-Makecert.
What could still restrict the permissions?
Update: Using a domain user instead of a local one of that server solves the issue. But I do not understand why. Can someone explain or even provide information how to make it work with a local user?
The username of either a domain or a local administrative account on
the target host(s).
Formats such as username, domain\username, machine-name\username, and .\username are supported.
UPN formats such as username#domain.com and built-in system accounts such as NT Authority\System are not supported.
Source Link
Both the domain account and local admin should be work. Please double check your format and give a try with another format.
One problem could be if that you have the agent as a service, that service has not the proper privileges, like being on Network Account. Try to change that to the user account which has administrative privileges.
Running "winrm quickconfig" fixed this problem for me
winrm quickconfig
https://learn.microsoft.com/en-us/windows/win32/winrm/installation-and-configuration-for-windows-remote-management

Remote Access to Secured Jenkins Server

I have a Jenkins installation on a machine running Windows Server 2008. The Jenkins installation is secured using Jenkins own user database with matrix-based security authorization. Anonymous users don't have any access, except to register an account. I have set up an account and gave this account full access.
Now I'd like to trigger a build remotely from a different machine that hosts the repository. I believe this should be possible by accessing the following URL:
https://[username]:[user_api_token]#[address.of.jenkins]:8080/job/[project]/build?token=[project_api_token]
However, this does not seem to be working for me. When I access this site in a browser, Jenkins forwards to the login-page, and does not start the build.
What am I doing wrong? It seems to be an authentication problem, as I'm not logged in after opening the URL above. Furthermore, if I give anonymous users full access, the URL works.
Try invoking the build from a command-line program like curl:
curl http://[userid]:[user_token]#localhost:8080/job/[project]/build?token=[proj_token]
or
curl --user [userid]:[user_token] http://localhost:8080/job/[project]/build?token=[proj_token]
I think your issue could be browser related, embedding credentials within the URL (Firefox pops up a warning in my case telling me I'm about to login to Jenkins)

Jenkins - remote access denied

I'm using the ArtifactDeployer plugin to deploy the build job artifacts to a remote location (Windows share SMB).
However Jenkins never manages to succeed. Throwing errors like:
[ArtifactDeployer] - Starting deployment from the post-action ...
[ArtifactDeployer] - [ERROR] - Failed to deploy. Can't create the directory ... Build step
[ArtifactDeployer] - Deploy artifacts from workspace to remote directories' changed build result to FAILURE
Local deployment works fine.
The Jenkins machine OS is Windows 7 32-bit Prof.
Jenkins is running as a service using a local system account.
I tried using another account, my user account but the service failed to start (Windows error 1069: the service did not start due to a logon failure).
The network service account did run but than Jenkins throws errors it can't access the .NET framework.
When manually trying the remote copy, this works fine. I can create directories and write to it. On the same machine of course.
I tried two different remote reference in Jenkins:
1) \\targetdirectory
2) I:\ - by mapping a drive letter to the remote dir in windows
No success...
Any tips or suggestions? Thanks!
Update 15/02/2012:
Still no solution or workaround for this issue.
It's not only the plugin, I hit also this issue using "Execute Windows batch command".
I found a bug report that I want to share.
Solution
I found a solution. You have to grant access persmission to the computer in a domain instead of the user of that machine. Seems very logic if you look back to it.
A 2nd solution is to run the service using a domain user account. Above I made a mistake by using the local user .\user in stead of DOMAIN\user.
If you don't have a domain, the following will work for sure. This should work even if you have a domain.
Background Info:
You need your mapped drive to be mapped for the same account that the service is using AND be available at the right time. Normally mapped drives are mapped only for the logged in user, at the time that they log in. Service user contexts don't get "logged in" per se -- for example, if I map a drive as MyUser and the service runs as MyUser, the drive won't be available until I actually log in by typing in my password. However, we can use a script to map the drive at startup (instead of login) for a particular user. Jenkins normally runs as Local System Account, so if you don't want to change that, you'll need to run the script below as the SYSTEM user. You can instead create a specific user for Jenkins to run as, if you don't want to grant this mapped drive to all services/processes that run as SYSTEM, and run both the service and the script below as that user (this is probably more secure).
Solution Steps:
In ArtifactDeployer you want to deploy to a mapped network drive. In my case this is S:.
There is no special setup for permissions on the remote share. (In my case, a Windows Server 2008 share with a username and password that is used for mapping the drive.)
Write a batch file MapDrives.bat in a place that your chosen user (default: SYSTEM) has access to, with the following in it:
net use S: "\\server_name\share_name" /persistent:yes password_here /USER:username_here
Note that I am mapping to S: in that line.
Via Task Scheduler, create a task that runs as the same user as the service (default: SYSTEM), triggers At Startup, and as it's action, runs the batch file MapDrives.bat.
Reboot and it should work!
Citations:
After diving through many pages and many tests, ultimately, the best suggestions were found here, and led me to the above solution.
https://stackoverflow.com/a/4763324/150794
Make sure your 'local system account' has access rights to the remote directory (including write access). Then use the notation
\\targetdirectory
Mapping drive letters to remote directories only applies to the user account you are currently working with. The drive letter mapping will not be available to any other account.

How can I test if I have permissions to install a service and have it run as me on the domain?

I'd like to write a service (that starts up and runs whenever the machine is on) that queries Active directory since the user IIS uses does not have permission to query AD. How do I determine if A) my workstation where I have local admin rights, and B) a shared team workstation will allow me to do this?
Anything you can do as an interactive user can be done by a service with appropriate permissions and configuration, so it isn't so much an issue of determining if you can, but rather configuring the service so that it can.
Your installation package should request an appropriate set of credentials (and of course must be run by a user with privileges to install such a service). The service itself should simply catch and log any permission exceptions.
As an example - look at the SQL Server installation process. Early on it requests that you specify accounts with the required privileges.

How do I grant a service user sufficient rights to create registry keys in windows 7

I have an application that runs as a service, and dynamically creates and publishes windows performance (perfmon) counters.
When I run the application under my own account (as a service) which has administrative privileges, I get the following error:
714: The specified registry key is referenced by a predefined handle.
When I run the application from the command line, no error is produced.
I believe that this is a result of UAC, but I don't particularly want to disable UAC altogether.
Any ideas?
It is not enough just to be logged in as an administrator. The service needs to have an embedded manifest that sets the requestedExecutionLevel to requireAdministrator.

Resources