forked from KurzonDax/traefik-certificate-extractor
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4cc43d8
commit 3711251
Showing
5 changed files
with
153 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
certs/ | ||
data/ | ||
|
||
# Python ignores | ||
__pycache__/ | ||
*.py[cod] | ||
*$py.class | ||
.Python | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
wheels/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Use Python on Alpine Linux as base image | ||
FROM python:alpine | ||
|
||
# Create working directory | ||
RUN mkdir -p /app | ||
WORKDIR /app | ||
|
||
# Copy requirements.txt to force Docker not to use the cache | ||
COPY requirements.txt /app | ||
|
||
# Install app dependencies | ||
RUN pip3 install -r requirements.txt | ||
|
||
# Copy app source | ||
COPY . /app | ||
|
||
# Define entrypoint of the app | ||
ENTRYPOINT ["python3", "extractor.py"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,29 @@ | ||
# traefik-certificate-extractor | ||
# Traefik Certificate Extractor | ||
|
||
Tool to extract Let's Encrypt certificates from Traefik's ACME storage file. | ||
|
||
## Installation | ||
``` | ||
git clone https://github.com/DanielHuisman/traefik-certificate-extractor | ||
``` | ||
|
||
## Usage | ||
``` | ||
python3 extractor.py [directory] | ||
``` | ||
Default directory is `./data`. The output directory is `./certs`. | ||
|
||
## Output | ||
``` | ||
certs/ | ||
example.com/ | ||
cert.pem | ||
chain.pem | ||
fullchain.pem | ||
privkey.pem | ||
sub.example.nl/ | ||
cert.pem | ||
chain.pem | ||
fullchain.pem | ||
privkey.pem | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import sys | ||
import os | ||
import errno | ||
import time | ||
import json | ||
from base64 import b64decode | ||
from watchdog.observers import Observer | ||
from watchdog.events import FileSystemEventHandler | ||
|
||
class Handler(FileSystemEventHandler): | ||
def on_created(self, event): | ||
self.handle(event) | ||
|
||
def on_modified(self, event): | ||
self.handle(event) | ||
|
||
def handle(self, event): | ||
# Check if it's a JSON file | ||
if not event.is_directory and event.src_path.endswith('.json'): | ||
print('Certificates changed') | ||
|
||
# Read JSON file | ||
data = json.loads(open(event.src_path).read()) | ||
certs = data['DomainsCertificate']['Certs'] | ||
|
||
# Loop over all certificates | ||
for c in certs: | ||
# Decode private key, certificate and chain | ||
privatekey = b64decode(c['Certificate']['PrivateKey']).decode('utf-8') | ||
fullchain = b64decode(c['Certificate']['Certificate']).decode('utf-8') | ||
start = fullchain.find('-----BEGIN CERTIFICATE-----', 1) | ||
cert = fullchain[0:start] | ||
chain = fullchain[start:] | ||
|
||
# Create domain directory if it doesn't exist | ||
directory = 'certs/' + c['Certificate']['Domain'] + '/' | ||
try: | ||
os.makedirs(directory) | ||
except OSError as error: | ||
if error.errno != errno.EEXIST: | ||
raise | ||
|
||
# Write private key, certificate and chain to file | ||
with open(directory + 'privkey.pem', 'w') as f: | ||
f.write(privatekey) | ||
|
||
with open(directory + 'cert.pem', 'w') as f: | ||
f.write(cert) | ||
|
||
with open(directory + 'chain.pem', 'w') as f: | ||
f.write(chain) | ||
|
||
with open(directory + 'fullchain.pem', 'w') as f: | ||
f.write(fullchain) | ||
|
||
print('Extracted certificate for: ' + c['Domains']['Main'] + (', ' + ', '.join(c['Domains']['SANs']) if c['Domains']['SANs'] else '')) | ||
|
||
if __name__ == "__main__": | ||
# Determine path to watch | ||
path = sys.argv[1] if len(sys.argv) > 1 else './data' | ||
|
||
# Create output directory if it doesn't exist | ||
try: | ||
os.makedirs('certs') | ||
except OSError as error: | ||
if error.errno != errno.EEXIST: | ||
raise | ||
|
||
# Create event handler and observer | ||
event_handler = Handler() | ||
observer = Observer() | ||
|
||
# Register the directory to watch | ||
observer.schedule(event_handler, path) | ||
|
||
# Main loop to watch the directory | ||
observer.start() | ||
try: | ||
while True: | ||
time.sleep(1) | ||
except KeyboardInterrupt: | ||
observer.stop() | ||
observer.join() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
watchdog |