aboutsummaryrefslogtreecommitdiff
path: root/potpourri/ca-pickle.py
blob: b8cd630cdafbd9722f824512c4b57c77d983d189 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/env python

# $Id$

# Copyright (C) 2016  Parsons Government Services ("PARSONS")
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notices and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND PARSONS DISCLAIMS ALL
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL
# PARSONS BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

"""
Package up state of an old (pre-rpkidb, pre-pubdb, pre-Django 1.8)
RPKI CA installation as a Python pickle database, for later re-loading
into a more recent version of the code using a companion script.
"""

import os
import sys
import cPickle
import argparse
import subprocess
import rpki.config
import rpki.version
import rpki.autoconf

from rpki.mysql_import import MySQLdb, _mysql_exceptions

parser = argparse.ArgumentParser(description = __doc__)
parser.add_argument("-c", "--config",
                    help = "specify alternate location for rpki.conf")
parser.add_argument("-p", "--protocol",
                    choices = (0, 1, 2), type = int, default = 2,
                    help = "pickling protocol to use")
parser.add_argument("output",
                    help = "output file")
args = parser.parse_args()

cfg = rpki.config.parser(args.config)

databases = {}

for section in ("rpkid", "irdbd", "pubd"):
    db = MySQLdb.connect(db     = cfg.get(section = section, option = "sql-database"),
                         user   = cfg.get(section = section, option = "sql-username"),
                         passwd = cfg.get(section = section, option = "sql-password"))
    tables = {}

    cur = db.cursor()
    cur.execute("SHOW TABLES")
    table_names = tuple(row[0] for row in cur.fetchall())
    cur.close()

    cur = db.cursor(MySQLdb.cursors.DictCursor)
    for name in table_names:
        cur.execute("SELECT * FROM " + name)
        tables[name] = cur.fetchall()
    cur.close()

    db.close()

    databases[section] = tables

filenames     = [cfg.filename]
raw_config    = dict((section, {}) for section in cfg.cfg.sections())
cooked_config = dict((section, {}) for section in cfg.cfg.sections())

for section in cfg.cfg.sections():
    for option in cfg.cfg.options(section):
        raw_config   [section][option] = cfg.cfg.get(section = section, option = option)
        cooked_config[section][option] =     cfg.get(section = section, option = option)
        if os.path.isfile(   cooked_config[section][option]):
            filenames.append(cooked_config[section][option])

# Sigh, even here we need special hacks for rootd, which handles filenames a bit differently.
rootd_dir = cfg.get(section = "rootd", option = "rpki-root-dir", default = "")
for option in ("rpki-root-crl", "rpki-root-manifest", "rpki-subject-cert"):
    fn = os.path.join(rootd_dir, cfg.get(section = "rootd", option = option, default = ""))
    if os.path.isfile(fn):
        filenames.append(fn)

for i, fn in enumerate(filenames):
    filenames[i] = os.path.abspath(fn)

files = {}

for filename in filenames:
    with open(filename, "rb") as f:
        files[filename] = f.read()

world = dict(
    VERSION   = rpki.version.VERSION,
    RPKI_CONF = filenames[0],
    db        = databases,
    file      = files,
    raw       = raw_config,
    cfg       = cooked_config)

xz = subprocess.Popen(
    ("xz", "-C", "sha256"),
    stdin = subprocess.PIPE,
    stdout = os.open(args.output, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0600))

cPickle.dump(world, xz.stdin, args.protocol)

xz.stdin.flush()
xz.stdin.close()

if xz.wait() != 0:
    sys.exit("XZ pickling failed with code {}".format(xz.returncode))