Topshelf, NLog and File Permissions - windows

I have a Windows service application that uses the TopShelf library and I'm installing it in AWS during the cfn-init using the handy command line features that you get with topshelf.
C:\handy_service\> HandyService.exe install start
This basically installs the service in the registry and then calls sc start, but it's quite useful because it checks the service name matches what you expect and it allows you to configure the user that service will run as using the nice fluent API.
The installer code also writes some diagnostic logs to NLog if the service is configured to use NLog in general.
The problem is this: the installer runs as the default local administrator account that the AMI starts with and the NLog file gets created by this user. When the service starts up as the Network Service user, it doesn't have permission to write to the NLog log file.
How can I get my service to write to the log file? I've thought about setting the permissions programmatically but it looks nasty and I'd have to determine the log file name as this is generated dynamically based on the ec2 instance id. Also, it's not entirely obvious at what point the log file is first created. The easiest hack that I might go with is having two NLog.configs and switching one out at the end of the install after the logger is flushed. But because there is some overlap in time between the service starting and the installer exiting, I expect I'll lose a few lines of logging here.
Any clean suggestions would be greatly appreciated!

In the end I went with setting the permissions on the logs folder at deploy time. It's actually pretty straightforward with icacls, only a couple of lines in rake for instance, assuming you know where your logs folder is going to be:
sh %{icacls "#{logs_dir}" /grant "#{username}":(OI)(W)}
Not calling UseNLog() in the service config would also be a simple option, any install-time errors would go in the Windows event log in that case.

Related

How to enable networking before User Data scripts are run in AWS Windows instances

I have been struggling with bootstrapping my Windows instances in AWS. I need to download some things from S3 and other places when the instance starts up and execute them.
This seems to be really straightforward for Linux instances, but not so much for Windows instances.
I have a user data script that works when I run it after logging into the instance, but it doesn't work when it runs as part of the EC2Launch/EC2Config described here: https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2-windows-user-data.html
I've found that the reason it doesn't work is that I am unable to download things from the internet due to: "The operation being requested was not performed because the user has not logged on to the network. The specified service does not exist."
Really what I'm trying to do is the following:
Download AWS_CLI Installer
Right now I'm using bitsadmin to try to download the installer from https://s3.amazonaws.com/aws-cli/AWSCLI64.msi
Install AWS_CLI
I am able to install the CLI with the CLI installer using msiexec and the /qn flags once it's on the box
Pull items from S3
This should be able to be done with aws s3 cp or sync
Install Python (installer stored in S3)
I am able to install the installer with msiexec once it's on the box similar to the CLI installer
Execute (python) scripts pulled from S3
Does anyone know of a better way to do this? This all works after I RDP in, but not as part of the Launch Script.
TL;DR - I need to download things using the EC2Launch User Data script provided to my EC2 Windows instances but the network doesn't seem to be available when it runs.
Thanks in advance for your help!
I Ran into a similar issue, I was using BITS to download an installer on a "user data" script and was getting the same error: "The operation being requested was not performed because the user has not logged on to the network. The specified service does not exist."
This not due to network issues, but rather to how BITS works, the user starting the download job must be logged on the machine, which it seems not to be the case for "user data" execution, which "runs as" the local Administrator without the user being logged in a way that BITS recognizes. From BITS documentation:
For BITS to detect that a user is logged on, the user must use one of the following interactive logon options:
Log on through the Welcome screen.
Log on to a terminal client.
Use fast user switching.
Starting with Windows 10, version, log on from another device using Remote Powershell.
During the script execution the network is mounted and ready to use, you can download your files using other methods that do not rely on BITS(e.g.: Invoke-WebRequest (rather slow for bigger files) or using System.Net.WebClient, both on PowerShell).

OEM 13C Log File Monitoring

I have installed OEM 13c and deployed a couple of agents and want to test out the Log File Monitoring utility. I have enabled it and added a log file to monitor.
When I go and test it out, it does not show any alerts when they are put into the Log File. On the agent server, I have tailed the file and see the messages coming into the log file.
Does anyone have experience adding log files to OEM? I could have configured it wrong. Or is there any troubleshooting steps that I can follow to see if the server is even contacting the agent for reading the log file. Status of the agent is good with no incidents.
Without access to the system, it would be difficult to tell you the exact cause of this issue. However, I can list a few potential causes of this issue that I have experienced personally:
Permissions. The Oracle Enterprise Manager Agent is very convoluted when it comes to system permissions within a remote server. The agent can be owned and run as any number of users but during metric evaluation, may also need sudo or pam-authentication permissions to access certain entities on the server. Depending on the authentication profiles on that server, this could be the cause of your issue. There are ways to grant the agent access through the PAM stack if that is necessary.
Syntax. The wildcard syntax in the OEM GUI can be a little confusing as well. I would play with the wildcard elements a bit on the "String" component to ensure that it isn't as simple as adding wildcards to the beginning and end of the string. Without diving into the binaries of the agent plugins, it is difficult to assess exactly how the agent is evaluating this particular metric
One suggestion I would have is to go through the agent commands. There are specific commands you can run to manually force an agent to evaluate a particular metric for a particular target. This can allow you to manually trigger the metric collection locally on the server and evaluate what exactly is being performed at the agent level.
On the system I was running (12c) the command was as follows:
emctl control agent runCollection <hostname>:host host_storage

remote wevtutil "The account is not authorized to log in from this station."

I am responsible for running centralized backups of Windows Security logs on a network of ~15 Windows boxes. To automate this task, I have been writing a Powershell script that utilizes wevtutil's /r parameter to do it all remotely. All of the boxes are connected to a Sharepoint network drive that I was hoping to copy the logs to so that I could centralize all of the logs, but I've run into some trouble.
The script runs fine when I pass it the ip of the Windows box that it's running on. The logs are copied to the Sharepoint without a hitch. The script also runs fine when I just tell it to copy the logs locally. However, when the script trys to remotely copy the computer's log to the sharepoint, I get a Failed to Archive Security log. The account is not authorized to log in from this station. error.
The format of the command is
wevtutil epl Security \\path\to\sharepoint\[hostname]-[datetime]Security.evtx /r:[hostname]
I am running the script as a domain admin. I have also ran the script with the credentials of a local admin and I got a generic access denied error.
A google search for the error message mostly includes computers not being able to access network drives (not remote wevtutil specifically) and include a lot of messing around in
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters
or
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters
which have not yielded any results. I am also restricted to Powershell 1, so I cannot use Powershell itself remotely AFAIK.
I could just put the script on each machine and run it locally with task scheduler, but I was hoping for a more elegant solution. Does anyone have experience with using wevtutil in this way and can point me in the right direction, or perhaps even suggest a better technique/tool?
How much latitude do you have to implement another solution?
If you wanted to do something with the logs, or make them easily searchable, you could set up a free Splunk server and either use a Splunk forwarder to ship the logs off box, or you could also use Powershell to send the logs to Splunk's HTTP event collector.

Can a Windows service install another Windows service?

I am having trouble when I have one Windows service try to install another Windows service.
Specifically, I have a TeamCity agent running tests for me on a Windows 2008 AWS instance. The tests are written in Java, which shell out to a .bat script to install a service (let's call it Service A), giving it a unique name each time.
The offending line is in the .bat script: sc create "%serviceName%" binPath= %binPath% DisplayName= "%serviceDisplayName:"=%" start= %serviceStartType%. I believe as long as the service name is unique that should work.
And indeed it does work if I run the tests manually on the command line, using an administrator account. Service A is installed, the test completes and Service A is uninstalled at the end.
I have tried running the TeamCity agent as LocalSystem, as Administrator, and as another user that is member of the administrators group. I have also tried disabling UAC completely.
Presumably the problem is access denied type errors, although that is not clear at this point. There are a few avenues to explore still, but it is a simple question really: are processes running as services forbidden from installing other services? Are there special things I have to do to configure the machine/ account to allow it to do this?
The point of the test it to install and use Service A, so workarounds are not relevant - Service A must be operated as a black box.
Thanks!
There are no restrictions on creating services with regards to how the creating process can execute, as long as the process has the appropriate permissions. That is to say, a process could be running as a service and create another service -- the only consideration here is the appropriate permission level.
The problem that often occurs with running batch scripts from within processes (as opposed to directly through user input on the command line) is that the environment expected isn't always the environment that is loaded. In this case, it appears that the env variables referred to in the batch script weren't properly set when running as a service, which of course then caused the service install failure. Correcting the environment loaded when the batch script is shelled out is the correct solution here.

service doesn't behave the same as command line

I am running on a Windows Server 2003. This is my problem:
I wrote a Perl script to automate the copy of some files from my Server machine to some network drives. I am using xcopy to copy the files. My problem is the permissions.
If I run the script from the command line, it works, all the copies are successful.
If I try to run the script using a service all the copies fail. This service is a program that I wrote that takes the script and runs it. In the background all it is doing is to call the C function 'system' and it runs the same program that I can run from the command line.
I have tried many variations of this to figure out what is wrong with it but I can't see why the service would not run the same way I run it from the command line.
I set up the service to run as the same user I am using from the command line.
I also tried to map the network drives as the user that has writing permission but the result is the same. Manually the script works, from the service, it doesn't.
Any suggestion is appreciated.
Thanks
Tony
The service may be running as the system and not have access to the network drives. In the Service settings, change the service to run under your account (or an account with the relevant permissions/mappings).
When the service runs, it uses whatever credentials you specify in the Services manager of Windows. The default, LOCAL SERVICE, probably does not have permission to access the resources to be copied.
Create a new user account with the minimum set of permissions needed to perform the copy and configure your service to run under that account.
I did figure out the issue (I think), and that matches what I later found in another post:
https://serverfault.com/questions/4623/windows-can-i-map-a-network-drive-for-a-service-account
<...Persistent drive mappings are only restored during an interactive login, which the service does not use. I believe the only way to get a service to use a network drive is for that service to map the drive itself or alternatively for it to us a UNC path instead of a mapped drive.>
What I did was mapping the drive using the service and that seems to work. It turns out, if I map the drive and save credentials, then I can access later the drive without having to map it again. I don't know why this approach seems to work though.
-Thanks everybody for your help.
Tony

Resources