If I use OpenSSL to create an X509 certificate that gets signed with a CA certificate and includes an X509v3 SAN (Subject Alternative Name) extension, the generated certificate contains the SAN extension twice, whereas if the certificate is self-signed the SAN extension appears only once (which I would consider correct).
Steps to reproduce:
$ openssl version
OpenSSL 1.0.2n 7 Dec 2017
$ openssl genrsa -out example.key 2048
$ openssl req -new -key example.key -out example.csr
# ... confirm certificate defaults only enter "example.com" as Common Name
$ echo subjectAltName=DNS:example.com,DNS:www.example.com > example.cnf
$ openssl x509 -req -sha256 -days 7300 -text -extfile example.cnf \
-in example.csr -signkey example.key \
-CA ../ca.crt -CAkey ../ca.key -set_serial 01 \
-out example.crt
Afterwards if I inpect the certificate the section "X509v3 Subject Alternative Name" is printed twice:
$ openssl x509 -in example.crt -text -noout
...
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com
X509v3 Subject Alternative Name:
DNS:example.com, DNS:www.example.com
...
This is not the case if no CA is used and the certificate gets self-signed via:
$ openssl x509 -req -sha256 -days 7300 -text -extfile example.cnf \
-in example.csr -signkey example.key \
-out example.crt
I can verify this behavior with OpenSSL 1.0.2n as well as OpenSSL 0.9.8zh.
Is this an OpenSSL bug or is there any valid explanation for this?
See answer of #dave_thompson_085:
Using both -signkey and -CAkey does not make any sense and triggers this strange side-effect.
Related
First I do:
$ openssl genrsa -out root.key 2048
Then I do:
$ openssl req -new -key root.key -subj "C=../..."
Then I create a signed certificate in the following way:
$ openssl x509 -req -in root.csr -extfile /etc/pki/tls/openssl.cnf -extensions v3_ca -signkey root.key
If I do the last command twice, I see a different signature in the certificate. Why is that?
I use self-signed CA cert to sign other certificates. For some certs I need to specify subject alternative names. I can specify them during request generation (openssl req ...) and I see them in .csr file. Then I sign it with CA cert using
openssl x509 -req -extensions x509v3_config -days 365 -in ${name}.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out ${name}.crt
and next sections in openssl.cnf file:
[ x509 ]
x509_extensions = x509v3_config
[ x509v3_config ]
copy_extensions = copy
but I see no SAN in .crt file.
I know about solutions with openssl ca ... command but I have no valid [ca] section and I don't want to copy/paste it without deep understanding what it does. So I hope that exists another solution with openssl x509 ... command.
The copy_extensions directive is only understood by the openssl ca command. There is no way to copy extensions from a CSR to the certificate with the openssl x509 command.
Instead, you should specify the exact extensions you want as part of the openssl x509 command, using the same directives you used for openssl req.
Sorry, I can't comment (yet).
In addition to #frasertweedale :
I generated my server-certificate with a config file
openssl req -new -out certificate.csr -key certificate_private_key.pem -sha256 -days 1825 -config certificate.conf
I then did
Instead, you should specify the exact extensions you want as part of the OpenSSL x509 command, using the same directives you used for OpenSSL req.
with the following command (I used the same .conf-file again):
openssl x509 -req -in certificate.csr -CA ca-root-public-certificate.pem -CAkey ca-key.pem -CAcreateserial -out certificate_public.pem -sha256 -days 1825 -extfile certificate.conf -extensions v3_req
There is a good documentation here : Certificates
You will need to compose an openssl conf file while creating a x509 cert request like this:
create CSR
openssl req -new -key server.key -out server.csr -config csr.conf
sign CERT
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 10000 -extensions v3_ext -extfile csr.conf
How can disable the hostnameverfifier in gRPC to avoid exception below?
java.security.cert.CertificateException: No subject alternative names present
The recommended way to use test certificates where the hostname doesn't match is to call ManagedChannelBuilder.overrideAuthority("test-hostname"). This is functionally similar to adding test-hostname to /etc/hosts. This allows you to choose different IPs/DNS names with forAddress()/forTarget() without disabling security.
But it still seems like your certificate is a bit broken. Subject Alternative Name is required; using the certificate's Subject had been deprecated for a decades.
You may also be interested in using gRPC's test certificates. We provide TlsTesting to load them.
server = ServerBuilder.forPort(0)
// Use test cert on server-side
.useTransportSecurity(
TlsTesting.loadCert("server1.pem"),
TlsTesting.loadCert("server1.key"))
// ...
.build().start();
channel = NettyChannelBuilder
.forAddress("localhost", server.getPort())
// Trust test CA on client-side
.sslContext(
GrpcSslContexts.forClient()
.trustManager(TlsTesting.loadCert("ca.pem"))
.build())
// Change hostname to match certificate
.overrideAuthority("foo.test.google.fr")
.build();
Just to elaborate on #Eric Anderson answer. In the gRPC's test certificates he points to there are 2 types *.cnf files used to generate the client and server certs
1.Generate client cert: openssl.cnf
2.Generate server cert: server1-openssl.cnf
at the very bottom of both files you will find the hostnames where you need to add the matching entries for the client and server
for example if you are local testing for client and server resolving on "localhost" then you would need for both openssl.cnf and server1-openssl.cnf to have
[alt_names]
DNS.1 = localhost
after this you would need to regenerate the certificates
here is a simple script based on the grpc-java info here
#!/bin/bash
SERVER_CN=localhost
CLIENT_CN=localhost # Used when doing mutual TLS
TLS_KEY_PSSWD=somepsswd
echo "When prompted for cert information, everything is default except the common name which is set to localhost"
echo Generate CA key:
openssl genrsa -passout pass:TLS_KEY_PSSWD -des3 -out ca.key 4096
echo Generate CA:
openssl req -passin pass:TLS_KEY_PSSWD -x509 -new -nodes -key ca.key -out ca.pem -config conf/ca-openssl.cnf -days 3650 -extensions v3_req -subj "/CN=${SERVER_CN}"
echo "Now that we’re a CA on all our devices, we can sign certificates for any new dev sites that need HTTPS"
echo Generate client key:
openssl genrsa -out client.key.rsa 1024
openssl pkcs8 -topk8 -in client.key.rsa -out client.key -nocrypt
rm client.key.rsa
echo Generate client signing request:
openssl req -passin pass:TLS_KEY_PSSWD -new -key client.key -out client.csr -subj "/CN=${CLIENT_CN}"
echo Generate client cert:
openssl ca -passin pass:TLS_KEY_PSSWD -in client.csr -out client.pem -keyfile ca.key -cert ca.pem -verbose -config conf/openssl.cnf -days 3650 -updatedb
openssl x509 -in client.pem -out client.pem -outform PEM
echo Generate server key:
openssl genrsa -passout pass:TLS_KEY_PSSWD -out server1.key.rsa 1024
openssl pkcs8 -topk8 -in server1.key.rsa -out server1.key -nocrypt
rm server1.key.rsa
echo Generate server signing request:
openssl req -passin pass:TLS_KEY_PSSWD -new -key server1.key -out server1.csr -config conf/server1-openssl.cnf -subj "/CN=${CLIENT_CN}"
echo Generate server cert:
openssl ca -passin pass:TLS_KEY_PSSWD -in server1.csr -out server1.pem -keyfile ca.key -cert ca.pem -verbose -config conf/server1-openssl.cnf -days 3650 -extensions v3_req -updatedb
openssl x509 -in server1.pem -out server1.pem -outform PEM
I am trying to create a docker swarm that has certificates that expire after 1 year or more. The documentation states the syntax and I tried this docker swarm init --cert-expiry 8760h0m0s
However under cat /var/lib/docker/swarm/certificates/swarm-node.crt when I decipher the certificate the validity is still 3 months. How do I make sure that validity is what I have set it to?
You can generate certificates manually using the OpenSSL tool and configure Docker daemon to use these certificates.
Generate Server Certificates
Generate CA private and public keys:
openssl genrsa -aes256 -out ca-key.pem 4096
openssl req -new -x509 -days 1000 -key ca-key.pem -sha256 -out ca.pem
Create a server key and certificate signing request (CSR):
openssl genrsa -out server-key.pem 4096
openssl req -subj "/CN=my.company.com" -sha256 -new -key server-key.pem -out server.csr
Sign the public key with CA:
echo subjectAltName = DNS:my.company.com,IP:127.0.0.1 >> extfile.cnf
echo extendedKeyUsage = serverAuth >> extfile.cnf
Generate the key:
openssl x509 -req -days 1000 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf
Generate Client Certificates
Create a client key and certificate signing request:
openssl genrsa -out key.pem 4096
openssl req -subj '/CN=client' -new -key key.pem -out client.csr
Create an extensions config file:
echo extendedKeyUsage = clientAuth >> extfile.cnf
Sign the private key:
openssl x509 -req -days 1000 -sha256 -in client.csr -CA ../server/ca.pem -CAkey ../server/ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf
Export cert.pem into PFX format to be added into Trusted Root Certification Authorities
openssl pkcs12 -export -in cert.pem -inkey key.pem -out cert.pfx
Configure Docker daemon with /etc/docker/daemon.json
{
"debug": false,
"tls": true,
"tlsverify": true,
"tlscacert": "/etc/docker/certificates/server/ca.pem",
"tlscert": "/etc/docker/certificates/server/server-cert.pem",
"tlskey": "/etc/docker/certificates/server/server-key.pem",
"hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]
}
Start Docker Service
systemctl start docker
Have a look at this article Building Jenkins Pipelines – Setting Up Docker Swarm. There's a step-by-step guide there.
Run the following commands on any of the management nodes:
docker swarm update --cert-expiry 8760h0m0s
docker swarm ca --rotate | openssl x509 -text -noout
The first one will set certificate expiry date.
The last one will actually apply changes and rotate certificates on all swarm nodes automatically. If not interested in decoding cert text output, the openssl part can be omitted.
A certificate is generated using the following openssl command :
openssl req -new -x509 -keyout server.key.pem -out server.crt.pem -config /etc/ssl/openssl.cnf -extensions cust_const
The corresponding CSR is generated using the command:
openssl x509 -x509toreq -in server.crt.pem -signkey server.key.pem -out server.csr -extensions cust_const
The conf file (openssl.cnf) has the below mentioned entry.
[ cust_const ]
basicConstraints = CA:FALSE
The problem is that the generated CSR doesn't include basicConstraints extension.
How can basicConstraints be included into the CSR when we already have a certificate with basicConstraints in it?
when you want to create a CSR to be signed by other CA he will "make" you CA as well ( e.g. root will sign intermediate as CA with depthLen=1 , where intermediate will sign endPoint as CA=FALSE ... )
first you need to understand what do you want to do (root / intermediate / Endpoint)
if you are root create extensions file (look for openssl default for help...)
below short list command to help you get started :
create root ca certificate
openssl genrsa -des3 -out rootca.key 2048
openssl rsa -in rootca.key -out rootca.key.insecure
openssl req -key rootca.key.insecure -new -x509 -days 3650 -extensions v3_ca -out rootca.crt
openssl x509 -text -in rootca.crt
NOTE:
it uses the default extensions file: /usr/lib/ssl/openssl.cnf (or /etc/ssl/openssl.cnf)
create intermediate certificate
openssl genrsa -des3 -out intermediate.key 2048
openssl rsa -in intermediate.key -out intermediate.key.insecure
openssl req -new -key intermediate.key.insecure -out intermediate.csr
NOTE: you might need these commands before the next command 'openssl ca'.
mkdir demoCA
touch demoCA/index.txt
echo 1122334455667788 > demoCA/serial
openssl ca -extensions v3_ca -days 3650 -outdir . -batch -cert rootca.crt -keyfile rootca.key.insecure -in intermediate.csr -out intermediate.crt
NOTE: after run 'openssl ca' you can remove the demoCA folder
rm -rf demoCA
openssl x509 -text -in intermediate.crt
openssl verify -CAfile rootca.crt intermediate.crt
create server/client certificate
openssl genrsa -des3 -out server.key 2048
openssl rsa -in server.key -out server.key.insecure
openssl req -new -key server.key.insecure -out server.csr
openssl x509 -req -days 3650 -CAcreateserial -CA intermediate.crt -CAkey intermediate.key.insecure -in server.csr -out server.crt
openssl x509 -text -in server.crt