I want to create a self-signed root certificate authority, such that the certificates signed by this CA are trusted by the OS which trusts the CA.
After following a couple different guides, I managed to produce certificate authority that works in a Linux machine. However, the same generation process fails when applied to my Mac.
Below is a script (generate.sh
) to generate the CA and the server certificate:
#!/bin/sh
mkdir -p ./out
# CA configuration
openssl genrsa -out ./out/CA.key 2048
openssl req -x509 \
-new \
-nodes \
-key ./out/CA.key \
-sha256 -days 365 \
-subj "/C=NA/ST=NA/L=NA/O=org/OU=orgunit/CN=special-name"\
-out ./out/CA.pem
# server certificate
openssl genrsa -out ./out/server.key 2048
openssl req -new -key ./out/server.key \
-subj "/C=NA/ST=NA/L=NA/O=org/OU=orgunit/CN=special-name"\
-out ./out/server.csr
echo "extendedKeyUsage = serverAuth
subjectAltName=DNS:localhost" | openssl x509 -req -in ./out/server.csr \
-CA ./out/CA.pem \
-CAkey ./out/CA.key \
-CAcreateserial \
-out ./out/server.crt \
-days 825 \
-sha256 \
-extfile /dev/stdin > /dev/null
I've spent some time trying to figure out what is happening, but every solution online seems to be different.
Here is the process to generate and test the certificate:
./generate.sh
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ./out/CA.pem
docker build -t cert-test .
docker run -d -p 443:443 --name cert-test cert-test
curl https://localhost:443
The server certificates are loaded to a container made by this Dockerfile:
FROM nginx:latest
COPY ./nginx/nginx.conf /etc/nginx/conf.d/
COPY ./out/server.crt /etc/ssl/certs/
COPY ./out/server.key /etc/ssl/private
EXPOSE 443
CMD ["nginx", "-g", "daemon off;"]
with the accompanying ./nginx/nginx.conf
:
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /etc/ssl/certs/server.crt;
ssl_certificate_key /etc/ssl/private/server.key;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
root /usr/share/nginx/html;
index index.html index.html;
}
}
All this is available in certificate-mess.
Expected result: curl https://localhost:443
returns the nginx welcome page.
Actual result: curl https://localhost:443
does not return the nginx welcome page, instead states the website is insecure/invalid:
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
Why does this process fail for ios/macos, and how do I resolve it? I've double-checked Requirements for trusted certificates in iOS 13 and macOS 10.15, Thanks in advance.
CN=special-name
withCN=CA
) for the CA it works for me on MacOS when testing the generated server certificate withopenssl s_server
and usingcurl --cacert ...
as client.