Skip to content

Instantly share code, notes, and snippets.

@dberstein
Last active May 1, 2023 04:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dberstein/7cac649704b030501d2e0f8f3526f0f9 to your computer and use it in GitHub Desktop.
Save dberstein/7cac649704b030501d2e0f8f3526f0f9 to your computer and use it in GitHub Desktop.
ca-bundler.py - Certificate extractor for CA bundle creation

Certificate extractor for CA bundle creation

Outputs lines between (inclusive) -----BEGIN something----- and -----END something----- in reverse order. Useful for creation of CA certificates bundles.

Note that start/stop lines must begin with at least one dash and be followed by either BEGIN or END , then a space then non-space characters and end the line with at least one dash.

Above format rule will matches usual PEM format items like:

-----BEGIN CERTIFICATE-----
....
-----END CERTIFICATE-----

Usage

[cat file|] ca-bundler.py [file1 [file2 [fileN]]]

Extracts certificates from files in arguments or stdin if none given.

Examples

From hostname:port

Given SSL/TLS enabled hostname and port fetch certificate(s) with openssl and pipe them to ca-bundle.py to output only certificates in reverse order:

openssl s_client -showcerts -connect HOSTNAME:PORT -servername HOSTNAME </dev/null 2>/dev/null | ca-bundler.py > bundle.crt

From files

ca-bundler.py site.crt intermediate.crt root.crt > bundle.crt

#!/usr/bin/env python
from __future__ import print_function
import re
import sys
import fileinput
class Splitter(object):
def __init__(self, write_to=sys.stdout):
self.start, self.stop = self.build_regex(r'BEGIN', r'[^ ]+'), None
items, inside = [], False
for line in fileinput.input():
inside = self._line(inside, items, line)
write_to.write(''.join(map(lambda r: ''.join(r), reversed(items))))
def _line(self, inside, items, line):
if inside:
items[-1].append(line)
return False if self.stop.match(line) else True
m = self.start.match(line)
if not m:
return inside
items.append([line])
self.stop = self.build_regex(r'END', m.group(1))
return True
@classmethod
def build_regex(cls, prefix, suffix):
return re.compile(r'^-+{} ({})-+$'.format(prefix, suffix))
if __name__ == '__main__':
Splitter()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment