Create a Self-Signed Development Certificate Trusted by Microsoft Edge

This blog explains how we can create a self-signed development certificate trusted by Microsoft Edge.

As a bit of background, I’m doing some testing in a local Hyper-V lab to stand up a sample App-V streaming server.  Be mindful that these certificates are only used for development purposes and not for a production environment.

Create a Self-Signed Development Certificate Trusted by Microsoft Edge

The first step is to create a root certificate authority (CA). This certificate will sign other certificates we issue in our environment.  Open a PowerShell session and run the following, ensuring to replace the export path at the end:

$rootCert = New-SelfSignedCertificate -Type Custom `
-KeyExportPolicy Exportable `
-KeySpec Signature `
-Subject "CN=DevRootCA" `
-KeyAlgorithm RSA `
-KeyLength 2048 `
-HashAlgorithm SHA256 `
-CertStoreLocation "Cert:\CurrentUser\My" `
-NotAfter (Get-Date).AddYears(10) `
-KeyUsage CertSign, CRLSign

# Export the root certificate to a .cer file
Export-Certificate -Cert $rootCert -FilePath C:\Alkane\DevRootCA.cer
PowerShell

We then install this certificate into the Computer Trusted Root Certificate Authority certificate store on every machine.  I did this using a computer group policy by importing the certificate C:\Alkane\DevRootCA.cer in the following location: Computer Configuration > Policies > Windows Settings > Security Settings > Public Key Policies > Trusted Root Certificate Authorities. When you generate the certificate it will place it in the Computer personal store.  You can simply open certlm.msc and manually move it into the Trusted Root Certificate Authority store before we proceed to the next step.

We can then use the root certificate to issue a certificate for our development web server. Once again, replace the DnsName and Subject to suit your own requirements:

#get root CA
$rootCert = Get-ChildItem -Path Cert:\CurrentUser\My | Where-Object { $_.Subject -eq "CN=DevRootCA" }

#issue new certificate
New-SelfSignedCertificate -Type Custom `
-DnsName "localhost", "::1", "alkaneweb", "alkaneweb.alkanesolutions.co.uk", "192.168.0.100" `
-KeyAlgorithm RSA `
-KeyLength 2048 `
-HashAlgorithm SHA256 `
-Subject "CN=alkanesolutions.co.uk" `
-Signer $rootCert `
-CertStoreLocation "Cert:\LocalMachine\My" `
-NotAfter (Get-Date).AddYears(10)
Markup

This certificate is added to our Personal certificate store (Cert:\LocalMachine\My) automatically, which has a trusted chain to the root certificate.  And by default this then appears in Internet Information Services (IIS) to bind to our site.

In IIS highlight your site.  Over to the right click Bindings.  Then Add.  Change the Type to https. And under SSL certificate, select the certificate we have just generated.

iis-bindings

Finally, I am using Windows Authentication to authenticate with my website.  This worked fine over HTTP.  But when testing over HTTPS I kept getting an authentication prompt to enter credentials.  When I entered the credentials it authenticated fine, but this manual step became annoying.  The solution was to add my site to the Intranet Zone for seamless authentication in Microsoft Edge.  Again, I did this using a group policy by navigating to Computer Configuration > Policies > Administrative Templates > Windows Components/Internet Explorer/Internet Control Panel/Security Page and adding https://alkaneweb.alkanesolutions.co.uk/ with a zone of 1 (Intranet Zone).

Java Deployment Rule Set and Self Signed Certificates

Java Deployment Rule Set and Self Signed Certificates enable us to load browser URLs with different versions of the Java Runtime.  This blog post forms part of a Java series including:

Securing Java Runtime Environment

Java Deployment Rule Set and Active Directory Certificates

Creating a Java Deployment Ruleset is actually a trivial process – it’s signing it that can be a pain in the backside.

In this post we are signing our Java Deployment Rule Set with a self signed certificate.

Java Deployment Rule Set and Self Signed Certificates

I am using jdk1.7.0_80 (yes, you need to download the Java Development Kit) to create my Java Deployment Rule Set.

Do NOT use a version of the JDK that has a major version that is greater than the JRE in your environment (for example if you are running Java 7 in your environment, use the Java 7 JDK and not the Java 8 JDK!).  If you do, it will appear to sign successfully but when you view the Java deployment rule set in the Java control panel you will see something like this (timestamp not available):

timestamp not available

instead of this:

timestamp java deployment ruleset

Create ruleset.xml

Create a file called ruleset.xml.  It MUST be called ruleset.xml since this is what Java specifically searches for inside the compiles JAR file.  The beauty of the ruleset.xml is that you can use wildcards for the URL and for the port.  With the exception.sites file you can’t do this.  Here is a basic example:

<ruleset version="1.0+">
	<rule>
		<id location="http://*.java.com" />
		<action permission="run" />
	</rule>
	<rule>
		<id location="https://*.java.com" />
		<action permission="run" />
	</rule>	
	<rule>
		<id />
		<action permission="block">
			<message>This applet has been blocked by Java.  Please contact your administrator for assistance.</message>
		</action>
	</rule>
</ruleset>
Markup

You obviously need to add your own URLs to this, and give them permission to “run”.  Interestingly if you have multiple versions of JRE installed, in the <action> tag you can provide a specific JRE version for that URL to use.  For example:

<action permission="run" version="1.6.0_31" force="true" />
Markup

When we set permission to “run”, the following types of RIAs are allowed to run without prompts:

  • Signed with a valid certificate from a trusted certificate authority
  • Signed with an expired certificate
  • Self-signed
  • Unsigned
  • Missing required JAR file manifest attributes

So Java deployment rule set is great for hiding some of these warnings.  A Rich Internet Application (RIA) is blocked if it is signed with a certificate that is blacklisted or known to be revoked, even though the action is set to “run”.

Also (untested) you should also pay close attention to the process flow of Java Rich Internet Applications.  In the above example, if a URL match cannot be found the RIA will be blocked.  However if we wanted default processing to continue (so that the Java exception.sites file gets processed, for example) we could either delete the rule with the “block” permission or replace it with:

<rule>
		<id />
		<action permission="default" />
</rule>
Visual Basic

Compile DeploymentRuleset.jar

Compile ruleset.xml into a JAR file.  This MUST be called DeploymentRuleset.jar because again, this is what Java specifically looks for.  When we compile the JAR file, we should NOT specify a full path name to the ruleset.xml because Java cannot locate it within the JAR file.  So you should first ‘CD’ to c:\Alkane and then run the following command line:

"C:\Program Files (x86)\Java\jdk1.7.0_80\bin\jar.exe" -cvf "C:\Alkane\DeploymentRuleSet.jar" "ruleset.xml"
Visual Basic

Create a Java Keystore

Here we generate a new Java keystore.  The keystore will include a key pair (a public key and associated private key), and will wrap the public key into an X.509 v3 self-signed certificate.

I would recommend keeping the alias name in lower case.  I’ve noticed that if you give it a mixed case alias name and attempt to verify it later (jarsigner.exe -verify) with the mixed case alias name, you’ll see a message:

This jar contains signed entries which are not signed by the specified alias(es)

Even though the jarsigner.exe -verify command will work when the alias name is specified in lower case, I’d recommend keeping the alias name lower case throughout for consistency.

You can grab the distinguished name (dname) parameter for your environment by running this line of PowerShell:

Get-ADDomain | Select DistinguishedName
Visual Basic
"C:\Program Files (x86)\Java\jdk1.7.0_80\bin\keytool.exe" -genkeypair -alias "selfsigned" -keystore "c:\alkane\DeploymentRulesetKeyStore.jks" -keyalg RSA -keysize 2048 -keypass "alkanecertpass" -startdate "2019/01/01 00:00:00" -validity 18262 -dname "DC=alkane,DC=solutions,DC=ad" -storepass "alkanestorepass" -storetype JKS
Visual Basic

Sign the JAR file

Now we sign the JAR file.

Because I am signing behind a proxy, I needed to specify a proxy host and port so I could timestamp my signature.  Timestamping is an important part of the process and ensures the signed JAR will remain valid indefinitely – even after the certificate expires.

"C:\Program Files (x86)\Java\jdk1.7.0_80\bin\jarsigner.exe" -keystore "c:\alkane\DeploymentRulesetKeyStore.jks" "c:\alkane\DeploymentRuleSet.jar" "selfsigned" -storepass "alkanestorepass" -storetype JKS -keypass "alkanecertpass" -tsa http://sha256timestamp.ws.symantec.com/sha256/timestamp -J-Dhttp.proxyHost=alkanehost -J-Dhttp.proxyPort=alkaneport
Visual Basic

Verify The Signature Of DeploymentRuleset.jar

We can verify the signature with the following command:

"C:\Program Files (x86)\Java\jdk1.7.0_80\bin\jarsigner.exe" -verify -verbose -certs -keystore "c:\alkane\DeploymentRulesetKeyStore.jks" -storetype JKS -storepass "alkanestorepass" "C:\Alkane\DeploymentRuleSet.jar" "selfsigned"
Visual Basic

DeploymentRuleset.jar Testing

Now that everything is signed and verified successfully, we need to test it.

Our Java is locked down by a deployment.config file and a deployment.properties file located in C:\Windows\SUN\Java\Deployment.

As such to test the DeploymentRuleSet.jar file it’s as easy as placing it into this same location.  Then launch the Java control panel applet and head over to the security tab (this may differ for later versions of Java).

There should be a blue link towards the bottom called ‘View the active Deployment Ruleset’.  Click it and you should see the contents of your ruleset.xml file and a verification that it is valid and timestamped.  Click ‘View Certificate Details’ to verify the certificate.

Of course if you were testing browser redirection specifically (assuming you have JRE 1.7.0_51 and JRE 1.6.0_31 installed locally), you could add a rule like this:

<rule>
		<id location="https://*.java.com" />
		<action permission="run" version="1.6.0_31" force="true" />
</rule>
Visual Basic

By default Java in the browser should use the latest version installed (1.7.0_51 in our case) but the rule above forces it to load any applets on java.com with version 1.6.0_31.  Once this rule is in place, head over to the Java verify page and ensure it shows the ‘older’ version of Java!