[Https] dotnet dev-certs --trust support on Linux · Issue #32842 · dotnet/aspnetcore (original) (raw)

Related Epic #41990

The different flavors of Linux are the only place where --trust is not supported for dotnet dev-certs. We had an issue on openssl blocking this in the past that prevented dotnet-to-dotnet trust. Now that the issue has been solved and that distros are updating their openssl versions to newer versions without the original issue that was blocking us, we can consider adding support for trust across supported distros.

Our support Matrix looks as follows (taken from here):

OS Version
Alpine Linux 3.13+
CentOS 7+
Debian 10+
Fedora 32+
OpenSUSE 15+
Red Hat Enterprise Linux 7+
SUSE Enterprise Linux (SLES)] 12 SP2+
Ubuntu 16.04, 18.04, 20.04+

Open SSL status across versions

OS Version Open SSL Version on latest OS version
Alpine Linux 3.13+ 1.1.1k (on 3.13)
CentOS 7+ 1.1.1d (on 8.3)
Debian 10+ 1.1.1k (on 11)
Fedora 32+ 1.1.1k (on 34)
OpenSUSE 15+ 1.1.1d (on 15.2)
Red Hat Enterprise Linux 7+ TBD
SUSE Enterprise Linux (SLES)] 12 SP2+ 1.1.1d (on latest, based on assumptions from OpenSUSE)
Ubuntu 16.04, 18.04, 20.04+ 1.1.1k (on 21.04)

For the distros that don't meet the openssl version requirement, a new openssl version can be installed in most cases (at the users risk/judgement), either from an existing package available for the distro or downloading openssl and compiling it from source. I validated this across a few distros as follows:

Each distro that we want to support should be considered to have the cost of supporting and maintaining entire new OS, since we have to support specific environment variations and test functionality on each of them.

For each distro we need to support:

In addition to that, we need to make sure that all the tools and libraries we need are present on the OS, have the right version and are available on the path:

For each distro we need come up with a list of instructions to setup the machine and create a VM image we can leverage for regression testing. We need to capture the instructions for doing the following:

Prepare the VM to be shared with the team (we should be able to do so as described here

Once all the software is installed on the given distro, --trust, --check, --clean must work on 3 areas:

Operation/Component Firefox Edge/Chrome dotnet runtime
--check look for a policy and a certificate in the right folder or use certutil against the profile database to ensure the right cert is trusted use certutil against the profile database to ensure the right cert is trusted check for a certificate file with the name aspnetcore-localhost-https-{sha256-certificate-hash}.pem in the openssl certificates folder
--trust either install an enterprise policy on the user profile or use certutil to modify the trust database for the profile db use certutil to modify the trust database export the certificate to a file in PEM format; copy the certificate to the openssl certificates directory with aspnetcore-localhost-https-{sha256-certificate-hash}.pem
--clean remove the enterprise policy and all certificates starting with aspnetcore-localhost-https- or use certutil to remove all certificates that match aspnetcore-localhost-https- from the profile database use certutil to remove all certificates that match aspnetcore-localhost-https- from the database remove all certificates that match aspnetcore-localhost-https- from the openssl certificates directory.

There are slight variations that we need to account for across distros. Ideally we don't want those things to show up in our code, since it will create a hard to maintain mess. To that matter, we will create a manifest for each distro/version with all the important details about the distro to drive all the operations and embed them in the dev-certs assembly.

When a command is run on Linux, we will try and recover the manifest by convention (<<distro>>.<<version>>.manifest.json) and will use the details there to drive the action.

The contents of the manifest are yet TBD, in its most simple form they can contain scripts that we can put on a temp file, chmod +x the file, run from the process and get a result back to determine the result of the operation. An alternative is to include details on per distro path locations and so on and have dotnet use that to drive the operation.

For example dotnet dev-certs https --trust --check can read the openssl directory location, get the current trusted certificate and check that there is a file with the right name at the openssl certs directory, read the cert and ensure it matches the one in the store.

Onboarding a new distro/version involves the following steps:

For reference, here are some scripts that cover many distros and that can be used as a starting point. The only one completely missing is Alpine, where the install experience just gives you a prompt and you have to run scripts to install everything else. In that case, we likely only need to figure out the work for trusting the cert by openssl since its very likely only used in container environments

CentOS (This likely works for RHEL too)

Setup Firefox

echo 'pref("general.config.filename", "firefox.cfg"); pref("general.config.obscure_value", 0);' > ./autoconfig.js

echo '//Enable policies.json lockPref("browser.policies.perUserDir", false);' > firefox.cfg

echo "{ "policies": { "Certificates": { "Install": [ "aspnetcore-localhost-https.crt" ] } } }" > policies.json

dotnet dev-certs https -ep localhost.crt --format PEM

sudo mv autoconfig.js /usr/lib64/firefox/ sudo mv firefox.cfg /usr/lib64/firefox/ sudo mv policies.json /usr/lib64/firefox/distribution/ mkdir -p ~/.mozilla/certificates cp localhost.crt ~/.mozilla/certificates/aspnetcore-localhost-https.crt

Trust Edge/Chrome

certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n localhost -i ./localhost.crt certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n localhost -i ./localhost.crt

Trust dotnet-to-dotnet (.pem extension is important here)

sudo cp localhost.crt /etc/pki/tls/certs/aspnetcore-localhost-https.pem sudo update-ca-trust

Cleanup

rm localhost.crt

Fedora

# Setup Firefox
echo 'pref("general.config.filename", "firefox.cfg");
pref("general.config.obscure_value", 0);' > ./autoconfig.js

echo '//Enable policies.json
lockPref("browser.policies.perUserDir", false);' > firefox.cfg

echo "{
    \"policies\": {
        \"Certificates\": {
            \"Install\": [
                \"aspnetcore-localhost-https.crt\"
            ]
        }
    }
}" > policies.json

dotnet dev-certs https -ep localhost.crt --format PEM

sudo mv autoconfig.js /usr/lib64/firefox/
sudo mv firefox.cfg /usr/lib64/firefox/
sudo mv policies.json /usr/lib64/firefox/distribution/
mkdir -p ~/.mozilla/certificates
cp localhost.crt ~/.mozilla/certificates/aspnetcore-localhost-https.crt

# Trust Edge/Chrome
certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n localhost -i ./localhost.crt
certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n localhost -i ./localhost.crt

# Trust dotnet-to-dotnet (.pem extension is important here)
sudo cp localhost.crt /etc/pki/tls/certs/aspnetcore-localhost-https.pem
sudo update-ca-trust

# Cleanup
rm localhost.crt

OpenSUSE (This likely works for SLES too)

# Setup Firefox
echo 'pref("general.config.filename", "firefox.cfg");
pref("general.config.obscure_value", 0);' > ./autoconfig.js

echo '//Enable policies.json
lockPref("browser.policies.perUserDir", false);' > firefox.cfg

echo "{
    \"policies\": {
        \"Certificates\": {
            \"Install\": [
                \"aspnetcore-localhost-https.crt\"
            ]
        }
    }
}" > policies.json

dotnet dev-certs https -ep localhost.crt --format PEM

sudo mv autoconfig.js /usr/lib64/firefox/
sudo mv firefox.cfg /usr/lib64/firefox/
sudo mv policies.json /usr/lib64/firefox/distribution/
mkdir -p ~/.mozilla/certificates
cp localhost.crt ~/.mozilla/certificates/aspnetcore-localhost-https.crt

# Trust Edge/Chrome
certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n localhost -i ./localhost.crt
certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n localhost -i ./localhost.crt

# Trust dotnet-to-dotnet (.pem extension is important here)
sudo cp localhost.crt /var/lib/ca-certificates/openssl/aspnetcore-localhost-https.pem

# Cleanup
rm localhost.crt

Ubuntu (This likely works for Debian too)

# Setup Firefox
echo "{
    \"policies\": {
        \"Certificates\": {
            \"Install\": [
                \"aspnetcore-localhost-https.crt\"
            ]
        }
    }
}" > policies.json

dotnet dev-certs https -ep localhost.crt --format PEM

sudo mv policies.json /usr/lib/firefox/distribution/
mkdir -p ~/.mozilla/certificates
cp localhost.crt ~/.mozilla/certificates/aspnetcore-localhost-https.crt

# Trust Edge/Chrome
certutil -d sql:$HOME/.pki/nssdb -A -t "P,," -n localhost -i ./localhost.crt
certutil -d sql:$HOME/.pki/nssdb -A -t "C,," -n localhost -i ./localhost.crt

# Trust dotnet-to-dotnet (.pem extension is important here)
sudo cp localhost.crt /usr/lib/ssl/certs/aspnetcore-https-localhost.pem

# Cleanup
rm localhost.crt