How to extract certs from apache ca-bundle.crt file?

Apache web server reads Certificate Authority(CA) certs from ../cert/ca-bundle.crt file for SSL authentication. It has all certs in PEM format and no way to know exactly what they are. I want to get each cert seperated by boundary strings into a file and feed it to "keytool" command to see what each cert is.

# some comments
some more text
# some empty lines or empty lines with spaces
 
 
-----BEGIN CERTIFICATE-----
MIIDTTCCAra
UzEkMCIGA1
FR1N
-----END CERTIFICATE-----
some text
-----BEGIN CERTIFICATE-----
FAsfTTCCAra
-----END CERTIFICATE-----
lot of text here
-----BEGIN CERTIFICATE-----
AFfsfser
AafdsFaf
-----END CERTIFICATE-----

I have around 60 of those blocks with different number of lines between each boundary. I want to read each cert block and pass it to keytool command then print it to a diffrent file to know what they are.

cat ca-bundle.crt | awk [
for each certblock begin with "-----BEGIN CERTIFICATE-----" and end with "-----END CERTIFICATE-----"; do
 
echo "\n ---------------------------" >>allcerts.log
keytool -v -printcert -file $certblock >>allcerts.log
echo "\n ---------------------------" >>allcerts.log
 
done;
]

can someone help with awk/nawk logic? I am using solaris8 kshell 88i version.
or some other simple split/looping to get each block so that I can feed it to keytool?

Here is an approach in bash:

#!/bin/bash

flag=0

while read line
do
        if [[ "$line" =~ ^[-]*BEGIN ]]
        then
                flag=1
                continue
        fi

        [[ "$line" =~ ^[-]*END ]] && flag=0

        [ $flag -eq 1 ] && keytool -v -printcert -file "$line"

done < ca-bundle.crt

Yoda, are you sure that code will work I thought the -file option of keytool required a filesystem file, and I believe ca-bundle.crt will contain encoded keyblocks eg:

-----BEGIN CERTIFICATE-----
gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8
YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf
b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9
9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S
zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk
-----END CERTIFICATE-----
1 Like

It won't work. Please disregard my code.

This might do the job:

awk '
v{v=v"\n"$0}
/----BEGIN/ {v=$0}
/----END/&&v{
  print v > "tmp.crt"
  close("tmp.crt")
  system("keytool -v -printcert -file tmp.crt >> allcerts.log")
  print "\n--------------------------" >> "allcerts.log"
  close("allcerts.log")
  v=x}' ca-bundle.crt
1 Like

with awk I am getting syntax error @line#2. So I tried it with "/usr/xpg4/bin/awk", that is creating tmp.crt with only

-----BEGIN CERTIFICATE-----

Then I tried it with nawk, it worked like a charm.
Since there are some certs in a commented state I have added additional condition to filter all commented lines.

nawk 'v{v=v"\n"$0}!/^#/ && /----BEGIN/ {v=$0}/----END/&&v{  print v > "tmp.crt"  close("tmp.crt")  system("keytool -v -printcert -file tmp.crt >> allcerts.log")  print "\n--------------------------" >> "allcerts.log"  close("allcerts.log")  v=x}' ca-bundle.crt

If I remove v at the start of second line output shows commented certs, with v at the start of second line output does not show commented lines.
What is that first "v" doing at the second line?
I can pre-filter comments from ca-bundle.crt, but I am curious to know the reason behind behaviour I am noticing with nawk.

The line v{v=v"\n"$0} translates to: if v has a value assigned then append current line to v

This causes the script to ignore all lines until a "-----BEGIN" line is seen, at which point v is set to "------BEGIBN CERTIFICATE-------" and will be appended with each line from the input until "------END" is seen.

1 Like

Hello,
I know the thread is old, but if you want an approach in Ruby, this one works pretty well for versions post 1.9.1.

#!/usr/bin/env ruby

caFile = File.open( "ca-bundle.pem", "rb").read

outputIndex=0
output = File.open("certificate.#{outputIndex}.pem", "wb")

caFile.each_line do |aLine|
  if (aLine.strip == "-----END CERTIFICATE-----")
  	output.print "#{aLine}"
  	output.close
  	outputIndex = outputIndex + 1
	output = File.open("certificate.#{outputIndex}.pem", "wb")
  else
  	output.print "#{aLine}"
  end
end

Keep in mind this only extracts the certificate files and will not process ca-bundles that contain a CRL. Hope this helps someone :slight_smile: