Running self-hosted OWIN Web API under non-admin account - c#

Is it possible for a self-hosted OWIN Web API to run under a non-administrator account? I have already tried dozens of url reservations and nothing works. The service fails to start with "Access is denied". It works when the account is added to the administrator role but I don't want that. Code below is running on Win 7 framework 4.5.2.
//install-package microsoft.owin.hosting
//install-package Microsoft.Owin.Host.HttpListener
StartOptions options = new StartOptions();
options.Urls.Add("http://localhost:5000/");
//options.Urls.Add(string.Format("http://{0}:5000", Environment.MachineName));
//options.Urls.Add("http://+:5000/");
//options.Urls.Add("http://*:5000/");
using (WebApp.Start<WebAPISelfHostMinimal.Startup>(options))
{
while (!Terminate)
{
await Task.Delay(10); //keep cpu from getting pegged
}
LogUtil.LogInfo("Terminating owin host.");
}
EDIT - this is running under a Windows account.
C:\>netsh http add urlacl http://+:5000/ user=mini2012\svcAPI
URL reservation successfully added
C:\>sc start apiservice
[SC] StartService FAILED 5:
Access is denied.
C:\>netsh http add urlacl http://*:5000/ user=mini2012\svcAPI
URL reservation successfully added
C:\>sc start apiservice
[SC] StartService FAILED 5:
Access is denied.
C:\>netsh http add urlacl http://localhost:5000/ user=mini2012\svcAPI
URL reservation successfully added
C:\>sc start apiservice
[SC] StartService FAILED 5:
Access is denied.

It looks like the problem was with the URL reservation. I didn't need one. If there is a URL reservation, it will just prevent the owin host from starting with the access denied error. Also, the default port for owin host is 5000. If there is a "dead" process that is still running on that port, it will block your service from starting. To check you can run netstat -a -b at the command prompt.

Your service is running (most likely) under the LocalSystem (SYSTEM) account. This account is not in the Everyone security principal.
In short, to solve this, either make the namespace reservation for Anonymous Logon or change your service to run under the Network Service account which happens to be in the Everyone principal.
Third option is, of course, to create a new local/domain user, create the reservation for it and have the service run under this account. But then you'd have to worry about setting proper security permissions for it, so I'd go with one of the first two options.

Run this command line under admin
netsh http add urlacl url=http://*:8080/ user=MyUser

Related

PowerShell remoting from a Windows service

I have a Windows service that regulary runs a PowerShell script on a remote computer via WsManConnectionInfo/RunspaceFactory (following the steps from this article: Remotely Executing Commands in PowerShell using C#):
var connectionInfo = new WSManConnectionInfo(false, server, 5985, "/wsman",
"http://schemas.microsoft.com/powershell/Microsoft.PowerShell",
cred)
{
OperationTimeout = 4*60*1000,
OpenTimeout = 1*60*1000
};
using (var runSpace = RunspaceFactory.CreateRunspace(connectionInfo))
{
runSpace.Open();
using (var p = runSpace.CreatePipeline())
{
p.Commands.AddScript(script);
var output = p.Invoke();
...
}
}
Now, if I run the Windows service itself with an Administrator account, all is well. But if i run the service with the LocalSystem account, I get the following exception;
System.Management.Automation.Remoting.PSRemotingTransportException:
Connecting to remote server NOSRVDEV02 failed with the following error message :
WinRM cannot process the request. The following error with
errorcode 0x8009030d occurred while using Negotiate authentication:
A specified logon session does not exist. It may already have been terminated.
Possible causes are:
-The user name or password specified are invalid.
-Kerberos is used when no authentication method and no user name are specified.
-Kerberos accepts domain user names, but not local user names.
-The Service Principal Name (SPN) for the remote computer name and port does not exist.
-The client and remote computers are in different domains and there is no trust between the two domains.
After checking for the above issues, try the following:
-Check the Event Viewer for events related to authentication.
-Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTTPS transport.
Note that computers in the TrustedHosts list might not be authenticated.
-For more information about WinRM configuration, run the following command: winrm help config. For more information, see the about_Remote_Troubleshooting Help topic.
at System.Management.Automation.Runspaces.AsyncResult.EndInvoke()
at System.Management.Automation.Runspaces.Internal.RunspacePoolInternal.EndOpen(IAsyncResult asyncResult)
at System.Management.Automation.RemoteRunspace.Open()
...
Note: This has nothing to do with the credentials in WSManConnectionInfo - just the account settings in the service properties "Log On" tab.
I don't want to give the service admin privileges. Any ideas why the LocalSystem user fails to log in?
Additional info:
The remote computer is not a member of a domain.
I have tried to connect both by IP address and hostname (both are listed in the local computer's TrustedHosts).
EDIT: Even more info (summary of the comments):
Local computer: Windows 7 Ultimate 64bit (virtual machine on a Windows 8 box).
Remote computer: Windows Server 2008R2 Datacenter 64bit.
The main reason we don't want to change service user accounts is that this is an update to an old service which is already deployed on many clients (customers).
The service also accesses the Windows registry and the file system on the local computer, so setting the user account to something more restricted, like NetworkService, would just open a different can of worms.
A rather surprising solution to this one: The username in the PSCredential object (cred) needed to be prefixed with the domain-less remote computer's name, e.g. "MYREMOTESERVERNAME\remoteusername" and not just "remoteusername".
I have no idea why the prefix is needed only when connecting with the LocalSystem account though...

Self hosted OWIN and urlacl

I've created a self hosted Nancy/SignalR application self-hosted in OWIN using Microsoft.Owin.Host.HttpListener and Microsoft.Owin.Hosting
Things work perfectly fine locally but as soon as I try to use anything but localhost to access the app I get a HTTP Error 503. The service is unavailable error. I can't even access the app using 127.0.0.1 or the machine name.
I've tried adding the port to urlacl using
http add urlacl http://*:8989/ user=EVERYONE but doesn't seem to do anything.
here are the OWIN start options that I've tried,
var options = new StartOptions
{
Url = "127.0.0.1",
App = GetType().AssemblyQualifiedName,
Port = _configFileProvider.Port
};
var options = new StartOptions
{
App = GetType().AssemblyQualifiedName,
Port = _configFileProvider.Port
};
Here is the source code for the file that starts and stops the server.
so it turns out you need to pass in a url into StartOptions in the same format as the urlacl.
Changing the start options to the code below fixed the problem. now the app is accessible across the network.
var options = new StartOptions("http://*:8989")
{
ServerFactory = "Microsoft.Owin.Host.HttpListener"
};
I spend many hours solving similar issue on Windows 8.1.
StartOptions options = new StartOptions();
options.Urls.Add("http://localhost:9000");
options.Urls.Add("http://127.0.0.1:9000");
options.Urls.Add("http://192.168.0.102:9000");
options.Urls.Add(string.Format("http://{0}:9000", Environment.MachineName));
WebApp.Start<Startup>(options);
I could not listen or was getting 503 error...
If you want to listen on several IP addresses, each address needs its own urlacl record:
Does NOT work:
netsh http>add urlacl http://+:9000/ user=EveryOne
OK:
netsh http>add urlacl http://localhost:9000/ user=EveryOne
netsh http>add urlacl http://127.0.0.1:9000/ user=EveryOne
etc.
After adding reservation for each address individually, everything works fine.
Thanks to the info that #kay.one provided I was able to access my self-hosted Web API 2.2 (OWIN/Katana, console app) from the same machine via IP address. However just consolidate it into a simple step-by-step:
In Main of Program.cs (for console app): WebApp.Start<Startup>("http://*:8080");
From Windows Command Prompt (run as Administrator) enter netsh http add urlacl http://*:8080/ user=EVERYONE
Go to Windows Firewall with Advanced Security and add an Inbound Rule that opens up TCP port 8080
You should then be able to access from another machine using IP address or computer name.
Disclaimer: I'm not a security expert so I don't know the security implications of doing this.

HttpWebResponse: Windows service vs. console application

I have a problem that I haven't been able to resolve for two days.
In a console app, this code works fine:
url="http://www.reuters.com/finance/currencies/quote?srcAmt=1.00&srcCurr=USD&destAmt=&destCurr=ASD&historicalDate=MMddyyyy"
HttpWebRequest req = WebRequest.Create(url) as HttpWebRequest;
req.Timeout = 3000000;
using (HttpWebResponse resp = req.GetResponse() as HttpWebResponse)
{
// ...
}
But in my Windows service, GetResponse() is throwing the exception, "The remote name could not be resolved: 'www.reuters.com'".
I have no idea what I am doing wrong, maybe I am setting something wrong in ServiceInstaller.
Thanks for showing me the right track, but there is an additional issue.
I am working on virtual machine (I have got admin rights, but I have no experience with administration at all).
If I set account in service installer for the user (and give details of my login) then I have problems with the connection to the database (Odbc). Connection open throws me:
ERROR [08001] [MERANT][ODBC Sybase driver]
Allocation of a Sybase Open Client Context failed.
Sybase normally generates a SYBINIT.ERR file containing more specific reasons for failing.\r\n
ERROR [01S00] [MERANT][ODBC Sybase driver]
Invalid attribute in connection string: Port.
So if set Account User in ServiceInstaller I can't connect to the DB, else if I set Account to LocalSystem I can open connection to DB but I can't use GetResponse().
So the question is, what should I do when everything is placed on Windows Terminal Server?
I suppose that there could be something messed up with admin rights. What could I do to fix this? Thanks again.
Windows Service application run under the LocalSystem account by default, whereas your console app runs under your user account, you may therefore be meeting permission problems (windows firewall?)
You should run the service under the administrator account to see if this resolves your issue.

.NET HttpListener Prefix issue with anything other than localhost

I'm trying to use C# and HttpListener with a prefix of anything other than localhost and it fails (i.e. if I give it server1, i.e.
http://localhost:1234 works, but
http://server1:1234 fails
The code is...
HttpListener listener = new HttpListener();
String prefix = #"http://server1:1234";
listener.Prefixes.Add(prefix);
listener.Start();
The failure occurs on listener.Start() with an exception of Access is denied..
I had the same issue once and i solved it by adding an URL reservation for the specified URL namespace for a user/users to the Network Shell (netsh). Here's an example on how to reserv an URL for every user, run this in the command prompt as an administrator:
netsh http add urlacl url=http://server1:1234/ user=Everyone
Here's an example on how reserv an URL for one user, run this in the command prompt as an administrator:
netsh http add urlacl url=http://server1:1234/ user=Steve
In this way you don't need to run the application as an administrator
Is your app running with elevated privilege?
Normal accounts cannot hook the Http pipeline without first making a reservation.
http://msdn.microsoft.com/en-us/library/Aa364673
It can be done programatically at install time. Let me know if this is of interest, and I'll dig out some code.
EDIT:
Actually, as I can't identify where the code came from at the moment, I can't post it here. There's a codeplex project for doing this kind of thing which is definitely worth picking apart.
/EDIT
Here's a way make the reservation on the command line:
http://www.casadehambone.com/HowToAddAURLACLAndAvoidAddressAccessDeniedExceptionInWindowsVista.aspx

Can't resolve DNS

I'm trying to consume a webmethod but it seems that my application can't resolve DNS. The problem surfaces when I configure my application with an url (e.g.: http://mywebservice.com/webservice/methods.asmx), but it does not when I access the same webmethod through the server's IP address.
The thing is that I need to access the webservice using the url and not the IP address due to an existing DHCP server policy.
Can anyone help me ?
Thanks in advance.
UPDATE: Checking out what moocha asked me to do, I found out that:
D:>nslookup server.com
Server: dnsserver.mycompany.com
Address: XXX.YYY.XXX.YYY
*** dnsserver.mycompany.com can't find server.com: Non-existent domain
Have you tried confirming the same DNS query works via nslookup from the same system on which your application runs?
I.e.,
C:\>nslookup
Default Server: whatever.dns.example.org
Address: 111.222.333.111
> set q=a
> mywebservice.com
Server: whatever.dns.example.org
Address: 111.222.333.111
Non-authoritative answer:
Name: mywebservice.com
Address: 208.254.26.139
Digging a little bit more I found that there is a proxy in between my PC and the server. Therefore, I'm oblied to log with a valid user in order to access the internet. The problem was that my application's server (where the IIS is running) was configured to run using anonymous access. All I had to do was to configure in the IIS an user that has permission to access the internet (through the proxy). Finally the problem is solved.
There was another option, I could use the logged user's credentials to grant access through the proxy; but that required that all users use the same log in information for the application and the intranet.

Categories

Resources