Are "normal" environment variables more secure than IIS environment variables? - asp.net-core

I have an ASP.Net Core website running on IIS. I need to store some passwords that the site needs to access in production. No paid password storing systems are available to me. I chose to store my passwords in environment variables. So on the production machine I have:
a service account my_prod_service_account
an application pool MyProdAppPool that runs under my_prod_service_account
a website MyDotNetCoreSite that runs in the MyProdAppPool
Approach 1: Normal Environment Variables
I login to the production machine as my_prod_service_account and set environment variables for this user in Powershell:
[Environment]::SetEnvironmentVariable("Pwd1", "MyPrecioussss1", "User");
[Environment]::SetEnvironmentVariable("Pwd2", "MyPrecioussss2", "User");
After this MyDotNetCoreSite can read these environment variables.
Approach 2: system.webServer\aspNetCore Environment Variables
Something similar can be achieved with %WINDIR%\system32\inetsrv\config\applicationHost.config (IIS configuration file) on the production machine. It can be edited manually or through UI, but in the end it looks like this:
<configuration>
<location path="MyDotNetCoreSite">
<system.webServer>
<aspNetCore>
<environmentVariables>
<environmentVariable name="Pwd1" value="MyPrecioussss1" />
<environmentVariable name="Pwd2" value="MyPrecioussss2" />
</environmentVariables>
</aspNetCore>
</system.webServer>
</location>
</configuration>
After iisreset MyDotNetCoreSite can read these values as environment variables.
Question
I want to change my password storage method from Approach 1 to Approach 2. The former sets environment variables per user, the latter per site (which I think is neater). But I can't find enough documentation to judge whether Approach 2 has the same level of security as Approach 1. Setting a "normal" environment variable stores it in the registry at HKEY_Users\my_prod_service_account SID\Environment\Pwd1. Accessing the registry usually requires elevated permissions, and if someone breaks into it, we will have bigger problems than hackers knowing Pwd1. Is applicationHost.config as secure as the registry? Can I confidently store a password in it?

I can just give some head-scratch questions/concerns:
I am curious, have you done a set in a command line and checked if any unwanted passwords are listed in the output in plaintext?
Also, if you store all passwords in one file like in Approach#2, this makes a nice honeypot. I do not know how well the encryption works, Lex Li mentioned.

Related

Service Fabric ApplicationManifest parameterized certificaterefs?

I have a solution with multiple SF services. Some of them use HTTPS endpoints, so I have these specs (details hidden or changed)
We are several developers, and we are using self-signed certificates for local deployment.
<Parameters>
<Parameter Name="Api_SslCertHash" DefaultValue="<my-thumbprint-here!>" />
</Parameters>
and
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="SomeAppPkg" ServiceManifestVersion="1.0.0" />
<Policies>
<EndpointBindingPolicy EndpointRef="ServiceEndpointHttps" CertificateRef="mycert" />
</Policies>
</ServiceManifestImport>
and then
<Certificates>
<EndpointCertificate X509FindValue="[Api_SslCertHash]" Name="mycert" />
</Certificates>
Now the problem is that we have this file checked in to Git, and since everyone has their own self-signed cert (Not: I don't know if this has to be, maybe we can share certs, by the question remains anyway) the thumbprint is different per developer.
My question is: Is it possible to have the thumbprint in an environment-variable, or get it from another source instead of changing it in the ApplicationManifest. I realise that it could be hard in a cluster environment, but maybe when deploying locally?
I have a similar requirement for ServiceManifest, where I would like to have different port numbers. I know I can override it in Local.1Node.xml but it would be nice to be able to pick it up externally.
I don't see why you cant use a variable like you are doing in your last example, but that doesn't solve your multiple developer problem.
The correct way to handle this is to generate a certificate, check it into source control and make everyone else use the same certificate. In fact, if you set up a secure cluster in production, anyone who wants to be able to view the Explorer will need the same certificate installed on their machine in order to authenticate.

Missing configuration for the issuer of security tokens error

I inherited an existing project without its development environment. I have UAT code and a backup of the Production database. I can run up the site locally via Visual Studio but have hit an authentication problem trying to setup a fresh standalone DEV server on AWS (single server, no load balancer). The doco indicates the Prod server is a dual server setup with a load balancer.
The front end site pages do display, although some search is not working. On trying to log into the backend pages, Chrome returns "The xxx page isn't working. xxx redirected you too many times." Using developer tools, I can see the page redirects back and forth between SWT?realm=... and sitefinity?wrap_defalted=true&wrap_access_token... On the second redirect response header there is "X-Authentication-Error:Missing configuration for the issuer of security tokens 'https://xxx/Sitefinity/Authenticate/SWT' "
I tried different values in the web.config lines:
<federatedAuthentication>
<wsFederation passiveRedirectEnabled="true" issuer="http://localhost" realm="http://localhost" requireHttps="true"/>
<cookieHandler requireSsl="false"/>
</federatedAuthentication>
but that actually made things worse so I have reverted.
I checked all the settings mentioned in http://docs.sitefinity.com/administration-switch-to-claims-based-authentication and they seem to be set correctly. I don't really know what else I can check to get this working.
I found http://docs.sitefinity.com/administration-configure-security, but it does not seem like these settings are set (I don't have access to Prod server so can't confirm if it is actually setup with load balancing). I am currently using a 30 day trial license so am not sure if this is contributing to the problem. The official license is in the process of being transferred by the client. The domain name associated with the official license would be different to the domain my new server is currently running on.
I am also running version 8 code on a version 9 install of Sitefinity. I wanted to get it working before I tried to upgrade the code. I think there was also an assembly load to manifest mismatch when I tried upgrading my local version.
Found the solution: Don't mess with the SecurityConfig.config file.
<securityTokenIssuers>
<add key="B886AA7BFB5515BA63F577A44BBEB5C7AE674035514D128BC397346B11F4C97A" encoding="Hexadecimal" membershipProvider="Default" realm="http://localhost" />
</securityTokenIssuers>
<relyingParties>
<add key="B886AA7BFB5515BA63F577A44BBEB5C7AE674035514D128BC397346B11F4C97A" encoding="Hexadecimal" realm="http://localhost" />
</relyingParties>
Even though it is running on a server, the above lines should still point to localhost. It seems like these only need to be edited if you have a multi-server setup with an entirely separate STS.
I initially changed it to match the new domain name, but after some experimentation around adding localhost and HTTP variations, it seems like it works best with just localhost.
Even when I changed the web.config entry above to use the new domain as the issuer instead of localhost and the SecureConfig.config to specify only the new domain as the realms, it didn't seem to work. I guess the authentication must try to hit localhost specifically.

Azure Cache not persisting Session State across VIP swaps?

As a follow-up to this post: Enabling co-located Session Caching in an Azure Cloud Service - I'm trying to store session state in Azure Cache to persist sessions between VIP swaps. Quoted from the answer:
To fix this problem, I'd like you to try the new Cache Service
(Preview). In this way you create dedicate cache for your subscription
so that you can use them across cloud service deployments, virtual
machines and websites.
I've set up an Azure Cache (Preview) instance, used its endpoint and primary access key in my web.config, and deployed to my Azure Cloud Service Staging slot.
I then logged in using Forms auth, and redeployed to the same slot. My credentials were persisted! This was great to see.
But then I VIP swapped to Production, logged in the same way to the production instance, redeployed to Staging, VIP swapped again, and then refreshed, expecting to remain logged in, but it didn't work - my session was lost on both production and staging.
I've followed the instructions found here:
http://www.windowsazure.com/en-us/manage/services/cache/net/how-to-in-role-cache/#getting-started-cache-role-instance
What could be causing this? No exceptions are thrown - my access key works (tested by giving it a bogus one and getting an exception)... I'm not sure what's going on. Config sections in web.config:
<sessionState mode="Custom" customProvider="AFCacheSessionStateProvider" xdt:Transform="Insert">
<providers>
<add name="AFCacheSessionStateProvider" type="Microsoft.Web.DistributedCache.DistributedCacheSessionStateStoreProvider, Microsoft.Web.DistributedCache" cacheName="default" dataCacheClientName="default" applicationName="AFCacheSessionState"/>
</providers>
</sessionState>
And:
<dataCacheClient name="default">
<autoDiscover isEnabled="true" identifier="mysite.cache.windows.net" />
<securityProperties mode="Message" sslEnabled="false">
<messageSecurity authorizationInfo="{my key}" />
</securityProperties>
</dataCacheClient>
As for timeout policy - I have it set to never expire with eviction enabled. I'm one of a handful of users and the cache is storing cookies in 128MB of space, so I don't think it's related to expiry.
I also noticed that in the docs, there is no entry for applicationName as I have above. I tried removing it and re-testing, to no avail - my Prod session is still lost upon VIP swap.
What am I doing wrong?
Update:
From a microsoft forum post:
I was able to reproduce the issue. I am investigating.
Forms authentication is not based on session state. It relies only on client-side cookies. Cookies are encrypted and validated with keys specified in machineKey section of web.config.
Default config is:
<machineKey validationKey="AutoGenerate,IsolateApps"
decryptionKey="AutoGenerate,IsolateApps"
validation="SHA1" decryption="Auto" />
AutoGenerate means that each physical machine gets its own decryptionKey. Cookies generated by production VM will not be accepted by staging VM.
After VIP swap all cookies set by old production VM will be rejected by new production VM (ex-Staging VM), causing all users to be logged out.
You need to specify machineKey values explicitly to force Forms Auth to generate cookies that will be valid for both new and old production VMs (see How To: Configure MachineKey, Web Farm Deployment Considerations section).
Check this online tool for machineKey section generation: http://aspnetresources.com/tools/machineKey.
UPD: There is a related note in Manage Deployments in Windows Azure/Managing ASP.NET machine keys for IIS:
Windows Azure automatically manages the ASP.NET machineKey for
services deployed using IIS. If you routinely use the VIP Swap
deployment strategy, you should manually configure the ASP.NET machine
keys.

RavenDB 2 returns 401 when trying to create database

This is a fresh install of Raven #2230, running on IIS8/Win8. When studio starts it offers to create new database, then browser pops up credentials window (401).
Web.config has add key="Raven/AnonymousAccess" value="All"/ set. Also tried add key="Raven/AnonymousUserAccessMode" value="All"/ as per documentation.
Anonymous Authentication on site is enabled, so is Windows Authentication.
Added Raven.Bundles.Authorization.dll to plugins folder (not sure if needed, but didn't make any difference).
Am I missing something ?
RavenDB as of today, is on version 2750 (stable). Upgrade and this issue should be fixed.
The way to do this is to set the AnonymousAccess setting in web.config to Admin:
<add key="Raven/AnonymousAccess" value="Admin"/>
You should change this back to All once you have created your database.

Failure to obtain lock using Lucene and Sitecore

I'm trying to implement Lucene search in Sitecore. Using the default Sitecore.Search implementation, I should be able to get a reference to the index defined in my config file and call index.Rebuild.
I tried using the RebuildDatabaseCrawlers script from the AdvancedDatabaseCrawler, but everytime I call Rebuild, it fails.
The error I receive is:
Lock obtain timed out: SimpleFSLock#C:\sites\MySite\Data\indexes\__mysite\write.lock
I've tried changing permissions (including giving Everyone full perms), restarting databases and IIS, all to no avail. I've also tried stripping my search configuration section down to the bare minimum, with the same result.
Unfortunately I don't have any visibility into what the index.Rebuild() method does, as its inside the Sitecore.Search assembly.
The issue ended up being related to configuration.
Specifically, when trying to remove all superfluous Sitecore.Data.Indexing references from the configuration files after determining that i didn't need both Sitecore.Search and Sitecore.Data.Indexing, I had commented out the following line:
<configuration>
<appSettings>
<add key="Lucene.Net.FSDirectory.class" value="Sitecore.Data.Indexing.FSDirectory, Sitecore.Kernel"/>
</appSettings>
</configuration>
That needs to be there.
Try to adjust the permissions for c:\Temp for your app pool user, e.g. Network Service
You can also try to do the same for: c:\windows\microsoft.net\framework\{version}\Temporary ASP.NET Files