From def95e42fda9a9e45bdf4f40a6ecb93b644dbf0b Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Mon, 15 Feb 2016 07:51:40 +0000 Subject: Checkpoint while shuffling stuff around for new installation scheme. Installation of everything but Debian packages is probably broken, and Debian packages are too at the moment due to (probably) minor errors in buildtools/debian-skeleton, but enough has changed that this really needs a snapshot checked in for backup. svn path=/branches/tk705/; revision=6257 --- Makefile.in | 58 +- buildtools/build-debian-packages.py | 70 ++ buildtools/build-ubuntu-ports.py | 70 -- buildtools/debian-skeleton/rpki-ca.install | 1 - buildtools/debian-skeleton/rpki-ca.postinst | 57 +- buildtools/debian-skeleton/rpki-ca.postrm | 8 +- buildtools/debian-skeleton/rpki-ca.prerm | 42 +- buildtools/debian-skeleton/rpki-rp.install | 2 +- buildtools/debian-skeleton/rpki-rp.postinst | 72 +- buildtools/debian-skeleton/rpki-rp.postrm | 7 + buildtools/debian-skeleton/rpki-rp.prerm | 15 +- .../freebsd-skeleton/rpki-rp/files/pkg-install.in | 65 +- buildtools/rpki-pbuilder.py | 2 +- ca/Makefile.in | 74 +- ca/rpki-confgen | 282 ----- ca/rpki-confgen.xml | 1031 ------------------ ca/rpki-manage | 15 - ca/rpki-sql-backup | 53 - ca/rpki-sql-setup | 348 ------ ca/rpki-start-servers | 3 +- ca/rpkic | 36 +- ca/upgrade-scripts/upgrade-rpkid-to-0.5709.py | 40 - configure.ac | 12 +- rp/Makefile.in | 2 +- rp/config/Makefile.in | 88 ++ rp/config/rpki-confgen | 282 +++++ rp/config/rpki-confgen.xml | 1111 ++++++++++++++++++++ rp/config/rpki-manage | 15 + rp/config/rpki-sql-backup | 53 + rp/config/rpki-sql-setup | 348 ++++++ rp/rcynic/Makefile.in | 14 +- rp/rcynic/rcynic-cron | 4 +- rp/rcynic/rules.darwin.mk | 78 +- rp/rcynic/rules.freebsd.mk | 43 +- rp/rcynic/rules.linux.mk | 51 +- rp/rpki-rtr/rules.freebsd.mk | 4 +- rp/rpki-rtr/rules.linux.mk | 2 +- setup.py | 15 +- 38 files changed, 2210 insertions(+), 2263 deletions(-) create mode 100644 buildtools/build-debian-packages.py delete mode 100644 buildtools/build-ubuntu-ports.py delete mode 100755 ca/rpki-confgen delete mode 100644 ca/rpki-confgen.xml delete mode 100755 ca/rpki-manage delete mode 100755 ca/rpki-sql-backup delete mode 100755 ca/rpki-sql-setup delete mode 100644 ca/upgrade-scripts/upgrade-rpkid-to-0.5709.py create mode 100644 rp/config/Makefile.in create mode 100755 rp/config/rpki-confgen create mode 100644 rp/config/rpki-confgen.xml create mode 100755 rp/config/rpki-manage create mode 100755 rp/config/rpki-sql-backup create mode 100755 rp/config/rpki-sql-setup diff --git a/Makefile.in b/Makefile.in index 8f53c2f4..a85cc6a4 100644 --- a/Makefile.in +++ b/Makefile.in @@ -7,6 +7,7 @@ LIBS = @LIBS@ PYTHON = @PYTHON@ INSTALL = @INSTALL@ -m 555 TRANG = @TRANG@ +SUDO = @SUDO@ prefix = @prefix@ exec_prefix = @exec_prefix@ @@ -32,8 +33,8 @@ CA_TARGET = @CA_TARGET@ WSGI_DAEMON_PROCESS = @WSGI_DAEMON_PROCESS@ WSGI_PROCESS_GROUP = @WSGI_PROCESS_GROUP@ RCYNIC_DIR = @RCYNIC_DIR@ -RCYNIC_USER = @RCYNIC_USER@ -RCYNIC_GROUP = @RCYNIC_GROUP@ +RPKI_USER = @RPKI_USER@ +RPKI_GROUP = @RPKI_GROUP@ RCYNIC_HTML_DIR = @RCYNIC_HTML_DIR@ RRDTOOL = @RRDTOOL@ APACHE_VERSION = @APACHE_VERSION@ @@ -127,38 +128,39 @@ VERSION: .FORCE ${PYTHON} buildtools/make-version.py rpki/autoconf.py: Makefile - @echo 'Generating $@'; \ - (echo '# Automatically generated. DO NOT EDIT.'; \ - echo ; \ - echo 'bindir = "${bindir}"'; \ - echo 'datarootdir = "${datarootdir}"'; \ - echo 'localstatedir = "${localstatedir}"'; \ - echo 'sbindir = "${sbindir}"'; \ - echo 'sharedstatedir = "${sharedstatedir}"'; \ - echo 'sysconfdir = "${sysconfdir}"'; \ - echo 'libexecdir = "${libexecdir}"'; \ - echo ; \ - echo 'WSGI_DAEMON_PROCESS = "${WSGI_DAEMON_PROCESS}"'; \ - echo 'WSGI_PROCESS_GROUP = "${WSGI_PROCESS_GROUP}"'; \ - echo 'RCYNIC_DIR = "${RCYNIC_DIR}"'; \ - echo 'RCYNIC_USER = "${RCYNIC_USER}"'; \ - echo 'RCYNIC_GROUP = "${RCYNIC_GROUP}"'; \ - echo 'RCYNIC_HTML_DIR = "${RCYNIC_HTML_DIR}"'; \ - echo 'RRDTOOL = "${RRDTOOL}"'; \ - echo 'APACHE_VERSION = "${APACHE_VERSION}"'; \ - echo 'WSGI_PYTHON_EGG_CACHE_DIR = "${WSGI_PYTHON_EGG_CACHE_DIR}"'; \ - echo 'WSGI_PYTHON_EGG_CACHE_USER = "${WSGI_PYTHON_EGG_CACHE_USER}"'; \ + @echo 'Generating $@'; \ + (echo '# Automatically generated. DO NOT EDIT.'; \ + echo ; \ + echo 'bindir = "${bindir}"'; \ + echo 'datarootdir = "${datarootdir}"'; \ + echo 'localstatedir = "${localstatedir}"'; \ + echo 'sbindir = "${sbindir}"'; \ + echo 'sharedstatedir = "${sharedstatedir}"'; \ + echo 'sysconfdir = "${sysconfdir}"'; \ + echo 'libexecdir = "${libexecdir}"'; \ + echo ; \ + echo 'WSGI_DAEMON_PROCESS = "${WSGI_DAEMON_PROCESS}"'; \ + echo 'WSGI_PROCESS_GROUP = "${WSGI_PROCESS_GROUP}"'; \ + echo 'RCYNIC_DIR = "${RCYNIC_DIR}"'; \ + echo 'RPKI_USER = "${RPKI_USER}"'; \ + echo 'RPKI_GROUP = "${RPKI_GROUP}"'; \ + echo 'RCYNIC_HTML_DIR = "${RCYNIC_HTML_DIR}"'; \ + echo 'RRDTOOL = "${RRDTOOL}"'; \ + echo 'APACHE_VERSION = "${APACHE_VERSION}"'; \ + echo 'WSGI_PYTHON_EGG_CACHE_DIR = "${WSGI_PYTHON_EGG_CACHE_DIR}"'; \ + echo 'WSGI_PYTHON_EGG_CACHE_USER = "${WSGI_PYTHON_EGG_CACHE_USER}"'; \ + echo 'SUDO = "${SUDO}"'; \ ) > $@ setup_autoconf.py: rpki/autoconf.py - @echo 'Generating $@'; \ - (cat rpki/autoconf.py; \ - echo ; \ + @echo 'Generating $@'; \ + (cat rpki/autoconf.py; \ + echo ; \ echo 'CFLAGS = """${CFLAGS}"""'; \ echo 'LDFLAGS = """${LDFLAGS}"""'; \ echo 'LIBS = """${LIBS}"""'; \ - echo 'RP_TARGET = """${RP_TARGET}"""'; \ - echo 'CA_TARGET = """${CA_TARGET}"""'; \ + echo 'RP_TARGET = """${RP_TARGET}"""'; \ + echo 'CA_TARGET = """${CA_TARGET}"""'; \ ) > $@ .FORCE: diff --git a/buildtools/build-debian-packages.py b/buildtools/build-debian-packages.py new file mode 100644 index 00000000..19f61f6d --- /dev/null +++ b/buildtools/build-debian-packages.py @@ -0,0 +1,70 @@ +# $Id$ +# +# Copyright (C) 2014 Dragon Research Labs ("DRL") +# Portions copyright (C) 2013 Internet Systems Consortium ("ISC") +# +# 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 DRL AND ISC DISCLAIM ALL +# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DRL OR +# ISC 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. + +""" +Set up for a Debian or Ubuntu package build. + +This is a script because we need to create the changelog. Other than +that, we just copy the Debian skeleton and optionally run the programs +necessary to produce a test build (production builds are happened +elsewhere, under pbuilder). +""" + +import subprocess +import platform +import argparse +import shutil +import sys +import os + +parser = argparse.ArgumentParser(description = __doc__) +parser.add_argument("-b", "--debuild", action = "store_true", help = "run debuild") +parser.add_argument("-i", "--debi", action = "store_true", help = "run debi") +parser.add_argument("-s", "--version-suffix", nargs = "?", const = platform.linux_distribution()[2], + help = "suffix to add to version string") +args = parser.parse_args() + +version = "0." + subprocess.check_output(("svnversion", "-c")).strip().split(":")[-1] + +if os.path.exists("debian"): + shutil.rmtree("debian") + +def ignore_dot_svn(src, names): + return [name for name in names if name == ".svn"] + +shutil.copytree("buildtools/debian-skeleton", "debian", ignore = ignore_dot_svn) + +os.chmod("debian/rules", 0755) + +msg = "Version %s of https://subvert-rpki.hactrn.net/trunk/" % version + +if args.version_suffix: + version += "~" + args.version_suffix + +subprocess.check_call(("dch", "--create", "--package", "rpki", "--newversion", version, msg), + env = dict(os.environ, + EDITOR = "true", + VISUAL = "true", + TZ = "UTC", + DEBEMAIL = "APT Builder Robot ")) + +if args.debuild or args.debi: + subprocess.check_call(("debuild", "-us", "-uc")) + +if args.debi: + subprocess.check_call(("sudo", "debi", "--with-depends")) diff --git a/buildtools/build-ubuntu-ports.py b/buildtools/build-ubuntu-ports.py deleted file mode 100644 index 19f61f6d..00000000 --- a/buildtools/build-ubuntu-ports.py +++ /dev/null @@ -1,70 +0,0 @@ -# $Id$ -# -# Copyright (C) 2014 Dragon Research Labs ("DRL") -# Portions copyright (C) 2013 Internet Systems Consortium ("ISC") -# -# 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 DRL AND ISC DISCLAIM ALL -# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DRL OR -# ISC 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. - -""" -Set up for a Debian or Ubuntu package build. - -This is a script because we need to create the changelog. Other than -that, we just copy the Debian skeleton and optionally run the programs -necessary to produce a test build (production builds are happened -elsewhere, under pbuilder). -""" - -import subprocess -import platform -import argparse -import shutil -import sys -import os - -parser = argparse.ArgumentParser(description = __doc__) -parser.add_argument("-b", "--debuild", action = "store_true", help = "run debuild") -parser.add_argument("-i", "--debi", action = "store_true", help = "run debi") -parser.add_argument("-s", "--version-suffix", nargs = "?", const = platform.linux_distribution()[2], - help = "suffix to add to version string") -args = parser.parse_args() - -version = "0." + subprocess.check_output(("svnversion", "-c")).strip().split(":")[-1] - -if os.path.exists("debian"): - shutil.rmtree("debian") - -def ignore_dot_svn(src, names): - return [name for name in names if name == ".svn"] - -shutil.copytree("buildtools/debian-skeleton", "debian", ignore = ignore_dot_svn) - -os.chmod("debian/rules", 0755) - -msg = "Version %s of https://subvert-rpki.hactrn.net/trunk/" % version - -if args.version_suffix: - version += "~" + args.version_suffix - -subprocess.check_call(("dch", "--create", "--package", "rpki", "--newversion", version, msg), - env = dict(os.environ, - EDITOR = "true", - VISUAL = "true", - TZ = "UTC", - DEBEMAIL = "APT Builder Robot ")) - -if args.debuild or args.debi: - subprocess.check_call(("debuild", "-us", "-uc")) - -if args.debi: - subprocess.check_call(("sudo", "debi", "--with-depends")) diff --git a/buildtools/debian-skeleton/rpki-ca.install b/buildtools/debian-skeleton/rpki-ca.install index ffae5103..90f4eecf 100644 --- a/buildtools/debian-skeleton/rpki-ca.install +++ b/buildtools/debian-skeleton/rpki-ca.install @@ -1,4 +1,3 @@ -etc/rpki/rpki-confgen.xml usr/lib/rpki usr/sbin usr/share/rpki diff --git a/buildtools/debian-skeleton/rpki-ca.postinst b/buildtools/debian-skeleton/rpki-ca.postinst index 18fef863..9bd1f96d 100644 --- a/buildtools/debian-skeleton/rpki-ca.postinst +++ b/buildtools/debian-skeleton/rpki-ca.postinst @@ -5,51 +5,25 @@ set -e -setup_rpkid_user() { - if ! getent passwd rpkid >/dev/null - then - useradd -g rpkid -M -N -d /nonexistent -s /sbin/nologin -c "RPKI certification authority engine(s)" rpkid - fi -} - -setup_rpkid_group() { - if ! getent group rpkid >/dev/null - then - groupadd rpkid - fi -} - setup_apache() { /usr/lib/rpki/rpkigui-apache-conf-gen --install --verbose } -setup_rpki_conf() { - # Update /etc/rpki.conf.sample for this system, and copy it to - # /etc/rpki.conf if no configuration file exists yet. - - # We don't (yet) have the ability to merge in settings from an - # existing rpki.conf, so we generate a new secret_key and a new - # SQL password every time, but that's harmless so long as we're - # careful not to overwrite an existing configuration. - - rpki-confgen --read-xml /etc/rpki/rpki-confgen.xml \ - --autoconf \ - --set myrpki::handle=`hostname -f | sed 's/[.]/_/g'` \ - --set myrpki::rpkid_server_host=`hostname -f` \ - --set myrpki::pubd_server_host=`hostname -f` \ - --set myrpki::shared_sql_engine=postgresql \ - --pwgen myrpki::shared_sql_password \ - --pwgen web_portal::secret-key \ - --write-conf /etc/rpki.conf.sample - - if test ! -f /etc/rpki.conf +setup_config() { + + rpki-confgen --read-xml /etc/rpki/rpki.rp.xml \ + --set myrpki::run_rpkid=yes \ + --set myrpki::run_pubd=yes \ + --write-xml /etc/rpki/rpki.ca.xml \ + --write-conf /etc/rpki/rpki.ca.sample.conf + + if test ! -f /etc/rpki.conf || cmp -s /etc/rpki.conf /etc/rpki/rpki.rp.sample.conf then - cp -p /etc/rpki.conf.sample /etc/rpki.conf + cp -p /etc/rpki/rpki.ca.conf.sample /etc/rpki.conf fi } setup_sql() { - #rpki-sql-setup --mysql-defaults /etc/mysql/debian.cnf create rpki-sql-setup --debug --verbose --postgresql-root-username postgres create } @@ -66,12 +40,7 @@ setup_cron() { t=$(hexdump -n 1 -e '"%u"' /dev/urandom) && echo "$(($t % 60)) */2 * * * nobody /usr/lib/rpki/rpkigui-import-routes" > /etc/cron.d/rpkigui-routeviews chmod 644 /etc/cron.d/rpkigui-routeviews ln -sf /usr/lib/rpki/rpkigui-check-expired /etc/cron.daily/rpkigui-check-expired - - # This should be user rpkid, but I don't have permissions set up - # properly for that yet. Arguably this should be integrated with - # rpkigui-check-expired anyway, not there yet either. - - echo "30 3 * * * root /usr/sbin/rpkic update_bpki" >/etc/cron.d/rpki-update-bpki + echo "30 3 * * * rpki /usr/sbin/rpkic update_bpki" >/etc/cron.d/rpki-update-bpki chmod 644 /etc/cron.d/rpki-update-bpki } @@ -90,10 +59,8 @@ setup_cron() { case "$1" in configure) - setup_rpkid_group - setup_rpkid_user setup_apache - setup_rpki_conf + setup_config setup_sql setup_bpki setup_django diff --git a/buildtools/debian-skeleton/rpki-ca.postrm b/buildtools/debian-skeleton/rpki-ca.postrm index 372847f2..c49492fe 100644 --- a/buildtools/debian-skeleton/rpki-ca.postrm +++ b/buildtools/debian-skeleton/rpki-ca.postrm @@ -22,13 +22,11 @@ set -e case "$1" in purge) - sql=/etc/rpki/drop_databases.sql - if test -f $sql + if cmp -s /etc/rpki.conf /etc/rpki/rpki.ca.sample.conf then - #mysql --defaults-file=/etc/mysql/debian.cnf --execute "source $sql" - sudo -u postgres psql -f $sql + cp -p /etc/rpki/rpki.rp.sample.conf /etc/rpki.conf fi - rm -f /etc/rpki.conf /etc/rpki.conf.sample $sql + rm -f /etc/rpki/rpki.ca.sample.conf /etc/rpki/rpki.ca.xml rm -f /etc/rpki/apache.conf /etc/rpki/apache.cer /etc/rpki/apache.key ;; diff --git a/buildtools/debian-skeleton/rpki-ca.prerm b/buildtools/debian-skeleton/rpki-ca.prerm index 2754ed43..3f44ea4d 100644 --- a/buildtools/debian-skeleton/rpki-ca.prerm +++ b/buildtools/debian-skeleton/rpki-ca.prerm @@ -31,53 +31,13 @@ case "$1" in rm -f /usr/share/rpki/rpkid.cer rm -f /usr/share/rpki/rpkid.key - # Record what will be needed to drop the databases completely, - # while we still have the necessary configuration data, but - # postpone dropping the databases until the postrm script, - # since that's where we find out whether this is a purge. - - #rpki-sql-setup --mysql-defaults /etc/mysql/debian.cnf script-drop /etc/rpki/drop_databases.sql - rpki-sql-setup --debug --verbose --postgresql-root-username postgres script-drop /etc/rpki/drop_databases.sql - # Clean up our cron jobs. rm -f /etc/cron.d/rpkigui-routeviews rm -f /etc/cron.daily/rpkigui-check-expired rm -f /etc/cron.d/rpki-update-bpki - # Clean up what we did to Apache. Modern version of this is - # just invocation of a Python script, but for now we also - # retain code needed to clean up nasty mess we created in the - # past, to avoid breaking old installations on upgrade. - - # Remove the old stuff first, if the containing file even exists. - - f=/etc/apache2/sites-available/default-ssl - if test -r $f - then - awk < $f > ${f}.tmp ' - BEGIN { - conf_file = "/etc/rpki/apache.conf"; - conf_regexp = "^[ \t]*Include[ \t]+" conf_file "[ \t]*$"; - } - $0 !~ conf_regexp { - print; - }' - - if cmp -s ${f}.tmp ${f}.orig - then - mv -f ${f}.orig $f - rm -f ${f}.tmp - else - mv -f ${f}.tmp $f - fi - fi - - # At this point we've cleaned up our Apache config mess. - # Not sure whether we should do "service apache2 reload" - # here, one could make a case either way. Skip for now. - - # Now remove the new stuff. + # Clean up what we did to Apache. /usr/lib/rpki/rpkigui-apache-conf-gen --remove --verbose diff --git a/buildtools/debian-skeleton/rpki-rp.install b/buildtools/debian-skeleton/rpki-rp.install index ce17bb14..fe0073a2 100644 --- a/buildtools/debian-skeleton/rpki-rp.install +++ b/buildtools/debian-skeleton/rpki-rp.install @@ -1,4 +1,4 @@ -etc/rcynic.conf +etc/rpki/rpki-confgen.xml etc/rpki/trust-anchors etc/xinetd.d/rpki-rtr usr/bin diff --git a/buildtools/debian-skeleton/rpki-rp.postinst b/buildtools/debian-skeleton/rpki-rp.postinst index b9f666a2..ae95e7b2 100644 --- a/buildtools/debian-skeleton/rpki-rp.postinst +++ b/buildtools/debian-skeleton/rpki-rp.postinst @@ -5,54 +5,63 @@ set -e -setup_groups() { - if ! getent group rcynic >/dev/null +setup_user() { + if ! getent group rpki >/dev/null then - groupadd rcynic + groupadd rpki fi - if ! getent group rpkirtr >/dev/null + if ! getent passwd rpki >/dev/null then - groupadd rpkirtr + useradd -g rpki -M -N -d /var/rcynic -s /sbin/nologin -c "RPKI system software" rpki fi } -setup_users() { - if ! getent passwd rcynic >/dev/null - then - useradd -g rcynic -M -N -d /var/rcynic -s /sbin/nologin -c "RPKI validation system" rcynic - fi - if ! getent passwd rpkirtr >/dev/null - then - useradd -g rpkirtr -M -N -d /var/rcynic/rpki-rtr -s /sbin/nologin -c "RPKI router server" rpkirtr - fi - usermod -a -G rpkirtr rcynic +setup_directories() { + install -o rpki -g rpki -d /var/rcynic/data /var/rcynic/rpki-rtr /var/rcynic/rpki-rtr/sockets /var/www/html/rcynic } -setup_directories() { - install -o rcynic -g rcynic -d /var/rcynic/data /var/rcynic/rpki-rtr - if test -d /var/www/html && test -d /var/www/rcynic && test ! -d /var/www/html/rcynic - then - mv /var/www/rcynic /var/www/html/rcynic - elif test -d /var/www/html +setup_config() { + + rpki-confgen --read-xml /etc/rpki/rpki-confgen.xml \ + --autoconf \ + --set myrpki::handle=`hostname -f | sed 's/[.]/_/g'` \ + --set myrpki::rpkid_server_host=`hostname -f` \ + --set myrpki::pubd_server_host=`hostname -f` \ + --set myrpki::shared_sql_engine=postgresql \ + --set myrpki::rcynic_sql_database=rpki \ + --set myrpki::rpkid_sql_database=rpki \ + --set myrpki::irdbd_sql_database=rpki \ + --set myrpki::pubd_sql_database=rpki \ + --pwgen myrpki::shared_sql_password \ + --pwgen web_portal::secret-key \ + --set myrpki::run_rpkid=no \ + --set myrpki::run_pubd=no \ + --write-xml /etc/rpki/rpki.rp.xml \ + --write-conf /etc/rpki/rpki.rp.sample.conf + + if test ! -f /etc/rpki.conf then - install -o rcynic -g rcynic -d /var/www/html/rcynic + cp -p /etc/rpki/rpki.rp.sample.conf /etc/rpki.conf fi - install -o rpkirtr -g rcynic -m 775 -d /var/rcynic/rpki-rtr/sockets +} + +setup_sql() { + rpki-sql-setup --debug --verbose --postgresql-root-username postgres create } # We want to pick a *random* minute for rcynic to run, to spread load # on repositories, which is why we don't just use a package crontab. -setup_rcynic_cron() { - if test "X`crontab -l -u rcynic 2>/dev/null`" = "X" +setup_cron() { + if test "X`crontab -l -u rpki 2>/dev/null`" = "X" then awk -v t=`hexdump -n 2 -e '"%u\n"' /dev/urandom` ' BEGIN {printf "MAILTO=root\n%u * * * *\texec /usr/bin/rcynic-cron\n", t % 60}' | - crontab -u rcynic - + crontab -u rpki - fi } -setup_rpkirtr_listener() { +setup_xinetd() { if test -f /var/run/xinetd.pid then kill -HUP `cat /var/run/xinetd.pid` @@ -74,11 +83,12 @@ setup_rpkirtr_listener() { case "$1" in configure) - setup_groups - setup_users + setup_user setup_directories - setup_rcynic_cron - setup_rpkirtr_listener + setup_config + setup_sql + setup_cron + setup_xinetd ;; abort-upgrade|abort-remove|abort-deconfigure) diff --git a/buildtools/debian-skeleton/rpki-rp.postrm b/buildtools/debian-skeleton/rpki-rp.postrm index ad4ed1b9..7236d7a5 100644 --- a/buildtools/debian-skeleton/rpki-rp.postrm +++ b/buildtools/debian-skeleton/rpki-rp.postrm @@ -23,6 +23,13 @@ case "$1" in purge) rm -rf /var/rcynic + sql=/etc/rpki/drop_databases.sql + if test -f $sql + then + sudo -u postgres psql -f $sql + rm -f $sql + fi + rm -f /etc/rpki/rpki.rp.sample.conf /etc/rpki/rpki.rp.xml /etc/rpki.conf ;; remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) diff --git a/buildtools/debian-skeleton/rpki-rp.prerm b/buildtools/debian-skeleton/rpki-rp.prerm index 37b111f2..b7e7cbde 100644 --- a/buildtools/debian-skeleton/rpki-rp.prerm +++ b/buildtools/debian-skeleton/rpki-rp.prerm @@ -20,16 +20,25 @@ set -e case "$1" in remove) - crontab -l -u rcynic 2>/dev/null | awk ' + # Record what will be needed to drop the databases completely, + # while we still have the necessary configuration data, but + # postpone dropping the databases until the postrm script, + # since that's where we find out whether this is a purge. + + rpki-sql-setup --debug --verbose --postgresql-root-username postgres script-drop /etc/rpki/drop_databases.sql + + # Clean up our cron job. + + crontab -l -u rpki 2>/dev/null | awk ' $0 !~ "exec /usr/bin/rcynic-cron" { line[++n] = $0; } END { if (n) for (i = 1; i <= n; i++) - print line[i] | "crontab -u rcynic -"; + print line[i] | "crontab -u rpki -"; else - system("crontab -u rcynic -r"); + system("crontab -u rpki -r"); }' ;; diff --git a/buildtools/freebsd-skeleton/rpki-rp/files/pkg-install.in b/buildtools/freebsd-skeleton/rpki-rp/files/pkg-install.in index 4c687f38..8942fd1a 100644 --- a/buildtools/freebsd-skeleton/rpki-rp/files/pkg-install.in +++ b/buildtools/freebsd-skeleton/rpki-rp/files/pkg-install.in @@ -3,47 +3,25 @@ case $2 in PRE-INSTALL) - if /usr/sbin/pw groupshow "rcynic" 2>/dev/null + if /usr/sbin/pw groupshow "rpki" 2>/dev/null then - echo "You already have a group \"rcynic\", so I will use it." - elif /usr/sbin/pw groupadd rcynic + echo "You already have a group \"rpki\", so I will use it." + elif /usr/sbin/pw groupadd rpki then - echo "Added group \"rcynic\"." + echo "Added group \"rpki\"." else - echo "Adding group \"rcynic\" failed..." + echo "Adding group \"rpki\" failed..." echo "Please create it, then try again." exit 1 fi - if /usr/sbin/pw usershow "rcynic" 2>/dev/null + if /usr/sbin/pw usershow "rpki" 2>/dev/null then - echo "You already have a user \"rcynic\", so I will use it." - elif /usr/sbin/pw useradd rcynic -g rcynic -h - -d /nonexistant -s /usr/sbin/nologin -c "RPKI validation system" + echo "You already have a user \"rpki\", so I will use it." + elif /usr/sbin/pw useradd rpki -g rpki -h - -d /nonexistant -s /usr/sbin/nologin -c "RPKI system daemons" then - echo "Added user \"rcynic\"." + echo "Added user \"rpki\"." else - echo "Adding user \"rcynic\" failed..." - echo "Please create it, then try again." - exit 1 - fi - if /usr/sbin/pw groupshow "rpkirtr" 2>/dev/null - then - echo "You already have a group \"rpkirtr\", so I will use it." - elif /usr/sbin/pw groupadd rpkirtr - then - echo "Added group \"rpkirtr\"." - else - echo "Adding group \"rpkirtr\" failed..." - echo "Please create it, then try again." - exit 1 - fi - if /usr/sbin/pw usershow "rpkirtr" 2>/dev/null - then - echo "You already have a user \"rpkirtr\", so I will use it." - elif /usr/sbin/pw useradd rpkirtr -g rpkirtr -h - -d /nonexistant -s /usr/sbin/nologin -c "RPKI router server" - then - echo "Added user \"rpkirtr\"." - else - echo "Adding user \"rpkirtr\" failed..." + echo "Adding user \"rpki\" failed..." echo "Please create it, then try again." exit 1 fi @@ -55,25 +33,24 @@ POST-INSTALL) echo "Creating /var/rcynic" /usr/bin/install -o root -g wheel -d /var/rcynic fi - for dir in /var/rcynic/data /var/rcynic/rpki-rtr + for dir in /var/rcynic/data /var/rcynic/rpki-rtr /var/rcynic/rpki-rtr/sockets do - /usr/bin/install -o rcynic -g rcynic -d $dir + /usr/bin/install -o rpki -g rpki -d $dir done - /usr/bin/install -o rpkirtr -g rcynic -m 775 -d /var/rcynic/rpki-rtr/sockets - if test ! -f /usr/local/etc/rcynic.conf + if test ! -f /usr/local/etc/rpki.conf then - /bin/cp -p /usr/local/etc/rcynic.conf.sample /usr/local/etc/rcynic.conf + /bin/cp -p /usr/local/etc/rpki.conf.sample /usr/local/etc/rpki.conf fi htmldir=/usr/local/www/apache%%APACHE_VERSION%%/data/rcynic - /usr/bin/install -o rcynic -g rcynic -d $htmldir - if test "X`/usr/bin/crontab -l -u rcynic 2>/dev/null`" != "X" + /usr/bin/install -o rpki -g rpki -d $htmldir + if test "X`/usr/bin/crontab -l -u rpki 2>/dev/null`" != "X" then - echo "rcynic user already has a crontab, leaving it alone" + echo "rpki user already has a crontab, leaving it alone" else - echo "Setting up rcynic's crontab to run rcynic-cron script" + echo "Setting up rpki's crontab to run rcynic-cron script" /usr/bin/awk -v t=`/usr/bin/hexdump -n 2 -e '"%u\n"' /dev/random` ' BEGIN {printf "MAILTO=root\n%u * * * *\texec /usr/local/bin/rcynic-cron\n", t % 60}' | - /usr/bin/crontab -u rcynic - + /usr/bin/crontab -u rpki - fi echo "Setting up rpki-rtr listener under inetd" if /usr/bin/egrep -q '^rpki-rtr' /etc/services @@ -101,7 +78,7 @@ POST-INSTALL) if /usr/bin/egrep -q "rpki-rtr[ ]+stream[ ]+tcp[ ]" /etc/inetd.conf then echo "You already have an /etc/inetd.conf entry for rpki-rtr on TCPv4, so I will use it." - elif echo >>/etc/inetd.conf "rpki-rtr stream tcp nowait rpkirtr /usr/local/bin/rpki-rtr rpki-rtr server /var/rcynic/rpki-rtr" + elif echo >>/etc/inetd.conf "rpki-rtr stream tcp nowait rpki /usr/local/bin/rpki-rtr rpki-rtr server /var/rcynic/rpki-rtr" then echo "Added rpki-rtr for TCPv4 to /etc/inetd.conf." else @@ -111,7 +88,7 @@ POST-INSTALL) if /usr/bin/egrep -q "rpki-rtr[ ]+stream[ ]+tcp6[ ]" /etc/inetd.conf then echo "You already have an /etc/inetd.conf entry for rpki-rtr on TCPv6, so I will use it." - elif echo >>/etc/inetd.conf "rpki-rtr stream tcp6 nowait rpkirtr /usr/local/bin/rpki-rtr rpki-rtr server /var/rcynic/rpki-rtr" + elif echo >>/etc/inetd.conf "rpki-rtr stream tcp6 nowait rpki /usr/local/bin/rpki-rtr rpki-rtr server /var/rcynic/rpki-rtr" then echo "Added rpki-rtr for TCPv6 to /etc/inetd.conf." else diff --git a/buildtools/rpki-pbuilder.py b/buildtools/rpki-pbuilder.py index 32247ff8..1d45e862 100644 --- a/buildtools/rpki-pbuilder.py +++ b/buildtools/rpki-pbuilder.py @@ -201,7 +201,7 @@ class Release(object): os.unlink(os.path.join(dsc_dir, fn)) run("rm", "-rf", "debian", cwd = args.svn_tree) run(sys.executable, "buildtools/make-version.py", cwd = args.svn_tree) - run(sys.executable, "buildtools/build-ubuntu-ports.py", "--version-suffix", self.release, cwd = args.svn_tree) + run(sys.executable, "buildtools/build-debian-packages.py", "--version-suffix", self.release, cwd = args.svn_tree) run("dpkg-buildpackage", "-S", "-us", "-uc", "-rfakeroot", cwd = args.svn_tree) if not os.path.exists(self.basefile): diff --git a/ca/Makefile.in b/ca/Makefile.in index e6081238..27425766 100644 --- a/ca/Makefile.in +++ b/ca/Makefile.in @@ -35,7 +35,11 @@ WSGI_PYTHON_EGG_CACHE_USER = @WSGI_PYTHON_EGG_CACHE_USER@ CA_INSTALL_TARGETS = @CA_INSTALL_TARGETS@ -all:: examples/rpki.conf +# Apache configuration may end up moving to common runtime config, but +# that yak will have to wait for another day to get its shave. + +all:: + @true clean:: cd tests; $(MAKE) $@ @@ -43,11 +47,8 @@ clean:: install:: ${CA_INSTALL_TARGETS} install-always:: all - @echo - @echo "== Default configuration file location is ${sysconfdir}/rpki.conf ==" - @echo - ${INSTALL} examples/rpki.conf ${DESTDIR}${sysconfdir}/rpki.conf.sample ${INSTALL} -d ${DESTDIR}${datarootdir}/rpki/publication + ${INSTALL} -d ${DESTDIR}${datarootdir}/rpki/rrdp-publication uninstall deinstall:: -${libexecdir}/rpkigui-apache-conf-gen --remove --verbose @@ -62,30 +63,8 @@ distclean:: clean cd tests; ${MAKE} $@ rm -f Makefile -examples/rpki.conf: ${abs_top_srcdir}/rpki/autoconf.py rpki-confgen rpki-confgen.xml - ${PYTHON} rpki-confgen \ - --read-xml rpki-confgen.xml \ - --autoconf \ - --set myrpki::handle=`hostname -f | sed 's/[.]/_/g'` \ - --set myrpki::rpkid_server_host=`hostname -f` \ - --set myrpki::pubd_server_host=`hostname -f` \ - --pwgen myrpki::shared_sql_password \ - --pwgen web_portal::secret-key \ - --write-conf $@ - -clean:: - rm -f examples/rpki.conf - install-postconf: \ - install-user install-egg-cache install-conf install-apache install-mysql install-django install-bpki install-cron - -# This should create user "rpkid" and group "rpkid", but as we have -# not yet tested our ability to run in such a configuration, this -# would be a little premature. Can steal Makefile code for this from -# rcynic when we're ready to do something with it. - -install-user: - @true + install-egg-cache install-conf install-apache install-bpki install-cron # This is only necessary on some platforms (currently FreeBSD, # due to shortcomings in the way that Python eggs are installed @@ -99,37 +78,25 @@ install-egg-cache: fi; \ fi -# We used to play the FreeBSD game of copying rpki.conf.sample to -# rpki.conf on install and removing rpki.conf if it's identical to -# rpki.conf.sample in uninstall, but that turns out to work poorly -# with generated passwords. So now we copy rpki.conf.sample if and -# only if rpki.conf does not exist, and we leave removal of rpki.conf -# for the user to deal with. This in turn leaves us with a different -# problem of how to upgrade rpki.conf, but at least in the FreeBSD -# universe we're supposed to leave that problem for the user. - install-conf: - if test -f ${DESTDIR}${sysconfdir}/rpki.conf; \ + ${sbindir}/rpki-confgen \ + --read-xml ${DESTDIR}${sysconfdir}/rpki/rpki.rp.xml \ + --set myrpki::run_rpkid=yes \ + --set myrpki::run_pubd=yes \ + --write-xml ${DESTDIR}${sysconfdir}/rpki/rpki.ca.xml \ + --write-conf ${DESTDIR}${sysconfdir}/rpki/rpki.ca.sample.conf + if test ! -f ${DESTDIR}${sysconfdir}/rpki.conf ||\ + cmp -s ${DESTDIR}${sysconfdir}/rpki.conf ${DESTDIR}${sysconfdir}/rpki/rpki.rp.sample.conf;\ then \ - true; \ - else \ - cp -p ${DESTDIR}${sysconfdir}/rpki.conf.sample ${DESTDIR}${sysconfdir}/rpki.conf; \ + cp -p ${DESTDIR}${sysconfdir}/rpki/rpki.ca.sample.conf ${DESTDIR}${sysconfdir}/rpki.conf fi -uninstall deinstall:: -# if cmp -s ${DESTDIR}${sysconfdir}/rpki.conf ${DESTDIR}${sysconfdir}/rpki.conf.sample; then rm -f ${DESTDIR}${sysconfdir}/rpki.conf; else true; fi - rm -f ${DESTDIR}${sysconfdir}/rpki.conf.sample +#uninstall deinstall:: +# rm -f ${DESTDIR}${sysconfdir}/rpki/rpki.ca.xml ${DESTDIR}${sysconfdir}/rpki/rpki.ca.sample.conf install-apache: ${libexecdir}/rpkigui-apache-conf-gen --install --verbose -install-mysql: - ${sbindir}/rpki-sql-setup create - -install-django: - ${sbindir}/rpki-manage syncdb --noinput - ${sbindir}/rpki-manage migrate app - install-bpki: ${sbindir}/rpkic initialize_server_bpki @@ -150,11 +117,8 @@ uninstall deinstall:: uninstall-cron-using-crontab # Code for setting up and tearing down cron jobs using the crontab(1) # program. We don't use this on all platforms, but we do use it on # more than one, so it's broken out here as common code. -# -# CRONTAB_USER really should be rpkid, but we don't have the rest of -# the package set up for that yet, so run it as root for now. -CRONTAB_USER = root +CRONTAB_USER = rpki install-cron-using-crontab: @crontab -l -u ${CRONTAB_USER} 2>/dev/null | \ diff --git a/ca/rpki-confgen b/ca/rpki-confgen deleted file mode 100755 index e6780446..00000000 --- a/ca/rpki-confgen +++ /dev/null @@ -1,282 +0,0 @@ -#!/usr/bin/env python - -# $Id$ -# -# Copyright (C) 2014 Dragon Research Labs ("DRL") -# Portions copyright (C) 2013 Internet Systems Consortium ("ISC") -# -# 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 DRL AND ISC DISCLAIM ALL -# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DRL OR -# ISC 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. - -import os -import sys -import argparse -import base64 -import textwrap - -from lxml.etree import Element, SubElement, ElementTree, Comment - -space4 = " " * 4 -space6 = " " * 6 -space8 = " " * 8 -star78 = "*" * 78 - -wiki_wrapper = textwrap.TextWrapper() -conf_wrapper = textwrap.TextWrapper(initial_indent = "# ", subsequent_indent = "# ") -xml6_wrapper = textwrap.TextWrapper(initial_indent = space6, subsequent_indent = space6) -xml8_wrapper = textwrap.TextWrapper(initial_indent = space8, subsequent_indent = space8) - -class Option(object): - - def __init__(self, name, value, doc): - self.name = name - self.value = value - self.doc = doc - - @property - def width(self): - return len(self.name) - - def to_xml(self): - x = Element("option", name = self.name) - if self.value is not None: - x.set("value", self.value) - for d in self.doc: - SubElement(x, "doc").text = "\n" + xml8_wrapper.fill(d) + "\n" + space6 - return x - - def to_wiki(self, f): - f.write("\n== {0.name} == #{0.name}\n".format(self)) - for d in self.doc: - f.write("\n{0}\n".format(wiki_wrapper.fill(d))) - if self.value is None: - f.write("\n{0}\n".format(wiki_wrapper.fill("No default value."))) - else: - f.write("\n{{{{{{\n#!ini\n{0.name} = {0.value}\n}}}}}}\n".format(self)) - - def to_conf(self, f, width): - for i, d in enumerate(self.doc): - f.write("{}\n{}\n".format("" if i == 0 else "#", - conf_wrapper.fill(d))) - if self.value is None: - f.write("\n#{1.name:{0}} = ???\n".format(width - 1, self)) - else: - f.write("\n{1.name:{0}} = {1.value}\n".format(width, self)) - -class Section(object): - - def __init__(self, name): - self.name = name - self.doc = [] - self.options = [] - - @property - def width(self): - return max(o.width for o in self.options) - - @classmethod - def from_xml(cls, elt): - self = cls(name = elt.get("name")) - for x in elt.iterchildren("doc"): - self.doc.append(" ".join(x.text.split())) - for x in elt.iterchildren("option"): - self.options.append(Option(name = x.get("name"), value = x.get("value"), - doc = [" ".join(d.text.split()) - for d in x.iterchildren("doc")])) - return self - - def to_xml(self): - x = Element("section", name = self.name) - for d in self.doc: - SubElement(x, "doc").text = "\n" + xml6_wrapper.fill(d) + "\n" + space4 - x.extend(o.to_xml() for o in self.options) - return x - - def to_wiki(self, f): - f.write("\n= [{0}] section = #{0}\n".format(self.name)) - for d in self.doc: - f.write("\n{0}\n".format(wiki_wrapper.fill(d))) - for o in self.options: - o.to_wiki(f) - - def to_conf(self, f, width): - f.write("\n" + "#" * 78 + "\n\n[" + self.name + "]\n") - if self.doc: - f.write("\n##") - for i, d in enumerate(self.doc): - f.write("{}\n{}\n".format("" if i == 0 else "#", - conf_wrapper.fill(d))) - f.write("##\n") - for o in self.options: - o.to_conf(f, width) - -def wiki_header(f, ident, toc): - f.write(textwrap.dedent('''\ - {{{{{{ - #!comment - - {star78} - THIS PAGE WAS GENERATED AUTOMATICALLY, DO NOT EDIT. - - Generated from {ident} - by $Id$ - {star78} - - }}}}}} - '''.format(star78 = star78, - ident = ident))) - if toc is not None: - f.write("[[TracNav({})]]\n".format(toc)) - f.write("[[PageOutline]]\n") - -def conf_header(f, ident): - f.write(textproc.dedent('''\ - # Automatically generated. Edit as needed, but be careful of overwriting. - # - # Generated from {ident} - # by $Id$ - - '''.format(ident = ident))) - - -# http://stackoverflow.com/questions/9027028/argparse-argument-order - -class CustomAction(argparse.Action): - - def __call__(self, parser, namespace, values, option_string = None): - if not "ordered_args" in namespace: - namespace.ordered_args = [] - namespace.ordered_args.append((self.dest, values)) - -class CustomFlagAction(CustomAction): - - def __init__(self, option_strings, dest, default = None, - required = False, help = None): # pylint: disable=W0622 - super(CustomFlagAction, self).__init__( - option_strings = option_strings, - dest = dest, - nargs = 0, - const = None, - default = default, - required = required, - help = help) - - -class main(object): - - def __init__(self): - self.sections = [] - self.section_map = None - self.option_map = None - self.ident = None - self.toc = None - - parser = argparse.ArgumentParser(description = __doc__) - parser.add_argument("--read-xml", type = argparse.FileType("r"), metavar = "FILE", action = CustomAction, help = "XML input file defining sections and options", required = True) - parser.add_argument("--write-xml", type = argparse.FileType("w"), metavar = "FILE", action = CustomAction, help = "XML output file to snapshot configuration") - parser.add_argument("--write-conf", type = argparse.FileType("w"), metavar = "FILE", action = CustomAction, help = "rpki.conf configuration file to write") - parser.add_argument("--write-wiki", type = argparse.FileType("w"), metavar = "FILE", action = CustomAction, help = "TracWiki file to write (monolithic)") - parser.add_argument("--write-wiki-pages", metavar = "PATTERN", action = CustomAction, help = "TracWiki filenames (pattern) to write (one section per page)") - parser.add_argument("--set", metavar = "VARVAL", action = CustomAction, help = "variable setting in form \"VAR=VAL\"") - parser.add_argument("--pwgen", metavar = "VAR", action = CustomAction, help = "set variable to generated password") - parser.add_argument("--toc", metavar = "TOCVAL", action = CustomAction, help = "set TOC value to use with TracNav plugin") - parser.add_argument("--autoconf", action = CustomFlagAction, help = "configure [autoconf] section") - args = parser.parse_args() - - for cmd, arg in args.ordered_args: - getattr(self, "do_" + cmd)(arg) - - def do_read_xml(self, arg): - self.option_map = None - root = ElementTree(file = arg).getroot() - self.ident = root.get("ident") - self.sections.extend(Section.from_xml(x) for x in root) - self.option_map = {} - self.section_map = {} - for section in self.sections: - if section.name in self.section_map: - sys.exit("Duplicate section {}".format(section.name)) - self.section_map[section.name] = section - for option in section.options: - name = (section.name, option.name) - if name in self.option_map: - sys.exit("Duplicate option {}::{}".format(*name)) - self.option_map[name] = option - - def do_set(self, arg): - try: - name, value = arg.split("=", 1) - section, option = name.split("::") - except ValueError: - sys.exit("Couldn't parse --set specification \"{}\"".format(arg)) - name = (section, option) - if name not in self.option_map: - sys.exit("Couldn't find option {}::{}".format(*name)) - self.option_map[name].value = value - - def do_pwgen(self, arg): - try: - section, option = arg.split("::") - except ValueError: - sys.exit("Couldn't parse --pwgen specification \"{}\"".format(arg)) - name = (section, option) - if name not in self.option_map: - sys.exit("Couldn't find option {}::{}".format(name)) - self.option_map[name].value = base64.urlsafe_b64encode(os.urandom(66)) - - def do_autoconf(self, ignored): - try: - import rpki.autoconf - for option in self.section_map["autoconf"].options: - try: - option.value = getattr(rpki.autoconf, option.name) - except AttributeError: - pass - except ImportError: - sys.exit("rpki.autoconf module is not available") - except KeyError: - sys.exit("Couldn't find autoconf section") - - def do_write_xml(self, arg): - x = Element("configuration", ident = self.ident) - x.append(Comment(" Machine-editable configuration snapshot, generated automatically, do not touch ")) - x.extend(s.to_xml() for s in self.sections) - ElementTree(x).write(arg, pretty_print = True, encoding = "us-ascii") - - def do_write_wiki(self, arg): - for i, section in enumerate(self.sections): - if i == 0: - wiki_header(arg, self.ident, self.toc) - else: - arg.write("\f\n") - section.to_wiki(arg) - - def do_write_wiki_pages(self, arg): - for section in self.sections: - with open(arg % section.name, "w") as f: - wiki_header(f, self.ident, self.toc) - section.to_wiki(f) - - def do_write_conf(self, arg): - with open(arg, "w") as f: - conf_header(f, self.ident) - width = max(s.width for s in self.sections) - for section in self.sections: - section.to_conf(f, width) - - def do_toc(self, arg): - self.toc = arg - - -if __name__ == "__main__": - main() diff --git a/ca/rpki-confgen.xml b/ca/rpki-confgen.xml deleted file mode 100644 index ba33c7c9..00000000 --- a/ca/rpki-confgen.xml +++ /dev/null @@ -1,1031 +0,0 @@ - - - - -
- - - The "`[myrpki]`" section contains all the parameters that you - really need to configure. The name "`myrpki`" is historical and - may change in the future. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - rpkid's default config file is the system `rpki.conf` file. - Start rpkid with "`-c filename`" to choose a different config - file. All options are in the "`[rpkid]`" section. BPKI - Certificates and keys may be in either DER or PEM format. - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - irdbd's default configuration file is the system `rpki.conf` - file. Start irdbd with "`-c filename`" to choose a different - configuration file. All options are in the "`[irdbd]`" section. - - - - Since irdbd is part of the back-end system, it has direct access to - the back-end's SQL database, and thus is able to pull its own BPKI - configuration directly from the database, and thus needs a bit less - configuration than the other daemons. - - - - - - - - - - - - - - - - -
- -
- - - pubd's default configuration file is the system `rpki.conf` - file. Start pubd with "`-c filename`" to choose a different - configuration file. All options are in the "`[pubd]`" section. - BPKI certificates and keys may be either DER or PEM format. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - You don't need to run rootd unless you're IANA, are certifying - private address space, or are an RIR which refuses to accept IANA as - the root of the public address hierarchy. - - - - Ok, if that wasn't enough to scare you off: rootd is a mess, - needs to be rewritten, or, better, merged into rpkid, and - requires far too many configuration parameters. - - - - rootd was originally intended to be a very simple program which - simplified rpkid enormously by moving one specific task (acting - as the root CA of an RPKI certificate hierarchy) out of rpkid. - As the specifications and code (mostly the latter) have evolved, - however, this task has become more complicated, and rootd would - have to become much more complicated to keep up. - - - - Don't run rootd unless you're sure that you need to do so. - - - - Still think you need to run rootd? OK, but remember, you have - been warned.... - - - - rootd's default configuration file is the system `rpki.conf` - file. Start rootd with "`-c filename`" to choose a different - configuration file. All options are in the "`[rootd]`" section. - Certificates and keys may be in either DER or PEM format. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
- - - Glue to allow Django to pull user configuration from this file - rather than requiring the user to edit settings.py. - - - - - - - - - - -
- -
- - - rpki-confgen --autoconf records the current autoconf settings - here, so that other options can refer to them. The section name - "autoconf" is magic, don't change it. - - - - - - - - - - -
- -
diff --git a/ca/rpki-manage b/ca/rpki-manage deleted file mode 100755 index 16d0990d..00000000 --- a/ca/rpki-manage +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python - -import os - -# django-admin seems to have problems creating the superuser account when -# $LANG is unset or is set to something totally incompatible with UTF-8. - -if os.environ.get("LANG") in (None, "", "C"): - os.environ["LANG"] = "en_US.UTF-8" - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rpki.django_settings.gui") - -from django.core.management import execute_from_command_line - -execute_from_command_line() diff --git a/ca/rpki-sql-backup b/ca/rpki-sql-backup deleted file mode 100755 index 986e10b1..00000000 --- a/ca/rpki-sql-backup +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python - -# $Id$ -# -# Copyright (C) 2014 Dragon Research Labs ("DRL") -# Portions copyright (C) 2010-2013 Internet Systems Consortium ("ISC") -# -# 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 DRL AND ISC DISCLAIM ALL -# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DRL OR -# ISC 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. - -""" -Back up data from SQL databases, looking at config file to figure out -which databases and what credentials to use with them. -""" - -import subprocess -import os -import argparse -import sys -import time -import rpki.config - -os.environ["TZ"] = "UTC" -time.tzset() - -parser = argparse.ArgumentParser(description = __doc__) -parser.add_argument("-c", "--config", - help = "override default location of configuration file") -parser.add_argument("-o", "--output", - type = argparse.FileType("wb"), default = sys.stdout, - help = "destination for SQL dump (default: stdout)") -args = parser.parse_args() - -cfg = rpki.config.parser(set_filename = args.config, section = "myrpki") - -for name in ("rpkid", "irdbd", "pubd"): - if cfg.getboolean("start_" + name, False): - subprocess.check_call( - ("mysqldump", "--add-drop-database", - "-u", cfg.get("sql-username", section = name), - "-p" + cfg.get("sql-password", section = name), - "-B", cfg.get("sql-database", section = name)), - stdout = args.output) diff --git a/ca/rpki-sql-setup b/ca/rpki-sql-setup deleted file mode 100755 index c72c97c5..00000000 --- a/ca/rpki-sql-setup +++ /dev/null @@ -1,348 +0,0 @@ -#!/usr/bin/env python - -# $Id$ -# -# Copyright (C) 2014 Dragon Research Labs ("DRL") -# Portions copyright (C) 2009-2013 Internet Systems Consortium ("ISC") -# -# 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 DRL AND ISC DISCLAIM ALL -# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DRL OR -# ISC 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. - -""" -Automated setup of SQL stuff used by the RPKI tools. Pulls -configuration from rpki.conf, prompts for SQL password when needed. -""" - -import os -import pwd -import sys -import getpass -import textwrap -import argparse -import rpki.config - - -class Abstract_Driver(object): - - # Kludge to make classes derived from this into singletons. Net - # of a Million Lies says this is Not Pythonic, but it seems to - # work, so long as one doesn't attempt to subclass the resulting - # driver classes. For our purposes, it will do. - - __instance = None - - def __new__(cls, *args, **kwargs): - if cls.__instance is None: - cls.__instance = object.__new__(cls, *args, **kwargs) - return cls.__instance - - def db_accessible(self, udb): - try: - self._db_accessible_test(udb) - except: - return False - else: - return True - - def db_exists(self, udb): - self.execute("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = %s", (udb.database,)) - return bool(self.fetchone()[0]) - - def fetchone(self): - return self._cur.fetchone() - - def fetchall(self): - return self._cur.fetchall() - - def close(self): - self._cur.close() - self._db.close() - - def log(self, msg): - if self.args.verbose: - sys.stderr.write(msg + "\n") - - -class MySQL_Driver(Abstract_Driver): - - _initialized = False - - def __init__(self, args): - try: - self.driver - except AttributeError: - from rpki.mysql_import import MySQLdb - self.driver = MySQLdb - self.args = args - - def _db_accessible_test(self, udb): - self.driver.connect(db = udb.database, user = udb.username, passwd = udb.password).close() - - def execute(*args): - try: - self._cur - except AttributeError: - self.log("MySQL driver initializing root connection") - if self.args.mysql_defaults: - mysql_cfg = rpki.config.parser(set_filename = self.args.mysql_defaults, section = "client") - self._db = self.driver.connect(db = "mysql", - user = mysql_cfg.get("user"), - passwd = mysql_cfg.get("password")) - else: - self._db = self.driver.connect(db = "mysql", - user = "root", - passwd = getpass.getpass("Please enter your MySQL root password: ")) - self._db.autocommit(True) - self._cur = self._db.cursor() - self.log("MySQL driver executing {}".format(", ".join(args))) - return self._cur.execute(*args) - - def create(self, udb): - self.execute("CREATE DATABASE IF NOT EXISTS {0.database}".format(udb)) - self.fix_grants(udb) - - def drop(self, udb): - self.execute("DROP DATABASE IF EXISTS {0.database}".format(udb)) - - def script_drop(self, udb): - self.args.script_output.write("DROP DATABASE IF EXISTS {};\n".format(udb.database)) - - def fix_grants(self, udb): - self.execute("GRANT ALL ON {0.database}.* TO {0.username}@localhost IDENTIFIED BY %s".format(udb), - (udb.password,)) - -class SQLite3_Driver(Abstract_Driver): - - def __init__(self, args): - try: - self.driver - except AttributeError: - import sqlite3 - self.driver = sqlite3 - self.args = args - - def _db_accessible_test(self, udb): - self.driver.connect(udb.database).close() - - def db_exists(self, udb): - return os.path.exists(udb.database) - - def _grant(self, udb): - if udb.username and os.geteuid() == 0: - pw = pwd.getpwnam(udb.username) - os.chown(udb.database, pw.pw_uid, pw.pw_gid) - - def create(self, udb): - self._db_accessible_test(udb.database) - self._grant(udb) - - def drop(self, udb): - os.unlink(udb.database) - - def script_drop(self, udb): - self.args.script_output.write("rm {}\n".format(udb.database)) - - def fix_grants(self, udb): - self._grant(udb) - - -class PostgreSQL_Driver(Abstract_Driver): - - def __init__(self, args): - try: - self.driver - except AttributeError: - import psycopg2 - self.driver = psycopg2 - self.args = args - if args.postgresql_root_username and (os.getuid() == 0 or os.geteuid() == 0): - self._pw = pwd.getpwnam(args.postgresql_root_username) - else: - self._pw = None - self.log("Initialized PostgreSQL driver, pw {!r}".format(self._pw)) - - def _seteuid(self, new_uid): - old_uid = os.geteuid() - if new_uid != old_uid: - self.log("PostgreSQL driver changing EUID from {} to {}".format(old_uid, new_uid)) - os.seteuid(new_uid) - return old_uid - - def execute(self, *args): - try: - self._cur - except AttributeError: - self.log("PostgreSQL driver opening connection to database {}".format(self.args.postgresql_root_database)) - if self._pw is not None: - euid = self._seteuid(self._pw.pw_uid) - try: - self._db = self.driver.connect(database = self.args.postgresql_root_database) - self._db.autocommit = True - self._cur = self._db.cursor() - finally: - if self._pw is not None: - self._seteuid(euid) - self.log("PostgreSQL driver executing {}".format(", ".join(args))) - return self._cur.execute(*args) - - def _db_accessible_test(self, udb): - pw = pwd.getpwnam(udb.username) - uid = self._seteuid(pw.pw_uid) - try: - self.driver.connect(database = udb.database, user = udb.username , password = usb.password).close() - finally: - self._seteuid(uid) - - def _role_in_use(self, udb): - self.execute('''\ - SELECT COUNT(*) FROM pg_database - JOIN pg_roles ON pg_database.datdba = pg_roles.oid - WHERE pg_roles.rolname = %s''', (udb.username,)) - return bool(self.fetchone()[0]) - - def create(self, udb): - self.execute('''\ - DO $$ BEGIN - IF NOT EXISTS (SELECT * FROM pg_catalog.pg_roles - WHERE rolname = '{0.username}') - THEN - CREATE ROLE {0.username} LOGIN PASSWORD '{0.password}'; - END IF; - END $$'''.format(udb)) - self.execute("CREATE DATABASE {0.database} OWNER {0.username}".format(udb)) - - def drop(self, udb): - self.execute("DROP DATABASE IF EXISTS {0.database}".format(udb)) - if not self._role_in_use(udb): - self.execute("DROP ROLE IF EXISTS {0.username}".format(udb)) - - def script_drop(self, udb): - self.args.script_output.write(textwrap.dedent('''\ - DROP DATABASE IF EXISTS {0.database}; - DO $$ BEGIN - IF NOT EXISTS (SELECT * FROM pg_database JOIN pg_roles - ON pg_database.datdba = pg_roles.oid - WHERE pg_roles.rolname = '{0.username}') - THEN - DROP ROLE IF EXISTS {0.username}; - END IF; - END $$; - '''.format(udb))) - - def fix_grants(self, udb): - self.execute("ALTER DATABASE {0.database} OWNER TO {0.username}".format(udb)) - self.execute("ALTER ROLE {0.username} WITH PASSWORD '{0.password}".format(udb)) - - -class UserDB(object): - """ - Class to wrap access parameters for a particular database. - """ - - drivers = dict(sqlite3 = SQLite3_Driver, - mysql = MySQL_Driver, - postgresql = PostgreSQL_Driver) - - def __init__(self, args, name): - self.database = cfg.get("sql-database", section = name) - self.username = cfg.get("sql-username", section = name) - self.password = cfg.get("sql-password", section = name) - self.engine = cfg.get("sql-engine", section = name) - self.driver = self.drivers[self.engine](args) - self.args = args - - def drop(self): - if self.args.force or self.driver.db_accessible(self): - self.driver.drop(self) - - def create(self): - if self.args.force or not self.driver.db_accessible(self): - self.driver.create(self) - - def script_drop(self): - self.driver.script_drop(self) - - def drop_and_create(self): - if self.args.force or self.driver.db_accessible(self): - self.driver.drop(self) - self.driver.create(self) - - def fix_grants(self): - if self.args.force or not self.driver.db_accessible(self): - self.driver.fix_grants(self) - - -parser = argparse.ArgumentParser(description = __doc__) -parser.add_argument("-c", "--config", - help = "specify alternate location for rpki.conf") -parser.add_argument("-d", "--debug", action = "store_true", - help = "enable debugging (eg, Python backtraces)") -parser.add_argument("-v", "--verbose", action = "store_true", - help = "whistle while you work") -parser.add_argument("-f", "--force", action = "store_true", - help = "force database create, drop, or grant regardless of current state") - -parser.add_argument("--mysql-defaults", - help = "specify MySQL root access credentials via a configuration file") - - -parser.add_argument("--postgresql-root-database", default = "postgres", - help = "name of PostgreSQL control database") -parser.add_argument("--postgresql-root-username", - help = "username of PostgreSQL control role") - -subparsers = parser.add_subparsers(title = "Commands", metavar = "", dest = "dispatch") - -subparsers.add_parser("create", - help = "create databases and load schemas") - -subparsers.add_parser("drop", - help = "drop databases") - -subparser = subparsers.add_parser("script-drop", - help = "show SQL commands to drop databases") -subparser.add_argument("script_output", - nargs = "?", type = argparse.FileType("w"), default = "-", - help = "destination for drop script") - -subparsers.add_parser("drop-and-create", - help = "drop databases then recreate them and load schemas") - -subparsers.add_parser("fix-grants", - help = "whack database to match configuration file") - -args = parser.parse_args() - -try: - - cfg = rpki.config.parser(set_filename = args.config, section = "myrpki") - - names = [name for name in ("irdbd", "rpkid", "pubd") - if cfg.getboolean("start_" + name, False)] - names.append("rcynic") - - # For now, we quietly ignore missing sections rather than throwing an exception. - # I could make a case either way for this, but ignoring missing sections is a - # lot easier to clean up while debugging the installation scripts. - - for name in names: - if cfg.has_section(name): - udb = UserDB(args = args, name = name) - method = args.dispatch.replace("-", "_") - getattr(udb, method)() - -except Exception, e: - if args.debug: - raise - else: - sys.exit(str(e)) diff --git a/ca/rpki-start-servers b/ca/rpki-start-servers index 9bf47d0c..26068bc7 100755 --- a/ca/rpki-start-servers +++ b/ca/rpki-start-servers @@ -69,7 +69,8 @@ cfg = rpki.config.parser(set_filename = args.config, section = "myrpki") def run(name, old_flag = None): if cfg.getboolean("start_" + name, cfg.getboolean("run_" + name if old_flag is None else old_flag, False)): log_file = os.path.join(args.log_directory, name + ".log") - cmd = (os.path.join(rpki.autoconf.libexecdir, name), "--log-level", args.log_level) + cmd = (rpki.autoconf.SUDO, "-u", rpki.autoconf.RPKI_USER, + os.path.join(rpki.autoconf.libexecdir, name), "--log-level", args.log_level) if args.log_file: cmd += ("--log-file", log_file) elif args.log_rotating_file_kbytes: diff --git a/ca/rpkic b/ca/rpkic index 3c3c7d99..5858014c 100755 --- a/ca/rpkic +++ b/ca/rpkic @@ -1,21 +1,25 @@ #!/usr/bin/env python -# $Id$ +# Using a Python script to run sudo to run a Python script is a bit +# silly, but it lets us use rpki.autoconf to locate sudo, lets us +# avoid needing a custom setuid wrapper, lets us avoid another pass +# through the adventures of shell quoting and tokenization, and +# generally is just a lot simpler to implement correctly. # -# Copyright (C) 2010-2011 Internet Systems Consortium ("ISC") -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS. IN NO EVENT SHALL ISC 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. +# OK, it's probably a few milliseconds slower. Big deal. if __name__ == "__main__": - import rpki.rpkic - rpki.rpkic.main() + + try: + import os + import sys + import rpki.autoconf + + argv = [rpki.autoconf.SUDO, "-u", rpki.autoconf.RPKI_USER, + sys.executable, "-c", "import rpki.rpkic; rpki.rpkic.main()"] + + os.execv(rpki.autoconf.SUDO, argv + sys.argv[1:]) + sys.exit("rpkic startup failure, no exception so don't know why, sorry") + + except Exception as e: + sys.exit("Couldn't exec sudo python rpkic: {!s}".format(e)) diff --git a/ca/upgrade-scripts/upgrade-rpkid-to-0.5709.py b/ca/upgrade-scripts/upgrade-rpkid-to-0.5709.py deleted file mode 100644 index 0cea5671..00000000 --- a/ca/upgrade-scripts/upgrade-rpkid-to-0.5709.py +++ /dev/null @@ -1,40 +0,0 @@ -# $Id$ -# -# Copyright (C) 2014 Dragon Research Labs ("DRL") -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND DRL DISCLAIMS ALL WARRANTIES WITH -# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -# AND FITNESS. IN NO EVENT SHALL DRL 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. - -# pylint: disable=E0602 - -""" -Upgrade RPKI SQL databases to schema expected by 0.5709. - -This code is evaluated in the context of rpki-sql-setup's -do_apply_upgrades() function and has access to its variables. -""" - -db.cur.execute(""" - CREATE TABLE ee_cert ( - ee_cert_id SERIAL NOT NULL, - ski BINARY(20) NOT NULL, - cert LONGBLOB NOT NULL, - published DATETIME, - self_id BIGINT UNSIGNED NOT NULL, - ca_detail_id BIGINT UNSIGNED NOT NULL, - PRIMARY KEY (ee_cert_id), - CONSTRAINT ee_cert_self_id - FOREIGN KEY (self_id) REFERENCES self (self_id) ON DELETE CASCADE, - CONSTRAINT ee_cert_ca_detail_id - FOREIGN KEY (ca_detail_id) REFERENCES ca_detail (ca_detail_id) ON DELETE CASCADE - ) ENGINE=InnoDB -""") diff --git a/configure.ac b/configure.ac index 0d06dd5d..23f92564 100644 --- a/configure.ac +++ b/configure.ac @@ -138,6 +138,7 @@ AC_PATH_PROG([SORT], [sort]) AC_PATH_PROG([RRDTOOL], [rrdtool]) AC_PATH_PROG([TRANG], [trang], [\${abs_top_srcdir}/buildtools/trang-not-found]) AC_PATH_PROG([RSYNC], [rsync]) +AC_PATH_PROG([SUDO], [sudo]) # See whether we need to check for dependencies that we only need at # runtime. We do this by default when compiling from source to avoid @@ -384,7 +385,7 @@ case $enable_rcynic_jail in RCYNIC_CONF_RSYNC="${RSYNC}" RCYNIC_CONF_DATA="${rcynic_base_dir}/data" RCYNIC_CONF_TA_DIR='${sysconfdir}/rpki/trust-anchors' - RCYNIC_CRON_USER='${RCYNIC_USER}' + RCYNIC_CRON_USER='${RPKI_USER}' RCYNIC_JAIL_DIRS='' ;; *) @@ -406,8 +407,8 @@ AC_MSG_RESULT([$use_rcynic_jail]) # Perhaps there should be a way to set these, but for now just # wire them in here so at least they're consistent in all Makefiles. -AC_SUBST(RCYNIC_USER, [rcynic]) -AC_SUBST(RCYNIC_GROUP, [rcynic]) +AC_SUBST(RPKI_USER, [rpki]) +AC_SUBST(RPKI_GROUP, [rpki]) if test $use_rcynic_jail = yes && test "X$LD_STATIC_FLAG" != "X" then @@ -487,10 +488,13 @@ AC_SUBST(RCYNIC_HTML_DIR) # Sort out which things to install, depending on rcynic jail status and whether # we're doing final target installation. +# +# As things have evolved, this a bit repetitive. Simplify someday, maybe. RCYNIC_INSTALL_TARGETS='install-always' RTR_ORIGIN_INSTALL_TARGETS='install-always' CA_INSTALL_TARGETS='install-always' +CFG_INSTALL_TARGETS='install-always' if test $use_rcynic_jail = yes then @@ -502,11 +506,13 @@ then RCYNIC_INSTALL_TARGETS="$RCYNIC_INSTALL_TARGETS install-postconf" RTR_ORIGIN_INSTALL_TARGETS="$RTR_ORIGIN_INSTALL_TARGETS install-postconf" CA_INSTALL_TARGETS="$CA_INSTALL_TARGETS install-postconf" + CFG_INSTALL_TARGETS="$CFG_INSTALL_TARGETS install-postconf" fi AC_SUBST(RCYNIC_INSTALL_TARGETS) AC_SUBST(RTR_ORIGIN_INSTALL_TARGETS) AC_SUBST(CA_INSTALL_TARGETS) +AC_SUBST(CFG_INSTALL_TARGETS) # Now a bunch of checks to figure out what we can do with Python. If # we don't have Python at all, none of the rest of this matters. If diff --git a/rp/Makefile.in b/rp/Makefile.in index 2c770a46..d22ddbcb 100644 --- a/rp/Makefile.in +++ b/rp/Makefile.in @@ -1,6 +1,6 @@ # $Id$ -SUBDIRS = rcynic rpki-rtr utils +SUBDIRS = config rcynic rpki-rtr utils all clean test distclean install deinstall uninstall:: @for i in ${SUBDIRS}; do echo "Making $@ in $$i"; (cd $$i && ${MAKE} $@); done diff --git a/rp/config/Makefile.in b/rp/config/Makefile.in new file mode 100644 index 00000000..40d0a882 --- /dev/null +++ b/rp/config/Makefile.in @@ -0,0 +1,88 @@ +# $Id$ + +PYTHON = @PYTHON@ + +INSTALL = @INSTALL@ -m 555 + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datarootdir = @datarootdir@ +datadir = @datadir@ +localstatedir = @localstatedir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +sysconfdir = @sysconfdir@ + +abs_builddir = @abs_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +abs_top_builddir= @abs_top_builddir@ +srcdir = @srcdir@ + +CFG_INSTALL_TARGETS = @CFG_INSTALL_TARGETS@ + +all:: rpki.rp.xml rpki.rp.sample.conf + +clean:: + cd tests; $(MAKE) $@ + +install:: ${CFG_INSTALL_TARGETS} + +install-always:: all + @echo + @echo "== Default configuration file location is ${sysconfdir}/rpki.conf ==" + @echo + ${INSTALL} -d ${DESTDIR}${sysconfdir}/rpki + ${INSTALL} rpki.rp.xml rpki.rp.sample.conf ${DESTDIR}${sysconfdir}/rpki + +test uninstall deinstall:: + @true + +distclean:: clean + rm -f Makefile + +rpki.rp.xml: ${abs_top_srcdir}/rpki/autoconf.py rpki-confgen rpki-confgen.xml + ${PYTHON} rpki-confgen \ + --read-xml rpki-confgen.xml \ + --autoconf \ + --set myrpki::handle=`hostname -f | sed 's/[.]/_/g'` \ + --set myrpki::rpkid_server_host=`hostname -f` \ + --set myrpki::pubd_server_host=`hostname -f` \ + --pwgen myrpki::shared_sql_password \ + --pwgen web_portal::secret-key \ + --set myrpki::run_rpkid=no \ + --set myrpki::run_pubd=no \ + --write-xml $@ + +rpki.rp.sample.conf: rpki.rp.xml + ${PYTHON} rpki-confgen \ + --read-xml rpki.rp.xml \ + --write-conf $@ + +clean:: + rm -f rpki.rp.xml rpki.rp.sample.conf + +install-postconf: \ + install-user install-conf install-sql install-django + +# This should create user "rpki" and group "rpki", but rcynic already +# does that...but we probably need to do it here instead, bother. + +install-user: + @true + +install-conf: + test -f ${DESTDIR}${sysconfdir}/rpki.conf ||\ + cp -p ${DESTDIR}${sysconfdir}/rpki/rpki.rp.sample.conf ${DESTDIR}${sysconfdir}/rpki.conf + +#uninstall deinstall:: +# rm -f ${DESTDIR}${sysconfdir}/rpki/rpki.rp.xml ${DESTDIR}${sysconfdir}/rpki/rpki.rp.sample.conf + +install-sql: + ${sbindir}/rpki-sql-setup create + +install-django: + ${sbindir}/rpki-manage syncdb --noinput + ${sbindir}/rpki-manage migrate app diff --git a/rp/config/rpki-confgen b/rp/config/rpki-confgen new file mode 100755 index 00000000..e6780446 --- /dev/null +++ b/rp/config/rpki-confgen @@ -0,0 +1,282 @@ +#!/usr/bin/env python + +# $Id$ +# +# Copyright (C) 2014 Dragon Research Labs ("DRL") +# Portions copyright (C) 2013 Internet Systems Consortium ("ISC") +# +# 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 DRL AND ISC DISCLAIM ALL +# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DRL OR +# ISC 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. + +import os +import sys +import argparse +import base64 +import textwrap + +from lxml.etree import Element, SubElement, ElementTree, Comment + +space4 = " " * 4 +space6 = " " * 6 +space8 = " " * 8 +star78 = "*" * 78 + +wiki_wrapper = textwrap.TextWrapper() +conf_wrapper = textwrap.TextWrapper(initial_indent = "# ", subsequent_indent = "# ") +xml6_wrapper = textwrap.TextWrapper(initial_indent = space6, subsequent_indent = space6) +xml8_wrapper = textwrap.TextWrapper(initial_indent = space8, subsequent_indent = space8) + +class Option(object): + + def __init__(self, name, value, doc): + self.name = name + self.value = value + self.doc = doc + + @property + def width(self): + return len(self.name) + + def to_xml(self): + x = Element("option", name = self.name) + if self.value is not None: + x.set("value", self.value) + for d in self.doc: + SubElement(x, "doc").text = "\n" + xml8_wrapper.fill(d) + "\n" + space6 + return x + + def to_wiki(self, f): + f.write("\n== {0.name} == #{0.name}\n".format(self)) + for d in self.doc: + f.write("\n{0}\n".format(wiki_wrapper.fill(d))) + if self.value is None: + f.write("\n{0}\n".format(wiki_wrapper.fill("No default value."))) + else: + f.write("\n{{{{{{\n#!ini\n{0.name} = {0.value}\n}}}}}}\n".format(self)) + + def to_conf(self, f, width): + for i, d in enumerate(self.doc): + f.write("{}\n{}\n".format("" if i == 0 else "#", + conf_wrapper.fill(d))) + if self.value is None: + f.write("\n#{1.name:{0}} = ???\n".format(width - 1, self)) + else: + f.write("\n{1.name:{0}} = {1.value}\n".format(width, self)) + +class Section(object): + + def __init__(self, name): + self.name = name + self.doc = [] + self.options = [] + + @property + def width(self): + return max(o.width for o in self.options) + + @classmethod + def from_xml(cls, elt): + self = cls(name = elt.get("name")) + for x in elt.iterchildren("doc"): + self.doc.append(" ".join(x.text.split())) + for x in elt.iterchildren("option"): + self.options.append(Option(name = x.get("name"), value = x.get("value"), + doc = [" ".join(d.text.split()) + for d in x.iterchildren("doc")])) + return self + + def to_xml(self): + x = Element("section", name = self.name) + for d in self.doc: + SubElement(x, "doc").text = "\n" + xml6_wrapper.fill(d) + "\n" + space4 + x.extend(o.to_xml() for o in self.options) + return x + + def to_wiki(self, f): + f.write("\n= [{0}] section = #{0}\n".format(self.name)) + for d in self.doc: + f.write("\n{0}\n".format(wiki_wrapper.fill(d))) + for o in self.options: + o.to_wiki(f) + + def to_conf(self, f, width): + f.write("\n" + "#" * 78 + "\n\n[" + self.name + "]\n") + if self.doc: + f.write("\n##") + for i, d in enumerate(self.doc): + f.write("{}\n{}\n".format("" if i == 0 else "#", + conf_wrapper.fill(d))) + f.write("##\n") + for o in self.options: + o.to_conf(f, width) + +def wiki_header(f, ident, toc): + f.write(textwrap.dedent('''\ + {{{{{{ + #!comment + + {star78} + THIS PAGE WAS GENERATED AUTOMATICALLY, DO NOT EDIT. + + Generated from {ident} + by $Id$ + {star78} + + }}}}}} + '''.format(star78 = star78, + ident = ident))) + if toc is not None: + f.write("[[TracNav({})]]\n".format(toc)) + f.write("[[PageOutline]]\n") + +def conf_header(f, ident): + f.write(textproc.dedent('''\ + # Automatically generated. Edit as needed, but be careful of overwriting. + # + # Generated from {ident} + # by $Id$ + + '''.format(ident = ident))) + + +# http://stackoverflow.com/questions/9027028/argparse-argument-order + +class CustomAction(argparse.Action): + + def __call__(self, parser, namespace, values, option_string = None): + if not "ordered_args" in namespace: + namespace.ordered_args = [] + namespace.ordered_args.append((self.dest, values)) + +class CustomFlagAction(CustomAction): + + def __init__(self, option_strings, dest, default = None, + required = False, help = None): # pylint: disable=W0622 + super(CustomFlagAction, self).__init__( + option_strings = option_strings, + dest = dest, + nargs = 0, + const = None, + default = default, + required = required, + help = help) + + +class main(object): + + def __init__(self): + self.sections = [] + self.section_map = None + self.option_map = None + self.ident = None + self.toc = None + + parser = argparse.ArgumentParser(description = __doc__) + parser.add_argument("--read-xml", type = argparse.FileType("r"), metavar = "FILE", action = CustomAction, help = "XML input file defining sections and options", required = True) + parser.add_argument("--write-xml", type = argparse.FileType("w"), metavar = "FILE", action = CustomAction, help = "XML output file to snapshot configuration") + parser.add_argument("--write-conf", type = argparse.FileType("w"), metavar = "FILE", action = CustomAction, help = "rpki.conf configuration file to write") + parser.add_argument("--write-wiki", type = argparse.FileType("w"), metavar = "FILE", action = CustomAction, help = "TracWiki file to write (monolithic)") + parser.add_argument("--write-wiki-pages", metavar = "PATTERN", action = CustomAction, help = "TracWiki filenames (pattern) to write (one section per page)") + parser.add_argument("--set", metavar = "VARVAL", action = CustomAction, help = "variable setting in form \"VAR=VAL\"") + parser.add_argument("--pwgen", metavar = "VAR", action = CustomAction, help = "set variable to generated password") + parser.add_argument("--toc", metavar = "TOCVAL", action = CustomAction, help = "set TOC value to use with TracNav plugin") + parser.add_argument("--autoconf", action = CustomFlagAction, help = "configure [autoconf] section") + args = parser.parse_args() + + for cmd, arg in args.ordered_args: + getattr(self, "do_" + cmd)(arg) + + def do_read_xml(self, arg): + self.option_map = None + root = ElementTree(file = arg).getroot() + self.ident = root.get("ident") + self.sections.extend(Section.from_xml(x) for x in root) + self.option_map = {} + self.section_map = {} + for section in self.sections: + if section.name in self.section_map: + sys.exit("Duplicate section {}".format(section.name)) + self.section_map[section.name] = section + for option in section.options: + name = (section.name, option.name) + if name in self.option_map: + sys.exit("Duplicate option {}::{}".format(*name)) + self.option_map[name] = option + + def do_set(self, arg): + try: + name, value = arg.split("=", 1) + section, option = name.split("::") + except ValueError: + sys.exit("Couldn't parse --set specification \"{}\"".format(arg)) + name = (section, option) + if name not in self.option_map: + sys.exit("Couldn't find option {}::{}".format(*name)) + self.option_map[name].value = value + + def do_pwgen(self, arg): + try: + section, option = arg.split("::") + except ValueError: + sys.exit("Couldn't parse --pwgen specification \"{}\"".format(arg)) + name = (section, option) + if name not in self.option_map: + sys.exit("Couldn't find option {}::{}".format(name)) + self.option_map[name].value = base64.urlsafe_b64encode(os.urandom(66)) + + def do_autoconf(self, ignored): + try: + import rpki.autoconf + for option in self.section_map["autoconf"].options: + try: + option.value = getattr(rpki.autoconf, option.name) + except AttributeError: + pass + except ImportError: + sys.exit("rpki.autoconf module is not available") + except KeyError: + sys.exit("Couldn't find autoconf section") + + def do_write_xml(self, arg): + x = Element("configuration", ident = self.ident) + x.append(Comment(" Machine-editable configuration snapshot, generated automatically, do not touch ")) + x.extend(s.to_xml() for s in self.sections) + ElementTree(x).write(arg, pretty_print = True, encoding = "us-ascii") + + def do_write_wiki(self, arg): + for i, section in enumerate(self.sections): + if i == 0: + wiki_header(arg, self.ident, self.toc) + else: + arg.write("\f\n") + section.to_wiki(arg) + + def do_write_wiki_pages(self, arg): + for section in self.sections: + with open(arg % section.name, "w") as f: + wiki_header(f, self.ident, self.toc) + section.to_wiki(f) + + def do_write_conf(self, arg): + with open(arg, "w") as f: + conf_header(f, self.ident) + width = max(s.width for s in self.sections) + for section in self.sections: + section.to_conf(f, width) + + def do_toc(self, arg): + self.toc = arg + + +if __name__ == "__main__": + main() diff --git a/rp/config/rpki-confgen.xml b/rp/config/rpki-confgen.xml new file mode 100644 index 00000000..1b86a140 --- /dev/null +++ b/rp/config/rpki-confgen.xml @@ -0,0 +1,1111 @@ + + + + +
+ + + The "`[myrpki]`" section contains all the parameters that you + really need to configure. The name "`myrpki`" is historical and + may change in the future. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + rcynicng, unlike it's predecessor, uses the same `rpki.conf` + file as all the other programs in the RPKI toolkit. Start + rcynicng with "`-c filename`" to choose a different + configuration file. All options are in the "`[rcynic]`" + section. + + + + This section isn't really fleshed out yet, and just contains the + settings needed for the new SQL code to work. This will change + as the stuff that's currently only configurable on rcynicng's + command line becomes integrated with the configuration file. + + + + + + + + + + +
+ +
+ + + rpkid's default config file is the system `rpki.conf` file. + Start rpkid with "`-c filename`" to choose a different config + file. All options are in the "`[rpkid]`" section. BPKI + Certificates and keys may be in either DER or PEM format. + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + irdbd's default configuration file is the system `rpki.conf` + file. Start irdbd with "`-c filename`" to choose a different + configuration file. All options are in the "`[irdbd]`" section. + + + + Since irdbd is part of the back-end system, it has direct access to + the back-end's SQL database, and thus is able to pull its own BPKI + configuration directly from the database, and thus needs a bit less + configuration than the other daemons. + + + + + + + + + + + + + + + + +
+ +
+ + + pubd's default configuration file is the system `rpki.conf` + file. Start pubd with "`-c filename`" to choose a different + configuration file. All options are in the "`[pubd]`" section. + BPKI certificates and keys may be either DER or PEM format. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + You don't need to run rootd unless you're IANA, are certifying + private address space, or are an RIR which refuses to accept IANA as + the root of the public address hierarchy. + + + + Ok, if that wasn't enough to scare you off: rootd is a mess, + needs to be rewritten, or, better, merged into rpkid, and + requires far too many configuration parameters. + + + + rootd was originally intended to be a very simple program which + simplified rpkid enormously by moving one specific task (acting + as the root CA of an RPKI certificate hierarchy) out of rpkid. + As the specifications and code (mostly the latter) have evolved, + however, this task has become more complicated, and rootd would + have to become much more complicated to keep up. + + + + Don't run rootd unless you're sure that you need to do so. + + + + Still think you need to run rootd? OK, but remember, you have + been warned.... + + + + rootd's default configuration file is the system `rpki.conf` + file. Start rootd with "`-c filename`" to choose a different + configuration file. All options are in the "`[rootd]`" section. + Certificates and keys may be in either DER or PEM format. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + Glue to allow Django to pull user configuration from this file + rather than requiring the user to edit settings.py. + + + + + + + + + + +
+ +
+ + + rpki-confgen --autoconf records the current autoconf settings + here, so that other options can refer to them. The section name + "autoconf" is magic, don't change it. + + + + + + + + + + +
+ +
diff --git a/rp/config/rpki-manage b/rp/config/rpki-manage new file mode 100755 index 00000000..16d0990d --- /dev/null +++ b/rp/config/rpki-manage @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +import os + +# django-admin seems to have problems creating the superuser account when +# $LANG is unset or is set to something totally incompatible with UTF-8. + +if os.environ.get("LANG") in (None, "", "C"): + os.environ["LANG"] = "en_US.UTF-8" + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "rpki.django_settings.gui") + +from django.core.management import execute_from_command_line + +execute_from_command_line() diff --git a/rp/config/rpki-sql-backup b/rp/config/rpki-sql-backup new file mode 100755 index 00000000..986e10b1 --- /dev/null +++ b/rp/config/rpki-sql-backup @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +# $Id$ +# +# Copyright (C) 2014 Dragon Research Labs ("DRL") +# Portions copyright (C) 2010-2013 Internet Systems Consortium ("ISC") +# +# 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 DRL AND ISC DISCLAIM ALL +# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DRL OR +# ISC 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. + +""" +Back up data from SQL databases, looking at config file to figure out +which databases and what credentials to use with them. +""" + +import subprocess +import os +import argparse +import sys +import time +import rpki.config + +os.environ["TZ"] = "UTC" +time.tzset() + +parser = argparse.ArgumentParser(description = __doc__) +parser.add_argument("-c", "--config", + help = "override default location of configuration file") +parser.add_argument("-o", "--output", + type = argparse.FileType("wb"), default = sys.stdout, + help = "destination for SQL dump (default: stdout)") +args = parser.parse_args() + +cfg = rpki.config.parser(set_filename = args.config, section = "myrpki") + +for name in ("rpkid", "irdbd", "pubd"): + if cfg.getboolean("start_" + name, False): + subprocess.check_call( + ("mysqldump", "--add-drop-database", + "-u", cfg.get("sql-username", section = name), + "-p" + cfg.get("sql-password", section = name), + "-B", cfg.get("sql-database", section = name)), + stdout = args.output) diff --git a/rp/config/rpki-sql-setup b/rp/config/rpki-sql-setup new file mode 100755 index 00000000..c72c97c5 --- /dev/null +++ b/rp/config/rpki-sql-setup @@ -0,0 +1,348 @@ +#!/usr/bin/env python + +# $Id$ +# +# Copyright (C) 2014 Dragon Research Labs ("DRL") +# Portions copyright (C) 2009-2013 Internet Systems Consortium ("ISC") +# +# 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 DRL AND ISC DISCLAIM ALL +# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DRL OR +# ISC 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. + +""" +Automated setup of SQL stuff used by the RPKI tools. Pulls +configuration from rpki.conf, prompts for SQL password when needed. +""" + +import os +import pwd +import sys +import getpass +import textwrap +import argparse +import rpki.config + + +class Abstract_Driver(object): + + # Kludge to make classes derived from this into singletons. Net + # of a Million Lies says this is Not Pythonic, but it seems to + # work, so long as one doesn't attempt to subclass the resulting + # driver classes. For our purposes, it will do. + + __instance = None + + def __new__(cls, *args, **kwargs): + if cls.__instance is None: + cls.__instance = object.__new__(cls, *args, **kwargs) + return cls.__instance + + def db_accessible(self, udb): + try: + self._db_accessible_test(udb) + except: + return False + else: + return True + + def db_exists(self, udb): + self.execute("SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = %s", (udb.database,)) + return bool(self.fetchone()[0]) + + def fetchone(self): + return self._cur.fetchone() + + def fetchall(self): + return self._cur.fetchall() + + def close(self): + self._cur.close() + self._db.close() + + def log(self, msg): + if self.args.verbose: + sys.stderr.write(msg + "\n") + + +class MySQL_Driver(Abstract_Driver): + + _initialized = False + + def __init__(self, args): + try: + self.driver + except AttributeError: + from rpki.mysql_import import MySQLdb + self.driver = MySQLdb + self.args = args + + def _db_accessible_test(self, udb): + self.driver.connect(db = udb.database, user = udb.username, passwd = udb.password).close() + + def execute(*args): + try: + self._cur + except AttributeError: + self.log("MySQL driver initializing root connection") + if self.args.mysql_defaults: + mysql_cfg = rpki.config.parser(set_filename = self.args.mysql_defaults, section = "client") + self._db = self.driver.connect(db = "mysql", + user = mysql_cfg.get("user"), + passwd = mysql_cfg.get("password")) + else: + self._db = self.driver.connect(db = "mysql", + user = "root", + passwd = getpass.getpass("Please enter your MySQL root password: ")) + self._db.autocommit(True) + self._cur = self._db.cursor() + self.log("MySQL driver executing {}".format(", ".join(args))) + return self._cur.execute(*args) + + def create(self, udb): + self.execute("CREATE DATABASE IF NOT EXISTS {0.database}".format(udb)) + self.fix_grants(udb) + + def drop(self, udb): + self.execute("DROP DATABASE IF EXISTS {0.database}".format(udb)) + + def script_drop(self, udb): + self.args.script_output.write("DROP DATABASE IF EXISTS {};\n".format(udb.database)) + + def fix_grants(self, udb): + self.execute("GRANT ALL ON {0.database}.* TO {0.username}@localhost IDENTIFIED BY %s".format(udb), + (udb.password,)) + +class SQLite3_Driver(Abstract_Driver): + + def __init__(self, args): + try: + self.driver + except AttributeError: + import sqlite3 + self.driver = sqlite3 + self.args = args + + def _db_accessible_test(self, udb): + self.driver.connect(udb.database).close() + + def db_exists(self, udb): + return os.path.exists(udb.database) + + def _grant(self, udb): + if udb.username and os.geteuid() == 0: + pw = pwd.getpwnam(udb.username) + os.chown(udb.database, pw.pw_uid, pw.pw_gid) + + def create(self, udb): + self._db_accessible_test(udb.database) + self._grant(udb) + + def drop(self, udb): + os.unlink(udb.database) + + def script_drop(self, udb): + self.args.script_output.write("rm {}\n".format(udb.database)) + + def fix_grants(self, udb): + self._grant(udb) + + +class PostgreSQL_Driver(Abstract_Driver): + + def __init__(self, args): + try: + self.driver + except AttributeError: + import psycopg2 + self.driver = psycopg2 + self.args = args + if args.postgresql_root_username and (os.getuid() == 0 or os.geteuid() == 0): + self._pw = pwd.getpwnam(args.postgresql_root_username) + else: + self._pw = None + self.log("Initialized PostgreSQL driver, pw {!r}".format(self._pw)) + + def _seteuid(self, new_uid): + old_uid = os.geteuid() + if new_uid != old_uid: + self.log("PostgreSQL driver changing EUID from {} to {}".format(old_uid, new_uid)) + os.seteuid(new_uid) + return old_uid + + def execute(self, *args): + try: + self._cur + except AttributeError: + self.log("PostgreSQL driver opening connection to database {}".format(self.args.postgresql_root_database)) + if self._pw is not None: + euid = self._seteuid(self._pw.pw_uid) + try: + self._db = self.driver.connect(database = self.args.postgresql_root_database) + self._db.autocommit = True + self._cur = self._db.cursor() + finally: + if self._pw is not None: + self._seteuid(euid) + self.log("PostgreSQL driver executing {}".format(", ".join(args))) + return self._cur.execute(*args) + + def _db_accessible_test(self, udb): + pw = pwd.getpwnam(udb.username) + uid = self._seteuid(pw.pw_uid) + try: + self.driver.connect(database = udb.database, user = udb.username , password = usb.password).close() + finally: + self._seteuid(uid) + + def _role_in_use(self, udb): + self.execute('''\ + SELECT COUNT(*) FROM pg_database + JOIN pg_roles ON pg_database.datdba = pg_roles.oid + WHERE pg_roles.rolname = %s''', (udb.username,)) + return bool(self.fetchone()[0]) + + def create(self, udb): + self.execute('''\ + DO $$ BEGIN + IF NOT EXISTS (SELECT * FROM pg_catalog.pg_roles + WHERE rolname = '{0.username}') + THEN + CREATE ROLE {0.username} LOGIN PASSWORD '{0.password}'; + END IF; + END $$'''.format(udb)) + self.execute("CREATE DATABASE {0.database} OWNER {0.username}".format(udb)) + + def drop(self, udb): + self.execute("DROP DATABASE IF EXISTS {0.database}".format(udb)) + if not self._role_in_use(udb): + self.execute("DROP ROLE IF EXISTS {0.username}".format(udb)) + + def script_drop(self, udb): + self.args.script_output.write(textwrap.dedent('''\ + DROP DATABASE IF EXISTS {0.database}; + DO $$ BEGIN + IF NOT EXISTS (SELECT * FROM pg_database JOIN pg_roles + ON pg_database.datdba = pg_roles.oid + WHERE pg_roles.rolname = '{0.username}') + THEN + DROP ROLE IF EXISTS {0.username}; + END IF; + END $$; + '''.format(udb))) + + def fix_grants(self, udb): + self.execute("ALTER DATABASE {0.database} OWNER TO {0.username}".format(udb)) + self.execute("ALTER ROLE {0.username} WITH PASSWORD '{0.password}".format(udb)) + + +class UserDB(object): + """ + Class to wrap access parameters for a particular database. + """ + + drivers = dict(sqlite3 = SQLite3_Driver, + mysql = MySQL_Driver, + postgresql = PostgreSQL_Driver) + + def __init__(self, args, name): + self.database = cfg.get("sql-database", section = name) + self.username = cfg.get("sql-username", section = name) + self.password = cfg.get("sql-password", section = name) + self.engine = cfg.get("sql-engine", section = name) + self.driver = self.drivers[self.engine](args) + self.args = args + + def drop(self): + if self.args.force or self.driver.db_accessible(self): + self.driver.drop(self) + + def create(self): + if self.args.force or not self.driver.db_accessible(self): + self.driver.create(self) + + def script_drop(self): + self.driver.script_drop(self) + + def drop_and_create(self): + if self.args.force or self.driver.db_accessible(self): + self.driver.drop(self) + self.driver.create(self) + + def fix_grants(self): + if self.args.force or not self.driver.db_accessible(self): + self.driver.fix_grants(self) + + +parser = argparse.ArgumentParser(description = __doc__) +parser.add_argument("-c", "--config", + help = "specify alternate location for rpki.conf") +parser.add_argument("-d", "--debug", action = "store_true", + help = "enable debugging (eg, Python backtraces)") +parser.add_argument("-v", "--verbose", action = "store_true", + help = "whistle while you work") +parser.add_argument("-f", "--force", action = "store_true", + help = "force database create, drop, or grant regardless of current state") + +parser.add_argument("--mysql-defaults", + help = "specify MySQL root access credentials via a configuration file") + + +parser.add_argument("--postgresql-root-database", default = "postgres", + help = "name of PostgreSQL control database") +parser.add_argument("--postgresql-root-username", + help = "username of PostgreSQL control role") + +subparsers = parser.add_subparsers(title = "Commands", metavar = "", dest = "dispatch") + +subparsers.add_parser("create", + help = "create databases and load schemas") + +subparsers.add_parser("drop", + help = "drop databases") + +subparser = subparsers.add_parser("script-drop", + help = "show SQL commands to drop databases") +subparser.add_argument("script_output", + nargs = "?", type = argparse.FileType("w"), default = "-", + help = "destination for drop script") + +subparsers.add_parser("drop-and-create", + help = "drop databases then recreate them and load schemas") + +subparsers.add_parser("fix-grants", + help = "whack database to match configuration file") + +args = parser.parse_args() + +try: + + cfg = rpki.config.parser(set_filename = args.config, section = "myrpki") + + names = [name for name in ("irdbd", "rpkid", "pubd") + if cfg.getboolean("start_" + name, False)] + names.append("rcynic") + + # For now, we quietly ignore missing sections rather than throwing an exception. + # I could make a case either way for this, but ignoring missing sections is a + # lot easier to clean up while debugging the installation scripts. + + for name in names: + if cfg.has_section(name): + udb = UserDB(args = args, name = name) + method = args.dispatch.replace("-", "_") + getattr(udb, method)() + +except Exception, e: + if args.debug: + raise + else: + sys.exit(str(e)) diff --git a/rp/rcynic/Makefile.in b/rp/rcynic/Makefile.in index a2d844bd..ce19ab81 100644 --- a/rp/rcynic/Makefile.in +++ b/rp/rcynic/Makefile.in @@ -49,19 +49,15 @@ RCYNIC_CRON_USER = @RCYNIC_CRON_USER@ RCYNIC_DATA_DIR = ${RCYNIC_DIR}/data RCYNIC_DIR = @RCYNIC_DIR@ RCYNIC_DIRS = ${RCYNIC_TA_DIR} ${RCYNIC_JAIL_DIRS} ${RCYNIC_DATA_DIR} ${RPKIRTR_DIR} ${RPKIRTR_DIR}/sockets -RCYNIC_GECOS = RPKI Validation System -RCYNIC_GROUP = @RCYNIC_GROUP@ +RPKI_GECOS = RPKI System Software +RPKI_GROUP = @RPKI_GROUP@ RCYNIC_HTML_DIR = @RCYNIC_HTML_DIR@ RCYNIC_INSTALL_TARGETS = @RCYNIC_INSTALL_TARGETS@ RCYNIC_JAIL_DIRS = @RCYNIC_JAIL_DIRS@ RCYNIC_STATIC_RSYNC = @RCYNIC_STATIC_RSYNC@ RCYNIC_TA_DIR = @RCYNIC_TA_DIR@ -RCYNIC_USER = @RCYNIC_USER@ +RPKI_USER = @RPKI_USER@ RPKIRTR_DIR = ${RCYNIC_DIR}/rpki-rtr -RPKIRTR_GECOS = RPKI router server -RPKIRTR_GROUP = rpkirtr -RPKIRTR_MODE = 775 -RPKIRTR_USER = rpkirtr all: ${BIN} ${RCYNIC_STATIC_RSYNC} @@ -122,9 +118,7 @@ ${RCYNIC_DIRS} ${DESTDIR}${bindir} ${DESTDIR}${sysconfdir}: ${INSTALL} -v -d $@ install-directory-ownership: ${RCYNIC_DATA_DIR} ${RPKIRTR_DIR} ${RPKIRTR_DIR}/sockets - chown ${RCYNIC_USER}:${RCYNIC_GROUP} ${RCYNIC_DATA_DIR} ${RPKIRTR_DIR} - chown ${RPKIRTR_USER}:${RCYNIC_GROUP} ${RPKIRTR_DIR}/sockets - chmod ${RPKIRTR_MODE} ${RPKIRTR_DIR}/sockets + chown ${RPKI_USER}:${RPKI_GROUP} ${RCYNIC_DATA_DIR} ${RPKIRTR_DIR} ${RPKIRTR_DIR}/sockets install-rcynic-conf: ${RCYNIC_CONF_FILE} diff --git a/rp/rcynic/rcynic-cron b/rp/rcynic/rcynic-cron index d1f96422..fcf38e53 100755 --- a/rp/rcynic/rcynic-cron +++ b/rp/rcynic/rcynic-cron @@ -74,9 +74,9 @@ if args.chroot and not we_are_root: sys.exit("Only root can --chroot") try: - pw = pwd.getpwnam(rpki.autoconf.RCYNIC_USER) + pw = pwd.getpwnam(rpki.autoconf.RPKI_USER) except KeyError: - sys.exit("Could not find passwd entry for user %s" % rpki.autoconf.RCYNIC_USER) + sys.exit("Could not find passwd entry for user %s" % rpki.autoconf.RPKI_USER) try: lock = os.open(os.path.join(rpki.autoconf.RCYNIC_DIR, "data/lock"), diff --git a/rp/rcynic/rules.darwin.mk b/rp/rcynic/rules.darwin.mk index d37b0e75..b5979979 100644 --- a/rp/rcynic/rules.darwin.mk +++ b/rp/rcynic/rules.darwin.mk @@ -1,77 +1,41 @@ # $Id$ install-user-and-group: .FORCE - @if /usr/bin/dscl . -read "/Groups/${RCYNIC_GROUP}" >/dev/null 2>&1; \ + @if /usr/bin/dscl . -read "/Groups/${RPKI_GROUP}" >/dev/null 2>&1; \ then \ - echo "You already have a group \"${RCYNIC_GROUP}\", so I will use it."; \ + echo "You already have a group \"${RPKI_GROUP}\", so I will use it."; \ elif gid="$$(/usr/bin/dscl . -list /Groups PrimaryGroupID | /usr/bin/awk 'BEGIN {gid = 501} $$2 >= gid {gid = 1 + $$2} END {print gid}')" && \ - /usr/bin/dscl . -create "/Groups/${RCYNIC_GROUP}" && \ - /usr/bin/dscl . -create "/Groups/${RCYNIC_GROUP}" RealName "${RCYNIC_GECOS}" && \ - /usr/bin/dscl . -create "/Groups/${RCYNIC_GROUP}" PrimaryGroupID "$$gid" && \ - /usr/bin/dscl . -create "/Groups/${RCYNIC_GROUP}" GeneratedUID "$$(/usr/bin/uuidgen)" && \ - /usr/bin/dscl . -create "/Groups/${RCYNIC_GROUP}" Password "*"; \ + /usr/bin/dscl . -create "/Groups/${RPKI_GROUP}" && \ + /usr/bin/dscl . -create "/Groups/${RPKI_GROUP}" RealName "${RPKI_GECOS}" && \ + /usr/bin/dscl . -create "/Groups/${RPKI_GROUP}" PrimaryGroupID "$$gid" && \ + /usr/bin/dscl . -create "/Groups/${RPKI_GROUP}" GeneratedUID "$$(/usr/bin/uuidgen)" && \ + /usr/bin/dscl . -create "/Groups/${RPKI_GROUP}" Password "*"; \ then \ - echo "Added group \"${RCYNIC_GROUP}\"."; \ + echo "Added group \"${RPKI_GROUP}\"."; \ else \ - echo "Adding group \"${RCYNIC_GROUP}\" failed..."; \ + echo "Adding group \"${RPKI_GROUP}\" failed..."; \ echo "Please create it, then try again."; \ exit 1; \ fi; \ - if /usr/bin/dscl . -read "/Users/${RCYNIC_USER}" >/dev/null 2>&1; \ + if /usr/bin/dscl . -read "/Users/${RPKI_USER}" >/dev/null 2>&1; \ then \ - echo "You already have a user \"${RCYNIC_USER}\", so I will use it."; \ + echo "You already have a user \"${RPKI_USER}\", so I will use it."; \ elif uid="$$(/usr/bin/dscl . -list /Users UniqueID | /usr/bin/awk 'BEGIN {uid = 501} $$2 >= uid {uid = 1 + $$2} END {print uid}')" && \ - /usr/bin/dscl . -create "/Users/${RCYNIC_USER}" && \ - /usr/bin/dscl . -create "/Users/${RCYNIC_USER}" UserShell "/usr/bin/false" && \ - /usr/bin/dscl . -create "/Users/${RCYNIC_USER}" RealName "${RCYNIC_GECOS}" && \ - /usr/bin/dscl . -create "/Users/${RCYNIC_USER}" UniqueID "$$uid" && \ - /usr/bin/dscl . -create "/Users/${RCYNIC_USER}" PrimaryGroupID "$$gid" && \ - /usr/bin/dscl . -create "/Users/${RCYNIC_USER}" NFSHomeDirectory "/var/empty" && \ - /usr/bin/dscl . -create "/Users/${RCYNIC_USER}" GeneratedUID "$$(/usr/bin/uuidgen)" && \ - /usr/bin/dscl . -create "/Users/${RCYNIC_USER}" Password "*"; \ + /usr/bin/dscl . -create "/Users/${RPKI_USER}" && \ + /usr/bin/dscl . -create "/Users/${RPKI_USER}" UserShell "/usr/bin/false" && \ + /usr/bin/dscl . -create "/Users/${RPKI_USER}" RealName "${RPKI_GECOS}" && \ + /usr/bin/dscl . -create "/Users/${RPKI_USER}" UniqueID "$$uid" && \ + /usr/bin/dscl . -create "/Users/${RPKI_USER}" PrimaryGroupID "$$gid" && \ + /usr/bin/dscl . -create "/Users/${RPKI_USER}" NFSHomeDirectory "/var/empty" && \ + /usr/bin/dscl . -create "/Users/${RPKI_USER}" GeneratedUID "$$(/usr/bin/uuidgen)" && \ + /usr/bin/dscl . -create "/Users/${RPKI_USER}" Password "*"; \ then \ - echo "Added user \"${RCYNIC_USER}\"."; \ + echo "Added user \"${RPKI_USER}\"."; \ else \ - echo "Adding user \"${RCYNIC_USER}\" failed..."; \ + echo "Adding user \"${RPKI_USER}\" failed..."; \ echo "Please create it, then try again."; \ exit 1; \ fi - @if /usr/bin/dscl . -read "/Groups/${RPKIRTR_GROUP}" >/dev/null 2>&1; \ - then \ - echo "You already have a group \"${RPKIRTR_GROUP}\", so I will use it."; \ - elif gid="$$(/usr/bin/dscl . -list /Groups PrimaryGroupID | /usr/bin/awk 'BEGIN {gid = 501} $$2 >= gid {gid = 1 + $$2} END {print gid}')" && \ - /usr/bin/dscl . -create "/Groups/${RPKIRTR_GROUP}" && \ - /usr/bin/dscl . -create "/Groups/${RPKIRTR_GROUP}" RealName "${RPKIRTR_GECOS}" && \ - /usr/bin/dscl . -create "/Groups/${RPKIRTR_GROUP}" PrimaryGroupID "$$gid" && \ - /usr/bin/dscl . -create "/Groups/${RPKIRTR_GROUP}" GeneratedUID "$$(/usr/bin/uuidgen)" && \ - /usr/bin/dscl . -create "/Groups/${RPKIRTR_GROUP}" Password "*"; \ - then \ - echo "Added group \"${RPKIRTR_GROUP}\"."; \ - else \ - echo "Adding group \"${RPKIRTR_GROUP}\" failed..."; \ - echo "Please create it, then try again."; \ - exit 1; \ - fi; \ - if /usr/bin/dscl . -read "/Users/${RPKIRTR_USER}" >/dev/null 2>&1; \ - then \ - echo "You already have a user \"${RPKIRTR_USER}\", so I will use it."; \ - elif uid="$$(/usr/bin/dscl . -list /Users UniqueID | /usr/bin/awk 'BEGIN {uid = 501} $$2 >= uid {uid = 1 + $$2} END {print uid}')" && \ - /usr/bin/dscl . -create "/Users/${RPKIRTR_USER}" && \ - /usr/bin/dscl . -create "/Users/${RPKIRTR_USER}" UserShell "/usr/bin/false" && \ - /usr/bin/dscl . -create "/Users/${RPKIRTR_USER}" RealName "${RPKIRTR_GECOS}" && \ - /usr/bin/dscl . -create "/Users/${RPKIRTR_USER}" UniqueID "$$uid" && \ - /usr/bin/dscl . -create "/Users/${RPKIRTR_USER}" PrimaryGroupID "$$gid" && \ - /usr/bin/dscl . -create "/Users/${RPKIRTR_USER}" NFSHomeDirectory "/var/empty" && \ - /usr/bin/dscl . -create "/Users/${RPKIRTR_USER}" GeneratedUID "$$(/usr/bin/uuidgen)" && \ - /usr/bin/dscl . -create "/Users/${RPKIRTR_USER}" Password "*"; \ - then \ - echo "Added user \"${RPKIRTR_USER}\"."; \ - else \ - echo "Adding user \"${RPKIRTR_USER}\" failed..."; \ - echo "Please create it, then try again."; \ - exit 1; \ - fi - install-shared-libraries: .FORCE @echo "Copying required shared libraries" diff --git a/rp/rcynic/rules.freebsd.mk b/rp/rcynic/rules.freebsd.mk index 5233386e..880ce3f4 100644 --- a/rp/rcynic/rules.freebsd.mk +++ b/rp/rcynic/rules.freebsd.mk @@ -1,51 +1,28 @@ # $Id$ install-user-and-group: .FORCE - @if /usr/sbin/pw groupshow "${RCYNIC_GROUP}" 2>/dev/null; \ + @if /usr/sbin/pw groupshow "${RPKI_GROUP}" 2>/dev/null; \ then \ - echo "You already have a group \"${RCYNIC_GROUP}\", so I will use it."; \ - elif /usr/sbin/pw groupadd ${RCYNIC_GROUP}; \ + echo "You already have a group \"${RPKI_GROUP}\", so I will use it."; \ + elif /usr/sbin/pw groupadd ${RPKI_GROUP}; \ then \ - echo "Added group \"${RCYNIC_GROUP}\"."; \ + echo "Added group \"${RPKI_GROUP}\"."; \ else \ - echo "Adding group \"${RCYNIC_GROUP}\" failed..."; \ + echo "Adding group \"${RPKI_GROUP}\" failed..."; \ echo "Please create it, then try again."; \ exit 1; \ fi - @if /usr/sbin/pw groupshow "${RPKIRTR_GROUP}" 2>/dev/null; \ + @if /usr/sbin/pw usershow "${RPKI_USER}" 2>/dev/null; \ then \ - echo "You already have a group \"${RPKIRTR_GROUP}\", so I will use it."; \ - elif /usr/sbin/pw groupadd ${RPKIRTR_GROUP}; \ + echo "You already have a user \"${RPKI_USER}\", so I will use it."; \ + elif /usr/sbin/pw useradd ${RPKI_USER} -g ${RPKI_GROUP} -h - -d /nonexistant -s /usr/sbin/nologin -c "${RPKI_GECOS}"; \ then \ - echo "Added group \"${RPKIRTR_GROUP}\"."; \ + echo "Added user \"${RPKI_USER}\"."; \ else \ - echo "Adding group \"${RPKIRTR_GROUP}\" failed..."; \ + echo "Adding user \"${RPKI_USER}\" failed..."; \ echo "Please create it, then try again."; \ exit 1; \ fi - @if /usr/sbin/pw usershow "${RCYNIC_USER}" 2>/dev/null; \ - then \ - echo "You already have a user \"${RCYNIC_USER}\", so I will use it."; \ - elif /usr/sbin/pw useradd ${RCYNIC_USER} -g ${RCYNIC_GROUP} -h - -d /nonexistant -s /usr/sbin/nologin -c "${RCYNIC_GECOS}" -G "${RPKIRTR_GROUP}"; \ - then \ - echo "Added user \"${RCYNIC_USER}\"."; \ - else \ - echo "Adding user \"${RCYNIC_USER}\" failed..."; \ - echo "Please create it, then try again."; \ - exit 1; \ - fi - @if /usr/sbin/pw usershow "${RPKIRTR_USER}" 2>/dev/null; \ - then \ - echo "You already have a user \"${RPKIRTR_USER}\", so I will use it."; \ - elif /usr/sbin/pw useradd ${RPKIRTR_USER} -g ${RPKIRTR_GROUP} -h - -d /nonexistant -s /usr/sbin/nologin -c "${RPKIRTR_GECOS}"; \ - then \ - echo "Added user \"${RPKIRTR_USER}\"."; \ - else \ - echo "Adding user \"${RPKIRTR_USER}\" failed..."; \ - echo "Please create it, then try again."; \ - exit 1; \ - fi - # We use static compilation on FreeBSD, so no need for shared libraries diff --git a/rp/rcynic/rules.linux.mk b/rp/rcynic/rules.linux.mk index 6a962cef..016b0582 100644 --- a/rp/rcynic/rules.linux.mk +++ b/rp/rcynic/rules.linux.mk @@ -1,55 +1,36 @@ # $Id$ install-user-and-group: .FORCE - @if getent group ${RCYNIC_GROUP} >/dev/null; \ + @if getent group ${RPKI_GROUP} >/dev/null; \ then \ - echo "You already have a group \"${RCYNIC_GROUP}\", so I will use it."; \ - elif /usr/sbin/groupadd ${RCYNIC_GROUP}; \ + echo "You already have a group \"${RPKI_GROUP}\", so I will use it."; \ + elif /usr/sbin/groupadd ${RPKI_GROUP}; \ then \ - echo "Added group \"${RCYNIC_GROUP}\"."; \ + echo "Added group \"${RPKI_GROUP}\"."; \ else \ - echo "Adding group \"${RCYNIC_GROUP}\" failed..."; \ + echo "Adding group \"${RPKI_GROUP}\" failed..."; \ echo "Please create it, then try again."; \ exit 1; \ fi @nogroup='-N'; \ if test -f /etc/redhat-release; then read vendor release version < /etc/redhat-release; if test $$vendor = CentOS; then nogroup='-n'; fi; fi; \ - if getent passwd ${RCYNIC_USER} >/dev/null; \ + if getent passwd ${RPKI_USER} >/dev/null; \ then \ - echo "You already have a user \"${RCYNIC_USER}\", so I will use it."; \ - elif /usr/sbin/useradd -g ${RCYNIC_GROUP} -M $$nogroup -d "${RCYNIC_DIR}" -s /sbin/nologin -c "${RCYNIC_GECOS}" ${RCYNIC_USER}; \ + echo "You already have a user \"${RPKI_USER}\", so I will use it."; \ + elif /usr/sbin/useradd -g ${RPKI_GROUP} -M $$nogroup -d "${RCYNIC_DIR}" -s /sbin/nologin -c "${RPKI_GECOS}" ${RPKI_USER}; \ then \ - echo "Added user \"${RCYNIC_USER}\"."; \ + echo "Added user \"${RPKI_USER}\"."; \ else \ - echo "Adding user \"${RCYNIC_USER}\" failed..."; \ + echo "Adding user \"${RPKI_USER}\" failed..."; \ echo "Please create it, then try again."; \ exit 1; \ fi - @if getent group ${RPKIRTR_GROUP} >/dev/null; \ - then \ - echo "You already have a group \"${RPKIRTR_GROUP}\", so I will use it."; \ - elif /usr/sbin/groupadd ${RPKIRTR_GROUP}; \ - then \ - echo "Added group \"${RPKIRTR_GROUP}\"."; \ - else \ - echo "Adding group \"${RPKIRTR_GROUP}\" failed..."; \ - echo "Please create it, then try again."; \ - exit 1; \ - fi - @nogroup='-N'; \ - if test -f /etc/redhat-release; then read vendor release version < /etc/redhat-release; if test $$vendor = CentOS; then nogroup='-n'; fi; fi; \ - if getent passwd ${RPKIRTR_USER} >/dev/null; \ - then \ - echo "You already have a user \"${RPKIRTR_USER}\", so I will use it."; \ - elif /usr/sbin/useradd -g ${RPKIRTR_GROUP} -M $$nogroup -d "${RPKIRTR_DIR}" -s /sbin/nologin -c "${RPKIRTR_GECOS}" ${RPKIRTR_USER}; \ - then \ - echo "Added user \"${RPKIRTR_USER}\"."; \ - else \ - echo "Adding user \"${RPKIRTR_USER}\" failed..."; \ - echo "Please create it, then try again."; \ - exit 1; \ - fi - usermod -a -G ${RPKIRTR_GROUP} ${RCYNIC_USER} + +# This all looks like a relic of the days when we still tried to support rcynic running in a chroot jail, which +# never really worked properly except on FreeBSD, and has since been overtaken by many other events. Do we +# still need this, even assuming anybody uses this installation instead of Debian packaging? +# +# Cleanup left for another day, but this looks pretty iffy. install-shared-libraries: .FORCE @echo "Copying required shared libraries" diff --git a/rp/rpki-rtr/rules.freebsd.mk b/rp/rpki-rtr/rules.freebsd.mk index f4d214a3..0f1546b2 100644 --- a/rp/rpki-rtr/rules.freebsd.mk +++ b/rp/rpki-rtr/rules.freebsd.mk @@ -18,7 +18,7 @@ install-listener: .FORCE @if /usr/bin/egrep -q "rpki-rtr[ ]+stream[ ]+tcp[ ]" /etc/inetd.conf; \ then \ echo "You already have an inetd.conf entry for rpki-rtr on TCPv4, so I will use it."; \ - elif echo >>/etc/inetd.conf "rpki-rtr stream tcp nowait rpkirtr /usr/local/bin/rpki-rtr rpki-rtr server /var/rcynic/rpki-rtr"; \ + elif echo >>/etc/inetd.conf "rpki-rtr stream tcp nowait rpki /usr/local/bin/rpki-rtr rpki-rtr server /var/rcynic/rpki-rtr"; \ then \ echo "Added rpki-rtr for TCPv4 to /etc/inetd.conf."; \ else \ @@ -28,7 +28,7 @@ install-listener: .FORCE @if /usr/bin/egrep -q "rpki-rtr[ ]+stream[ ]+tcp6[ ]" /etc/inetd.conf; \ then \ echo "You already have an inetd.conf entry for rpki-rtr on TCPv6, so I will use it."; \ - elif echo >>/etc/inetd.conf "rpki-rtr stream tcp6 nowait rpkirtr /usr/local/bin/rpki-rtr rpki-rtr server /var/rcynic/rpki-rtr"; \ + elif echo >>/etc/inetd.conf "rpki-rtr stream tcp6 nowait rpki /usr/local/bin/rpki-rtr rpki-rtr server /var/rcynic/rpki-rtr"; \ then \ echo "Added rpki-rtr for TCPv6 to /etc/inetd.conf."; \ else \ diff --git a/rp/rpki-rtr/rules.linux.mk b/rp/rpki-rtr/rules.linux.mk index d9b21590..bad35ace 100644 --- a/rp/rpki-rtr/rules.linux.mk +++ b/rp/rpki-rtr/rules.linux.mk @@ -19,7 +19,7 @@ ${DESTDIR}/etc/xinetd.d/rpki-rtr: print " protocol = tcp"; \ print " port = ${RPKI_RTR_PORT}"; \ print " wait = no"; \ - print " user = rpkirtr"; \ + print " user = rpki"; \ print " server = ${bindir}/${BIN}"; \ print " server_args = server /var/rcynic/rpki-rtr"; \ print "}"; \ diff --git a/setup.py b/setup.py index 6bd5245b..58503bd4 100644 --- a/setup.py +++ b/setup.py @@ -96,7 +96,12 @@ if autoconf.RP_TARGET == "rp": "rp/utils/print_rpki_manifest", "rp/utils/scan_roas", "rp/utils/scan_routercerts", - "rp/utils/uri"])] + "rp/utils/uri"]), + (autoconf.sbindir, + ["rp/config/rpki-confgen", + "rp/config/rpki-sql-backup", + "rp/config/rpki-sql-setup", + "rp/config/rpki-manage"])] if autoconf.CA_TARGET == "ca": setup_args.update( @@ -109,17 +114,11 @@ if autoconf.CA_TARGET == "ca": (autoconf.datarootdir + "/rpki/media/js", glob("rpki/gui/app/static/js/*")), (autoconf.datarootdir + "/rpki/media/img", - glob("rpki/gui/app/static/img/*")), - (autoconf.datarootdir + "/rpki/upgrade-scripts", - glob("ca/upgrade-scripts/*"))]) + glob("rpki/gui/app/static/img/*"))]) scripts += [(autoconf.sbindir, ["ca/rpkic", - "ca/rpki-confgen", "ca/rpki-start-servers", - "ca/rpki-sql-backup", - "ca/rpki-sql-setup", - "ca/rpki-manage", "ca/rpkigui-query-routes", "ca/irbe_cli"]), (autoconf.libexecdir, -- cgit v1.2.3