8

I know that I can dump the entire information from a PEM certificate file with this command:

openssl x509 -in certfile -noout -text

And I've already found another direct parameter to show me only the expiry date of a certificate:

openssl x509 -in certfile -noout -enddate

But is there also a shortcut to get only the alternative names? Like when a certificate can be used for example.com as well as www.example.com. In the full dump, it's here:

Certificate:
    Data:
        X509v3 extensions:
            X509v3 Subject Alternative Name: 
                DNS:www.example.com, DNS:example.com

I'd just like to save me the hassle to parse this output and get the domain names only. Is that possible? Otherwise, what would be best practices to parse this output? What can be assumed, what may change? Could I use a regexp like X509v3 Subject Alternative Name:\s*DNS:(\S+)(?:, DNS:(\S+))*?

5 Answers 5

7

Here's what I would do to make it a little more readable:

for i in $(openssl x509 -in certfile -noout -text | grep -A1 'Subject Alternative Name' | tail -n1 | tr -d ','); { echo $i | cut -f2 -d:; }

This gets you a long list format, assuming the same input as the sample above, something like this:

*.google.com
*.android.com
*.appengine.google.com
*.cloud.google.com
...

Where the raw output of the line would have been:

DNS:*.google.com, DNS:*.android.com, DNS:*.appengine.google.com, DNS:*.cloud.google.com

Of course you have to choose the right format for your list. For instance, that actual Google list is quite long and difficult to consume. If you're looking for something specific breaking the entries on to each line allows you to grep for the entry you're looking for and remove all the other information.

So this (notice the grep at the end) ...

for i in $(openssl x509 -in certfile -noout -text | grep -A1 'Subject Alternative Name' | tail -n1 | tr -d ','); { echo $i | cut -f2 -d:; } | grep google.com

Results in...

*.google.com
4

I find this method works reasonably well and is easy to remember since it's just a grep DNS:.

$ openssl x509 -noout -text -in cert.pem | grep DNS:
                DNS:localhost, DNS:someserver1.somedom.local, DNS:someserver2.somedom.com, DNS:someserver3
4

I think the best way to do this is this:

openssl x509 -in cert_file_name.crt -noout -ext subjectAltName

You can check more about the -ext flag in the official documentation of openssl here: https://www.openssl.org/docs/man1.1.1/man1/x509.html

This way you'll only get the relevant information you need with one command, no need to use other softwares like awk and sed.

2
  • 1
    Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.
    – Community Bot
    Mar 26, 2022 at 7:53
  • 1
    The x509 -ext argument was added in OpenSSL 1.1.1.
    – user310346
    Aug 1, 2022 at 7:46
2

Since there can be many entries, I simply select the next line and clean it up using awk and tr

openssl x509 -noout -text -in certfile | awk '/X509v3 Subject Alternative Name/ {getline;gsub(/ /, "", $0); print}' | tr -d "DNS:"

Here is what you get with google.com

*.google.com,*.android.com,*.appengine.google.com,*.cloud.google.com,*.google-analytics.com,*.google.ca,*.google.cl,*.google.co.in,*.google.co.jp,*.google.co.uk,*.google.com.ar,*.google.com.au,*.google.com.br,*.google.com.co,*.google.com.mx,*.google.com.tr,*.google.com.vn,*.google.de,*.google.es,*.google.fr,*.google.hu,*.google.it,*.google.nl,*.google.pl,*.google.pt,*.googleadapis.com,*.googleapis.cn,*.googlecommerce.com,*.googlevideo.com,*.gstatic.cn,*.gstatic.com,*.gvt1.com,*.gvt2.com,*.urchin.com,*.url.google.com,*.youtube-nocookie.com,*.youtube.com,*.youtubeeducation.com,*.ytimg.com,android.com,g.co,goo.gl,google-analytics.com,google.com,googlecommerce.com,urchin.com,youtu.be,youtube.com,youtubeeducation.com
2
  • 3
    I think it's worth pointing out that "tr -d "DNS:" can be dangerous, it means delete all instances of the characters D,N,S and :, anywhere, in any order, in the input. It does NOT delete "DNS:" as a complete string. For example, echo "MY DOMAIN NAME SERVER: bla" | tr -d "DNS:" would output "MY OMAI AME ERVER bla"
    – Hamid
    Feb 25, 2016 at 13:22
  • 1
    I should also point out that a better solution is to add multiple additional gsubs to do it properly. "gsub(/DNS:/,"",$0);gsub(/IPAddress:/,"",$0)" will remove both "DNS:" and "IPAddress:" (for IP type SANs).
    – Hamid
    Feb 25, 2016 at 13:24
1

In addition to using awk, you can use sed:

openssl x509 -in cert_file_name.crt -noout -text | awk '/DNS:/' | sed 's/DNS://g'

This will turn a SAN list from:

DNS:domain1.com, DNS:www.domain2.com, DNS:domain3.com, DNS:sub.domain3.com

to

domain1.com, www.domain2.com, domain3.com, sub.domain3.com
1
  • without using sed in addition : ` openssl x509 -in cert_file_name.crt -noout -text | awk '/DNS:/{sub(/DNS:/,"");print}' ' ` Dec 7, 2022 at 16:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .