Distributing SSL Certificates to All Browsers in an Active Directory Environment
I've generated a single self-signed SSL certificate (that expires in 5000 years). The purpose of the cert is to simply encrypt the https traffic of a trusted deno application that is accessed by a variety of web browsers on multiple corporate intranet sites.
In a comment, of my prior question, someone advised me that it is possible to distribute my self-signed public SSL key to all computers within an Active Directory environment using Group Policy on the domain controller.
My goal, is to prevent users from having to manually accept this self-sign certificate.
This application's security is not the top priority. The top priority is the automatic acceptance of the self-signed certificate. So that even if a new user is using Chrome or Firefox to access this application for the first time, they will not have to manually accept the certificate to see a page within the App.
If you're wondering why I'm not just using http (instead of https), it is only because there are features in the web standards that are not available unless your protocol is https. The Notification API is one example.
Does there exist a full tutorial for my use case?
I right-clicked here:
That brought me to the Group Policy editor, and I actually succeeded in importing my self-signed public key here:
However, this had no effect. For example, I logged into a few workstation on the LAN, and from both Firefox and Chrome I was still prompted to manually permit the certificate.
Where can I find thorough instructions for my exact use-case and goals. How can I do this in a way that both Chrome and Firefox will auto-receive the pre-authorization of the certificate I'm trying to distribute?
This is something I need to accomplish for multiple installations at multiple company intranet sites. At each install-location, I need to get active directory to distribute this cert, so that all browsers on each workstation will accept it.
Writing a comprehensive tutorial on this might not be suitable for a Q/A site, but here's some advices. Also, this is from the perspective of managing the installation for a single client within their own intranet. For e.g. SaaS installations it's better to use global FQDNs & PKI.
As a software vendor, you SHOULD NOT:
- implement own PKI and push it across your clients, as it enables you to issue certificates for arbitrary hosnames, giving you a God mode over their entire infrastucture.
- use the same self-signed certificates for multiple clients with hard-coded private keys, as they can easily be extracted and used against other clients.
- combine these mistakes, as it would give every client a God mode over all other clients.
Create your own PKI instead of trusting individual certificates
This is mainly a security consideration, but it's also easier to maintain, as you mention having multiple installations at multiple intranet sites.
From the security perspective, you don't want every application to be able to sign certificates for arbitrary hostnames. Therefore, the individual self-signed certificates should not all be trusted certificate authorities.
From the maintenance perspective, you don't want to update your policies and wait for them to propagate every time you need to add a new web application.
Although preferable, sometimes it's not possible (or wanted) to get certificates from external CAs. The intranet sites may not have globally valid FQDNs, making domain verification impossible, or their connectivity to the Internet is restricted, making it harder to maintain certificate renewals.
In this case, the recommended alternative is to create an own certificate authority for the client (do not push your PKI to multiple clients as a software vendor) and sign all the application certificates with it. This way you only need to add a single certificate to the trusted certificate authorities using GP, and every application certificate signed with it will be trusted.
If you only need a tiny certificate authority for this purpose alone, you might go with OpenSSL:
-
Generate the root key (
rootCA.key
) and the root certificate (rootCA.crt
).openssl genrsa -aes256 -out rootCA.key 4096 openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 7300 -out rootCA.crt
Keep the key safe, recommendably offline, and distribute the certificate using Group Policy.
-
Create a certificate for your application starting with a key and a certificate signing request (
.csr
).openssl genrsa -out app.example.com.key 2048 openssl req -new -sha256 \ -key app.example.com.key \ -subj "/C=US/ST=CA/O=My Application/CN=app.example.com" \ -out app.example.com.csr
-
Create an application certificate signed with your CA:
openssl x509 -req -in app.example.com.csr \ -CA rootCA.crt -CAkey rootCA.key -CAcreateserial \ -days 730 -sha256 \ -out app.example.com.crt
Use the
app.example.com.key
andapp.example.com.crt
in your application.
For heavier solutions there's Active Directory Certificate Services (AD CS), but that really needs some planning, and your skillset might not be adequate for that, yet.
Use a GPO instead of editing the Default Domain Policy
As a side note, I wouldn't edit the Default Domain Policy for this, but create a new Group Policy Object (GPO), instead. It makes a lot easier to limit the scope of the changes, e.g. making it possible to apply them to a group of test computers, first. It also makes it easier to revert changes, if something goes wrong.
Firefox has own cert store – possible to use certificates from Windows
Mozillaʼs CA Certificate Program governs inclusion of root certificates in Network Security Services (NSS), a set of open source libraries designed to support cross-platform development of security-enabled client and server applications. The NSS root certificate store is used in Mozilla products such as the Firefox browser, and is also used by other companies in a variety of products.
This means certificates added to Windows certificate store doesn't apply to Firefox, by default. For easier maintenance it might be a good idea to make Firefox use the certificate authories installed on Windows. Using own certificate store is a good idea for protecting privacy of individuals using Firefox, but not that suitable for Windows AD environments. Luckily, there's a way to disable it.
Assuming the installation directory of Firefox is C:\Program Files\Mozilla Firefox\
, you need to add two ANSI encoded configuration files:
-
C:\Program Files\Mozilla Firefox\defaults\pref\local-settings.js
havingpref("general.config.obscure_value", 0); pref("general.config.filename", "ownsettings.cfg");
This simply refers to the next file, having the actual configuration parameters.
-
C:\Program Files\Mozilla Firefox\ownsettings.cfg
having// lockPref("security.enterprise_roots.enabled", true);
It's important the actual settings starts from the second line after
//
!
These files can be distributed on the same GPO using:
Computer Configuration \ Preferences \ Windows Settings \ Files
Don't introduce root CAs into other organisations
Using self-signed certificates and distributing them through Active Directory is possible, but fairly involved. Esa Jokinen goes into more detail in his answer.
More important are the security implications; root certificates are like a master key, all certificates signed by a root certificate in AD will be trusted by all company computers. If you control a root cert at an application then you can not just create a certificate for yourapp.intranet that will be trusted, you can do that for any domain. Also for bigbank.com, or for google.com.
Essentially, getting someone to install your root certificate puts you in a position to attack all their HTTPS connections. This means you need to have proper procedures for dealing with those keys, for dealing with revocations, and for dealing with security breaches. It also means that those companies need to put an awful lot of trust in you. And I don't think they should, sorry.
Honestly, if a supplier tried to introduce their own root CA into my organization without thoroughly understanding the concerns involved and having proper plans for everything, I would veto them. I'd probably even veto them with those plans.
Depending on the organization, perhaps they already have their own internal CA; in that case you could request a certificate from them; this absolves you from most of these issues, since CA management is their responsibility, not yours. They also will only give you certificates for just your application.
Is there an alternative?
Consider this alternative approach; Obtain a proper domain name for your application, and obtain a regular SSL certificate from any CA. If cost is a concern, there are several parties offering certificates for free. I like Let's Encrypt.
For the domain name, the most obvious options are company.yourapp.com
and yourapp.company.com
. The first is easier for you to manage, since obtaining the hostname and the certificate are standardized across all deployments. The latter requires you to deal with the client's IT, but offers better integration for them.
By the way, neither of these options requires your application to be publicly accessible (although that is certainly an option). The domain could simply point to an IP address internal to the company where the application is deployed; You'd need to use email verification or DNS verification to obtain the certificates.
Another option is to have split-DNS; the domain points to a server under your control, which hosts the necessary CA verification stuff so you can obtain certificates. At the company where you application is deployed, their internal DNS points your domain to your private application server.
Replying to some comments
In my opinion, the security zealots blow this topic out of proportion. They treat every situation like online banking, when sometimes all a developer wants is encrypted data transfer.
What you want doesn't exist. You can set up "just encryption", but when you exchange the encryption keys, an attacker can simply intercept those keys and substitute their own, enabling them to read all your encrypted traffic. Certificates ensure that the browser is actually exchanging keys with the intended server, instead of with an attacker. This part is necessary for safe encryption.
In the end, the identity verification is integral to getting the encrypted communication; it is not optional.
The truth is, that a self-signed certificate can provide the same level of encryption (during data transfer) as one used by Bank of America.
Only if you can manage to correctly distribute those certificates. That's easy if it's just one local computer that needs the certificate, but it scales very poorly, and becomes very hard to do right for an arbitrary number of computers.
That's why we use Certificate Authorities; they provide a way to distribute certificates in a scalable and reasonably secure manner.
Apps served from private IP addresses shouldn't have to play by the same rules as international banks, in my opinion.
Thing is, computers don't have common sense. They don't understand that good security is necessary for visiting a bank website, but ehhh security is alright for visiting your app. They can't understand that. And they shouldn't try. What if your app starts dealing with medical records? Suddenly the "common sense" of accepting ehhh security for your app is unacceptable. The computer cannot know that distinction.
If computers have to accept sloppy security on your site, they have to accept it for other sites as well. And luckily we've gotten to the point where that is unacceptable. Accept it, and proudly give your application the same encryption banks use!
It puts a terrible unnecessary burden on the developer
No it doesn't.
Yes, securing a website with HTTPS puts some burden on the developer, such is life. Calling it either terrible or unnecessary is blowing things way out of proportion.
Honestly, just slap some Let's Encrypt certificates on your sites. It gets you the security you want (plus a bit extra), and it's way less effort than complaining about all of this. It's also less effort and safer than trying to be a CA for your clients.