[PATCH] Minion to minion (certmaster)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Attached is the certmaster half of the m2m patch.  It is also available
here:

git://fedorapeople.org/~jeckersb/certmaster.git
branch: m2m-merge
hash: cd7c424c4870bdf1b93c43b9283b25fb803361eb

- --
John Eckersberg
IT Engineering Support
Red Hat, Inc.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org

iEYEARECAAYFAkm6uEoACgkQdxt4pd4ztYvPIACfbxv6BMeKhHfWQKTORmKaPQF9
nBIAoLSTyJ9T7t8fiEWeQqLy5mCG6Hwg
=eY1j
-----END PGP SIGNATURE-----
>From cd7c424c4870bdf1b93c43b9283b25fb803361eb Mon Sep 17 00:00:00 2001
From: John Eckersberg <jeckersb@xxxxxxxxxx>
Date: Fri, 13 Mar 2009 15:39:37 -0400
Subject: [PATCH] Minion-to-minion support, certmaster half.

---
 certmaster.spec            |    2 +
 certmaster/certmaster.py   |    7 ++
 certmaster/commonconfig.py |    4 +-
 scripts/certmaster-sync    |  139 ++++++++++++++++++++++++++++++++++++++++++++
 setup.py                   |    2 +-
 5 files changed, 152 insertions(+), 2 deletions(-)
 create mode 100644 scripts/certmaster-sync

diff --git a/certmaster.spec b/certmaster.spec
index e03ec78..f7fa30c 100644
--- a/certmaster.spec
+++ b/certmaster.spec
@@ -74,6 +74,7 @@ rm -fr $RPM_BUILD_ROOT
 %{_bindir}/certmaster
 %{_bindir}/certmaster-request
 %{_bindir}/certmaster-ca
+%{_bindir}/certmaster-sync
 /etc/init.d/certmaster
 %dir %{_sysconfdir}/%{name}
 %dir %{_sysconfdir}/%{name}/minion-acl.d/
@@ -85,6 +86,7 @@ rm -fr $RPM_BUILD_ROOT
 %{python_sitelib}/certmaster/*.py*
 %dir /var/log/certmaster
 %dir /var/lib/certmaster
+%dir /var/lib/certmaster/peers
 %dir /var/lib/certmaster/triggers/sign/
 %dir /var/lib/certmaster/triggers/sign/pre
 %dir /var/lib/certmaster/triggers/sign/post
diff --git a/certmaster/certmaster.py b/certmaster/certmaster.py
index 506a029..58cb50b 100644
--- a/certmaster/certmaster.py
+++ b/certmaster/certmaster.py
@@ -276,6 +276,13 @@ class CertMaster(object):
 
         return signed_certs
 
+    def get_peer_certs(self):
+        """
+        Returns a list of all certs under peerroot
+        """
+        myglob = os.path.join(self.cfg.peerroot, '*.%s' % self.cfg.cert_extension)
+        return glob.glob(myglob)
+
     # return a list of the cert hash string we use to identify systems
     def get_cert_hashes(self, hostglobs=None):
         certglob = "%s/*.cert" % (self.cfg.certroot)
diff --git a/certmaster/commonconfig.py b/certmaster/commonconfig.py
index 4be491e..5d0361e 100644
--- a/certmaster/commonconfig.py
+++ b/certmaster/commonconfig.py
@@ -26,10 +26,12 @@ class CMConfig(BaseConfig):
     csrroot = Option('/var/lib/certmaster/certmaster/csrs')
     cert_extension = Option('cert')
     autosign = BoolOption(False)
+    sync_certs = BoolOption(False)
+    peering = BoolOption(True)
+    peerroot =  Option('/var/lib/certmaster/peers')
 
 class MinionConfig(BaseConfig):
     log_level = Option('INFO')
     certmaster = Option('certmaster')
     certmaster_port = IntOption(51235)
     cert_dir = Option('/etc/pki/certmaster')
-
diff --git a/scripts/certmaster-sync b/scripts/certmaster-sync
new file mode 100644
index 0000000..bd27af5
--- /dev/null
+++ b/scripts/certmaster-sync
@@ -0,0 +1,139 @@
+#!/usr/bin/python -tt
+
+# Syncs the valid CA-signed certificates from certmaster to all known
+# hosts via func.  To be called during the post-sign hook to copy new
+# certificates and from the post-clean hook in order to purge stale
+# certificates.  Requires 'sync_certs' to be set in certmaster.conf.
+
+import os
+import sys
+import sha
+import xmlrpclib
+from glob import glob
+from time import sleep
+from certmaster import certmaster as certmaster
+from func.overlord.client import Client
+from func.CommonErrors import Func_Client_Exception
+import func.jobthing as jobthing
+
+def syncable(cert_list):
+    """
+    Calls out to known hosts to find out who is configured for
+    peering.  Returns a list of hostnames who support peering.
+    """
+    try:
+        fc = Client('*', async=True, nforks=len(cert_list))
+    except Func_Client_Exception:
+        # we are either:
+        #   - signing the first minion
+        #   - cleaning the only minion
+        # so there's nothing to hit.  This shouldn't happen
+        # when we get called from the 'post-fetch' trigger
+        # (future work)
+        return None
+
+    # Only wait for a few seconds.  Assume anything that doesn't get
+    # back by then is a lost cause.  Don't want this trigger to spin
+    # too long.
+    ticks = 0
+    return_code = jobthing.JOB_ID_RUNNING
+    results = None
+    job_id = fc.certmastermod.peering_enabled()
+    while return_code != jobthing.JOB_ID_FINISHED and ticks < 3:
+        sleep(1)
+        (return_code, results) = fc.job_status(job_id)
+        ticks += 1
+
+    hosts = []
+    for host, result in results.iteritems():
+        if result == True:
+            hosts.append(host)
+    return hosts
+
+def remote_peers(hosts):
+    """
+    Calls out to hosts to collect peer information
+    """
+    fc = Client(';'.join(hosts))
+    return fc.certmastermod.known_peers()
+
+def local_certs():
+    """
+    Returns (hostname, sha1) hash of local certs
+    """
+    globby = '*.%s' % cm.cfg.cert_extension
+    globby = os.path.join(cm.cfg.certroot, globby)
+    files = glob(globby)
+    results = []
+    for f in files:
+        hostname = os.path.basename(f).replace('.' + cm.cfg.cert_extension, '')
+        digest = checksum(f)
+        results.append([hostname, digest])
+    return results
+
+def checksum(f):
+    thissum = sha.new()
+    if os.path.exists(f):
+        fo = open(f, 'r')
+        data = fo.read()
+        fo.close()
+        thissum.update(data)
+
+    return thissum.hexdigest()
+
+def remove_stale_certs(local, remote):
+    """
+    For each cert on each remote host, make sure it exists locally.
+    If not then it has been cleaned locally and needs unlinked
+    remotely.
+    """
+    local = [foo[0] for foo in local] # don't care about checksums
+    for host, peers in remote.iteritems():
+        fc = Client(host)
+        die = []
+        for peer in peers:
+            if peer[0] not in local:
+                die.append(peer[0])
+        if die != []:
+            fc.certmastermod.remove_peer_certs(die)
+
+def copy_updated_certs(local, remote):
+    """
+    For each local cert, make sure it exists on the remote with the
+    correct hash.  If not, copy it over!
+    """
+    for host, peers in remote.iteritems():
+        fc = Client(host)
+        for cert in local:
+            if cert not in peers:
+                cert_name = '%s.%s' % (cert[0], cm.cfg.cert_extension)
+                full_path = os.path.join(cm.cfg.certroot, cert_name)
+                fd = open(full_path)
+                certblob = fd.read()
+                fd.close()
+                fc.certmastermod.copy_peer_cert(cert[0], xmlrpclib.Binary(certblob))
+
+def main():
+    forced = False
+    try:
+        if sys.argv[1] in ['-f', '--force']:
+            forced = True
+    except IndexError:
+        pass
+
+    if not cm.cfg.sync_certs and not forced:
+        sys.exit(0)
+
+    certs = glob(os.path.join(cm.cfg.certroot,
+                              '*.%s' % cm.cfg.cert_extension))
+    hosts = syncable(certs)
+    if not hosts:
+        return 0
+    remote = remote_peers(hosts)
+    local = local_certs()
+    remove_stale_certs(local, remote)
+    copy_updated_certs(local, remote)
+
+if __name__ == "__main__":
+    cm = certmaster.CertMaster()
+    main()
diff --git a/setup.py b/setup.py
index c647170..8cf70eb 100644
--- a/setup.py
+++ b/setup.py
@@ -31,7 +31,7 @@ if __name__ == "__main__":
                 license = "GPL",
 		scripts = [
                      "scripts/certmaster", "scripts/certmaster-ca",
-                     "scripts/certmaster-request",
+                     "scripts/certmaster-request", "scripts/certmaster-sync",
                 ],
 		# package_data = { '' : ['*.*'] },
                 package_dir = {"%s" % NAME: "%s" % NAME
-- 
1.6.0.6

_______________________________________________
Func-list mailing list
Func-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/func-list

[Index of Archives]     [Fedora Users]     [Linux Networking]     [Fedora Legacy List]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]

  Powered by Linux