[-]
[+]
|
Changed |
certmaster.spec
|
|
|
Deleted |
certmaster-0.24.tar.gz/etc/.minion.conf.swp
^
|
[-]
[+]
|
Deleted |
certmaster-0.24.tar.gz/version
^
|
@@ -1 +0,0 @@
-0.24 1
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/PKG-INFO
^
|
@@ -1,10 +1,10 @@
Metadata-Version: 1.0
Name: certmaster
-Version: 0.24
+Version: 0.28
Summary: certmaster remote configuration and management api
-Home-page: https://hosted.fedoraproject.org/projects/certmaster/
+Home-page: https://fedorahosted.org/certmaster/
Author: Lots
-Author-email: certmaster-list@redhat.com
+Author-email: func-list@redhat.com
License: GPL
Description:
A small pluggable xml-rpc daemon used by certmaster to implement various web services hooks
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/README
^
|
@@ -2,7 +2,7 @@
read more at:
-https://hosted.fedoraproject.org/projects/certmaster
+https://fedorahosted.org/certmaster/
-Source: http://git.fedoraproject.org/git/certmaster.git
+Source: http://git.fedorahosted.org/git/?p=certmaster.git;a=summary
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/certmaster/CommonErrors.py
^
|
@@ -67,4 +67,3 @@
self.value = value
def __str__(self):
return "%s" %(self.value,)
-
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/certmaster/SSLCommon.py
^
|
@@ -29,13 +29,16 @@
return preverifyOK
-def CreateSSLContext(pkey, cert, ca_cert):
+def CreateSSLContext(pkey, cert, ca_cert, passwd_callback=None):
for f in pkey, cert, ca_cert:
if f and not os.access(f, os.R_OK):
print "%s does not exist or is not readable." % f
os._exit(1)
ctx = SSL.Context(SSL.SSLv3_METHOD) # SSLv3 only
+ if passwd_callback:
+ ctx.set_passwd_cb = passwd_callback
+
ctx.use_certificate_file(cert)
ctx.use_privatekey_file(pkey)
ctx.load_client_ca(ca_cert)
@@ -118,4 +121,3 @@
def __init__(self, host='', port=None, ssl_context=None, strict=None, timeout=None):
self._setup(self._connection_class(host, port, ssl_context, strict, timeout))
-
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/certmaster/SSLConnection.py
^
|
@@ -62,7 +62,7 @@
c, a = self.__dict__["conn"].accept()
return (SSLConnection(c), a)
- def makefile(self, mode, bufsize):
+ def makefile(self, mode='r', bufsize=-1):
"""
We need to use socket._fileobject Because SSL.Connection
doesn't have a 'dup'. Not exactly sure WHY this is, but
@@ -97,6 +97,9 @@
if not con in write:
raise socket.timeout((110, "Operation timed out."))
+ if hasattr(data, 'tobytes'):
+ data = data.tobytes()
+
starttime = time.time()
origlen = len(data)
sent = -1
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/certmaster/certmaster.py
^
|
@@ -16,11 +16,25 @@
# standard modules
import SimpleXMLRPCServer
+import string
import sys
+import traceback
import os
import os.path
from OpenSSL import crypto
-import sha
+
+try:
+ import hashlib
+except ImportError:
+ # Python-2.4.z ... gah! (or even 2.3!)
+ import sha
+ class hashlib:
+ @staticmethod
+ def new(algo):
+ if algo == 'sha1':
+ return sha.new()
+ raise ValueError, "Bad checksum type"
+
import glob
import socket
import exceptions
@@ -50,6 +64,10 @@
self.logger = logger.Logger().logger
self.audit_logger = logger.AuditLogger()
+ # if ca_key_file exists and ca_cert_file is missing == minion only setup
+ if os.path.exists(self.ca_key_file) and not os.path.exists(self.ca_cert_file):
+ return
+
try:
if not os.path.exists(self.cfg.cadir):
os.makedirs(self.cfg.cadir)
@@ -59,11 +77,11 @@
print 'Cannot make certmaster certificate authority keys/certs, aborting: %s' % e
sys.exit(1)
-
+
# open up the cakey and cacert so we have them available
self.cakey = certs.retrieve_key_from_file(self.ca_key_file)
self.cacert = certs.retrieve_cert_from_file(self.ca_cert_file)
-
+
for dirpath in [self.cfg.cadir, self.cfg.certroot, self.cfg.csrroot]:
if not os.path.exists(dirpath):
os.makedirs(dirpath)
@@ -73,7 +91,7 @@
'wait_for_cert': self.wait_for_cert,
}
-
+
def _dispatch(self, method, params):
if method == 'trait_names' or method == '_getAttributeNames':
return self.handlers.keys()
@@ -84,54 +102,54 @@
else:
self.logger.info("Unhandled method call for method: %s " % method)
raise codes.InvalidMethodException
-
+
def _sanitize_cn(self, commonname):
commonname = commonname.replace('/', '')
- commonname = commonname.replace('\\', '')
+ commonname = commonname.replace('\\', '')
return commonname
-
+
def wait_for_cert(self, csrbuf, with_triggers=True):
"""
takes csr as a string
returns True, caller_cert, ca_cert
returns False, '', ''
"""
-
+
try:
csrreq = crypto.load_certificate_request(crypto.FILETYPE_PEM, csrbuf)
except crypto.Error, e:
#XXX need to raise a fault here and document it - but false is just as good
return False, '', ''
-
+
requesting_host = self._sanitize_cn(csrreq.get_subject().CN)
if with_triggers:
- self._run_triggers(requesting_host, '/var/lib/certmaster/triggers/request/pre/*')
+ self._run_triggers(requesting_host, '/var/lib/certmaster/triggers/request/pre/*')
self.logger.info("%s requested signing of cert %s" % (requesting_host,csrreq.get_subject().CN))
# get rid of dodgy characters in the filename we're about to make
-
+
certfile = '%s/%s.cert' % (self.cfg.certroot, requesting_host)
csrfile = '%s/%s.csr' % (self.cfg.csrroot, requesting_host)
# check for old csr on disk
# if we have it - compare the two - if they are not the same - raise a fault
self.logger.debug("csrfile: %s certfile: %s" % (csrfile, certfile))
-
+
if os.path.exists(csrfile):
oldfo = open(csrfile)
oldcsrbuf = oldfo.read()
- oldsha = sha.new()
+ oldsha = hashlib.new('sha1')
oldsha.update(oldcsrbuf)
olddig = oldsha.hexdigest()
- newsha = sha.new()
+ newsha = hashlib.new('sha1')
newsha.update(csrbuf)
newdig = newsha.hexdigest()
if not newdig == olddig:
self.logger.info("A cert for %s already exists and does not match the requesting cert" % (requesting_host))
# XXX raise a proper fault
return False, '', ''
-
+
# look for a cert:
# if we have it, then return True, etc, etc
@@ -142,21 +160,21 @@
if with_triggers:
self._run_triggers(requesting_host,'/var/lib/certmaster/triggers/request/post/*')
return True, cert_buf, cacert_buf
-
+
# if we don't have a cert then:
# if we're autosign then sign it, write out the cert and return True, etc, etc
# else write out the csr
-
+
if self.cfg.autosign:
cert_fn = self.sign_this_csr(csrreq)
- cert = certs.retrieve_cert_from_file(cert_fn)
+ cert = certs.retrieve_cert_from_file(cert_fn)
cert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, cert)
cacert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, self.cacert)
self.logger.info("cert for %s was autosigned" % (requesting_host))
if with_triggers:
self._run_triggers(None,'/var/lib/certmaster/triggers/request/post/*')
return True, cert_buf, cacert_buf
-
+
else:
# write the csr out to a file to be dealt with by the admin
destfo = open(csrfile, 'w')
@@ -171,7 +189,7 @@
return False, '', ''
def get_csrs_waiting(self):
- hosts = []
+ hosts = []
csrglob = '%s/*.csr' % self.cfg.csrroot
csr_list = glob.glob(csrglob)
for f in csr_list:
@@ -179,7 +197,7 @@
hn = hn[:-4]
hosts.append(hn)
return hosts
-
+
def remove_this_cert(self, hn, with_triggers=True):
""" removes cert for hostname using unlink """
cm = self
@@ -199,32 +217,32 @@
os.unlink(fn)
if with_triggers:
self._run_triggers(hn,'/var/lib/certmaster/triggers/remove/post/*')
-
+
def sign_this_csr(self, csr, with_triggers=True):
"""returns the path to the signed cert file"""
csr_unlink_file = None
- if type(csr) is type(''):
+ if type(csr) is type(''):
if csr.startswith('/') and os.path.exists(csr): # we have a full path to the file
csrfo = open(csr)
csr_buf = csrfo.read()
csr_unlink_file = csr
-
+
elif os.path.exists('%s/%s' % (self.cfg.csrroot, csr)): # we have a partial path?
csrfo = open('%s/%s' % (self.cfg.csrroot, csr))
csr_buf = csrfo.read()
csr_unlink_file = '%s/%s' % (self.cfg.csrroot, csr)
-
+
# we have a string of some kind
else:
csr_buf = csr
try:
- csrreq = crypto.load_certificate_request(crypto.FILETYPE_PEM, csr_buf)
+ csrreq = crypto.load_certificate_request(crypto.FILETYPE_PEM, csr_buf)
except crypto.Error, e:
self.logger.info("Unable to sign %s: Bad CSR" % (csr))
raise exceptions.Exception("Bad CSR: %s" % csr)
-
+
else: # assume we got a bare csr req
csrreq = csr
@@ -248,10 +266,10 @@
if with_triggers:
self._run_triggers(requesting_host,'/var/lib/certmaster/triggers/sign/post/*')
-
+
if csr_unlink_file and os.path.exists(csr_unlink_file):
os.unlink(csr_unlink_file)
-
+
return certfile
# return a list of already signed certs
@@ -274,6 +292,13 @@
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)
@@ -286,12 +311,12 @@
for hostglob in globs:
certglob = "%s/%s.cert" % (self.cfg.certroot, hostglob)
certfiles = certfiles + glob.glob(certglob)
-
+
cert_hashes = []
for certfile in certfiles:
cert = certs.retrieve_cert_from_file(certfile)
cert_hashes.append("%s-%s" % (cert.get_subject().CN, cert.subject_name_hash()))
-
+
return cert_hashes
def _run_triggers(self, ref, globber):
@@ -302,7 +327,7 @@
def __init__(self, addr):
self.allow_reuse_address = True
SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, addr)
-
+
def serve(xmlrpcinstance):
@@ -315,7 +340,7 @@
listen_addr = config.listen_addr
listen_port = config.listen_port
if listen_port == '':
- listen_port = CERTMASTER_LISTEN_PORT
+ listen_port = CERTMASTER_LISTEN_PORT
server = CertmasterXMLRPCServer((listen_addr,listen_port))
server.logRequests = 0 # don't print stuff to console
server.register_instance(xmlrpcinstance)
@@ -323,21 +348,39 @@
xmlrpcinstance.audit_logger.logger.info("certmaster started")
server.serve_forever()
+def excepthook(exctype, value, tracebackobj):
+ exctype_blurb = "Exception occured: %s" % exctype
+ excvalue_blurb = "Exception value: %s" % value
+ exctb_blurb = "Exception Info:\n%s" % string.join(traceback.format_list(traceback.extract_tb(tracebackobj)))
+
+ print exctype_blurb
+ print excvalue_blurb
+ print exctb_blurb
+
+ log = logger.Logger().logger
+ log.info(exctype_blurb)
+ log.info(excvalue_blurb)
+ log.info(exctb_blurb)
+
def main(argv):
-
+
+ sys.excepthook = excepthook
cm = CertMaster('/etc/certmaster/certmaster.conf')
+ if "--version" in sys.argv or "-v" in sys.argv:
+ print >> sys.stderr, file("/etc/certmaster/version").read().strip()
+ sys.exit(0)
+
if "daemon" in argv or "--daemon" in argv:
utils.daemonize("/var/run/certmaster.pid")
else:
print "serving...\n"
-
# just let exceptions bubble up for now
serve(cm)
-
+
if __name__ == "__main__":
#textdomain(I18N_DOMAIN)
main(sys.argv)
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/certmaster/certs.py
^
|
@@ -11,7 +11,7 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-# Copyright (c) 2007 Red Hat, inc
+# Copyright (c) 2007 Red Hat, inc
#- Written by Seth Vidal skvidal @ fedoraproject.org
from OpenSSL import crypto
@@ -33,11 +33,11 @@
destfd = os.open(dest, os.O_RDWR|os.O_CREAT, 0600)
os.write(destfd, (crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)))
os.close(destfd)
-
+
return pkey
-def make_csr(pkey, dest=None, cn=None):
+def make_csr(pkey, dest=None, cn=None, hostname=None, emailaddr=None):
req = crypto.X509Req()
req.get_subject()
subj = req.get_subject()
@@ -48,10 +48,16 @@
subj.OU = def_ou
if cn:
subj.CN = cn
+ elif hostname:
+ subj.CN = hostname
+ else:
+ subj.CN = utils.gethostname()
+
+ if emailaddr:
+ subj.emailAddress = emailaddr
else:
- subj.CN = utils.get_hostname()
- subj.emailAddress = 'root@%s' % subj.CN
-
+ subj.emailAddress = 'root@%s' % subj.CN
+
req.set_pubkey(pkey)
req.sign(pkey, 'md5')
if dest:
@@ -68,7 +74,7 @@
keypair = crypto.load_privatekey(crypto.FILETYPE_PEM, buf)
return keypair
-
+
def retrieve_csr_from_file(csrfile):
fo = open(csrfile, 'r')
buf = fo.read()
@@ -93,13 +99,17 @@
cacert.set_issuer(careq.get_subject())
cacert.set_subject(careq.get_subject())
cacert.set_pubkey(careq.get_pubkey())
- cacert.sign(cakey, 'md5')
+ cacert.set_version(2)
+ xt = crypto.X509Extension('basicConstraints',1,'CA:TRUE')
+ # FIXME - add subjectkeyidentifier and authoritykeyidentifier extensions, too)
+ cacert.add_extensions((xt,))
+ cacert.sign(cakey, 'sha1')
if ca_cert_file:
destfo = open(ca_cert_file, 'w')
destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cacert))
destfo.close()
-
-
+
+
def _get_serial_number(cadir):
serial = '%s/serial.txt' % cadir
i = 1
@@ -108,11 +118,11 @@
f = f.replace('\n','')
try:
i = int(f)
- i+=1
+ i+=1
except ValueError, e:
i = 1
-
- _set_serial_number(cadir, i)
+
+ _set_serial_number(cadir, i)
return i
@@ -121,8 +131,8 @@
f = open(serial, 'w')
f.write(str(last) + '\n')
f.close()
-
-
+
+
def create_slave_certificate(csr, cakey, cacert, cadir, slave_cert_file=None):
cert = crypto.X509()
cert.set_serial_number(_get_serial_number(cadir))
@@ -131,9 +141,28 @@
cert.set_issuer(cacert.get_subject())
cert.set_subject(csr.get_subject())
cert.set_pubkey(csr.get_pubkey())
- cert.sign(cakey, 'md5')
+ cert.set_version(2)
+ xt = crypto.X509Extension('basicConstraints', False ,'CA:FALSE')
+ # FIXME - add subjectkeyidentifier and authoritykeyidentifier extensions, too)
+ cert.add_extensions((xt,))
+ cert.sign(cakey, 'sha1')
if slave_cert_file:
destfo = open(slave_cert_file, 'w')
destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
destfo.close()
return cert
+
+def check_cert_key_match(cert, key):
+ if not isinstance(cert, crypto.X509Type):
+ cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
+ if not isinstance(key, crypto.PKeyType):
+ key = crypto.load_privatekey(crypto.FILETYPE_PEM, key)
+
+ from OpenSSL import SSL
+ context = SSL.Context(SSL.SSLv3_METHOD)
+ try:
+ context.use_certificate(cert)
+ context.use_privatekey(key)
+ return True
+ except:
+ return False
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/certmaster/codes.py
^
|
@@ -25,4 +25,3 @@
pass
# FIXME: more sub-exceptions maybe
-
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/certmaster/commonconfig.py
^
|
@@ -26,10 +26,12 @@
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')
-
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/certmaster/config.py
^
|
@@ -11,7 +11,7 @@
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-# Copyright 2002 Duke University
+# Copyright 2002 Duke University
# filched from yum - menno smits wrote this - he rocks
@@ -32,13 +32,13 @@
self.value = value
def __str__(self):
return "%s" %(self.value,)
-
-
+
+
class Option(object):
'''
This class handles a single Yum configuration file option. Create
subclasses for each type of supported configuration option.
-
+
Python descriptor foo (__get__ and __set__) is used to make option
definition easy and consise.
'''
@@ -55,7 +55,7 @@
self._attrname = '__opt%d' % id(self)
def __get__(self, obj, objtype):
- '''Called when the option is read (via the descriptor protocol).
+ '''Called when the option is read (via the descriptor protocol).
@param obj: The configuration instance to modify.
@param objtype: The type of the config instance (not used).
@@ -68,7 +68,7 @@
return getattr(obj, self._attrname, None)
def __set__(self, obj, value):
- '''Called when the option is set (via the descriptor protocol).
+ '''Called when the option is set (via the descriptor protocol).
@param obj: The configuration instance to modify.
@param value: The value to set the option to.
@@ -85,8 +85,8 @@
setattr(obj, self._attrname, value)
def setup(self, obj, name):
- '''Initialise the option for a config instance.
- This must be called before the option can be set or retrieved.
+ '''Initialise the option for a config instance.
+ This must be called before the option can be set or retrieved.
@param obj: BaseConfig (or subclass) instance.
@param name: Name of the option.
@@ -105,7 +105,7 @@
@param s: Raw string value to parse.
@return: Validated native value.
-
+
Will raise ValueError if there was a problem parsing the string.
Subclasses should override this.
'''
@@ -164,7 +164,7 @@
This option handles lists of URLs with validation of the URL scheme.
'''
- def __init__(self, default=None, schemes=('http', 'ftp', 'file', 'https'),
+ def __init__(self, default=None, schemes=('http', 'ftp', 'file', 'https'),
allow_none=False):
super(UrlOption, self).__init__(default)
self.schemes = schemes
@@ -208,7 +208,7 @@
# Hold a UrlOption instance to assist with parsing
self._urloption = UrlOption(schemes=schemes)
-
+
def parse(self, s):
out = []
for url in super(UrlListOption, self).parse(s):
@@ -255,7 +255,7 @@
def __init__(self, default=None, allowed=()):
super(SelectionOption, self).__init__(default)
self._allowed = allowed
-
+
def parse(self, s):
if s not in self._allowed:
raise ValueError('"%s" is not an allowed value' % s)
@@ -276,7 +276,7 @@
The input should be a string containing a (possibly floating point)
number followed by an optional single character unit. Valid units are
'k', 'M', 'G'. Case is ignored.
-
+
Valid inputs: 100, 123M, 45.6k, 12.4G, 100K, 786.3, 0
Invalid inputs: -10, -0.1, 45.6L, 123Mb
@@ -298,7 +298,7 @@
else:
n = s
mult = 1
-
+
try:
n = float(n)
except ValueError:
@@ -313,7 +313,7 @@
class ThrottleOption(BytesOption):
def parse(self, s):
- """Get a throttle option.
+ """Get a throttle option.
Input may either be a percentage or a "friendly bandwidth value" as
accepted by the BytesOption.
@@ -382,7 +382,7 @@
# No matching option in this section, try inheriting
if parent and option.inherit:
value = getattr(parent, name)
-
+
if value is not None:
setattr(self, name, value)
@@ -397,7 +397,7 @@
optionobj = classmethod(optionobj)
def isoption(cls, name):
- '''Return True if the given name refers to a defined option
+ '''Return True if the given name refers to a defined option
'''
try:
cls.optionobj(name)
@@ -438,7 +438,7 @@
raise ValueError("not populated, don't know section")
section = self._section
- # Updated the ConfigParser with the changed values
+ # Updated the ConfigParser with the changed values
cfgOptions = self.cfg.options(section)
for name,value in self.iteritems():
option = self.optionobj(name)
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/certmaster/logger.py
^
|
@@ -33,12 +33,12 @@
def __init__(self, logfilepath ="/var/log/certmaster/certmaster.log"):
config_file = '/etc/certmaster/minion.conf'
- self.config = read_config(config_file, CMConfig)
+ self.config = read_config(config_file, CMConfig)
self.loglevel = logging._levelNames[self.config.log_level]
self._setup_logging()
if self._no_handlers:
self._setup_handlers(logfilepath=logfilepath)
-
+
def _setup_logging(self):
self.logger = logging.getLogger("certmaster")
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/certmaster/requester.py
^
|
@@ -15,8 +15,8 @@
import utils
-def request_cert():
- # this should be enough, but do we want to allow parameters
- # for overriding the server and port from the config file?
- # maybe not. -- mpd
- utils.create_minion_keys()
+def request_cert(hostname=None):
+ # this should be enough, but do we want to allow parameters
+ # for overriding the server and port from the config file?
+ # maybe not. -- mpd
+ utils.create_minion_keys(hostname)
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/certmaster/utils.py
^
|
@@ -57,7 +57,7 @@
sys.exit(0)
os.chdir("/")
os.setsid()
- os.umask(0)
+ os.umask(077)
pid = os.fork()
os.close(0)
@@ -65,10 +65,10 @@
os.close(2)
# based on http://code.activestate.com/recipes/278731/
- os.open(REDIRECT_TO, os.O_RDWR) # standard input (0)
+ os.open(REDIRECT_TO, os.O_RDWR) # standard input (0)
- os.dup2(0, 1) # standard output (1)
- os.dup2(0, 2) # standard error (2)
+ os.dup2(0, 1) # standard output (1)
+ os.dup2(0, 2) # standard error (2)
@@ -87,7 +87,7 @@
except:
nicetype = etype
nicestack = string.join(traceback.format_list(traceback.extract_tb(etb)))
- return [ REMOTE_ERROR, nicetype, str(evalue), nicestack ]
+ return [ REMOTE_ERROR, nicetype, str(evalue), nicestack ]
def is_error(result):
# FIXME: I believe we can remove this function
@@ -104,64 +104,42 @@
"localhost" is a lame hostname to use for a key, so try to get
a more meaningful hostname. We do this by connecting to the certmaster
and seeing what interface/ip it uses to make that connection, and looking
- up the hostname for that.
+ up the hostname for that.
"""
# FIXME: this code ignores http proxies (which granted, we don't
- # support elsewhere either. It also hardcodes the port number
- # for the certmaster for now
+ # support elsewhere either.
hostname = None
hostname = socket.gethostname()
# print "DEBUG: HOSTNAME TRY1: %s" % hostname
try:
ip = socket.gethostbyname(hostname)
- # print "DEBUG: IP TRY2: %s" % ip
except:
- # print "DEBUG: ERROR: returning"
return hostname
if ip != "127.0.0.1":
- # print "DEBUG: ERROR: returning 2"
return hostname
- if talk_to_certmaster:
- config_file = '/etc/certmaster/minion.conf'
- config = read_config(config_file, MinionConfig)
-
- server = config.certmaster
- port = config.certmaster_port
-
- try:
- s = socket.socket()
- s.settimeout(5)
- s.connect((server, port))
- (intf, port) = s.getsockname()
- remote_hostname = socket.gethostbyaddr(intf)[0]
- if remote_hostname != "localhost":
- hostname = remote_hostname
- # print "DEBUG: HOSTNAME FROM CERTMASTER == %s" % hostname
- s.close()
- except:
- s.close()
- raise
-
- # print "DEBUG: final hostname=%s" % hostname
- return hostname
-
# FIXME: move to requestor module and also create a verbose mode
# prints to the screen for usage by /usr/bin/certmaster-request
-def create_minion_keys():
+def create_minion_keys(hostname=None):
+ log = logger.Logger().logger
+
# FIXME: paths should not be hard coded here, move to settings universally
config_file = '/etc/certmaster/minion.conf'
config = read_config(config_file, MinionConfig)
cert_dir = config.cert_dir
master_uri = 'http://%s:%s/' % (config.certmaster, config.certmaster_port)
- # print "DEBUG: acquiring hostname"
- hn = get_hostname()
- # print "DEBUG: hostname = %s\n" % hn
+
+ hn = hostname
+ if hn is None:
+ hn = get_hostname()
if hn is None:
raise codes.CMException("Could not determine a hostname other than localhost")
+ else:
+ # use lowercase letters for hostnames
+ hn = hn.lower()
key_file = '%s/%s.pem' % (cert_dir, hn)
csr_file = '%s/%s.csr' % (cert_dir, hn)
@@ -182,20 +160,20 @@
if not os.path.exists(csr_file):
if not keypair:
keypair = certs.retrieve_key_from_file(key_file)
- csr = certs.make_csr(keypair, dest=csr_file)
+ csr = certs.make_csr(keypair, dest=csr_file, hostname=hn)
except Exception, e:
traceback.print_exc()
raise codes.CMException, "Could not create local keypair or csr for session"
result = False
- log = logger.Logger().logger
+
while not result:
try:
# print "DEBUG: submitting CSR to certmaster: %s" % master_uri
- log.debug("submitting CSR to certmaster %s" % master_uri)
+ log.debug("submitting CSR: %s to certmaster %s" % (csr_file, master_uri))
result, cert_string, ca_cert_string = submit_csr_to_master(csr_file, master_uri)
- except socket.gaierror, e:
- raise codes.CMException, "Could not locate certmaster at %s" % master_uri
+ except socket.error, e:
+ log.warning("Could not locate certmaster at %s" % master_uri)
# logging here would be nice
if not result:
@@ -207,6 +185,13 @@
if result:
# print "DEBUG: recieved certificate from certmaster"
log.debug("received certificate from certmaster %s, storing to %s" % (master_uri, cert_file))
+ if not keypair:
+ keypair = certs.retrieve_key_from_file(key_file)
+ valid = certs.check_cert_key_match(cert_string, keypair)
+ if not valid:
+ log.info("certificate does not match key (run certmaster-ca --clean first?)")
+ sys.stderr.write("certificate does not match key (run certmaster-ca --clean first?)\n")
+ return
cert_fd = os.open(cert_file, os.O_RDWR|os.O_CREAT, 0644)
os.write(cert_fd, cert_string)
os.close(cert_fd)
@@ -259,4 +244,3 @@
# print "DEBUG: waiting for cert"
return s.wait_for_cert(csr)
-
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/docs/certmaster-ca.1.gz
^
|
@@ -1,15 +1,7 @@
-.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.07)
+.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
.\"
.\" Standard preamble:
.\" ========================================================================
-.de Sh \" Subsection heading
-.br
-.if t .Sp
-.ne 5
-.PP
-\fB\\$1\fR
-.PP
-..
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
@@ -53,7 +45,7 @@
.el .ds Aq '
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
-.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.ie \nF \{\
@@ -132,7 +124,7 @@
.\" ========================================================================
.\"
.IX Title "CERTMASTER-CA 1"
-.TH CERTMASTER-CA 1 "2008-09-19" "" "certmaster-ca"
+.TH CERTMASTER-CA 1 "2009-11-24" "" "certmaster-ca"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@@ -162,8 +154,9 @@
.SH "ADDITONAL RESOURCES"
.IX Header "ADDITONAL RESOURCES"
See https://fedorahosted.org/certmaster. It's a Wiki.
-.PP
+See also https://fedorahosted.org/func
See also the manpages for \*(L"certmaster\*(R" and \*(L"certmaster-request\*(R".
.SH "AUTHOR"
.IX Header "AUTHOR"
Various. See https://fedorahosted.org/certmaster
+and https://fedorahosted.org/func
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/docs/certmaster-ca.pod
^
|
@@ -28,11 +28,11 @@
=head1 ADDITONAL RESOURCES
See https://fedorahosted.org/certmaster. It's a Wiki.
-
+See also https://fedorahosted.org/func
See also the manpages for "certmaster" and "certmaster-request".
=head1 AUTHOR
Various. See https://fedorahosted.org/certmaster
-
+and https://fedorahosted.org/func
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/docs/certmaster-request.1.gz
^
|
@@ -0,0 +1,159 @@
+.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. \*(C+ will
+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.ie \nF \{\
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. nr % 0
+. rr F
+.\}
+.el \{\
+. de IX
+..
+.\}
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "CERTMASTER-REQUEST 1"
+.TH CERTMASTER-REQUEST 1 "2010-02-16" "" "certmaster-request"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+certmaster\-request \-\- requests SSL certs from a certmaster
+Fedora Unified Network Controller.
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+certmaster-request [\-\-server certmaster.example.com] [\-\-port port]
+[ \-\-wait infinite/seconds ]
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+\&\s-1FIXME:\s0 To be added later once we split this out from func.
+.SH "API"
+.IX Header "API"
+Note: Many applications will want to use the \s-1XMLRPC\s0 \s-1API\s0 (see source) or import
+the Python code to request certs. For those that don't want to do that,
+this command line tool is available. Explore the other options if they
+make more sense for your application.
+.SH "EXIT_STATUS"
+.IX Header "EXIT_STATUS"
+non-zero upon failure.
+.SH "ADDITONAL RESOURCES"
+.IX Header "ADDITONAL RESOURCES"
+See https://fedorahosted.org/certmaster for more information
+.PP
+See also the manpages for \*(L"certmaster\*(R", and \*(L"certmaster-ca\*(R".
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Various. See https://fedorahosted.org/func and
+https://fedorahosted.org/certmaster
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/docs/certmaster-request.pod
^
|
@@ -1,6 +1,6 @@
=head1 NAME
-certmaster-request -- requests SSL certs from a certmasster
+certmaster-request -- requests SSL certs from a certmaster
Fedora Unified Network Controller.
=head1 SYNOPSIS
@@ -31,6 +31,7 @@
=head1 AUTHOR
-Various. See https://fedorahosted.org/func
+Various. See https://fedorahosted.org/func and
+https://fedorahosted.org/certmaster
|
[-]
[+]
|
Added |
certmaster-0.28.tar.bz2/docs/certmaster-sync.1.gz
^
|
@@ -0,0 +1,160 @@
+.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. \*(C+ will
+.\" give a nicer C++. Capital omega is used to do unbreakable dashes and
+.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff,
+.\" nothing in troff, for use with C<>.
+.tr \(*W-
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.ie \nF \{\
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. nr % 0
+. rr F
+.\}
+.el \{\
+. de IX
+..
+.\}
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "CERTMASTER-SYNC 1"
+.TH CERTMASTER-SYNC 1 "2010-03-04" "" "certmaster-sync"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH "NAME"
+certmaster\-sync \-\- synchronize client certificates with Func.
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+certmaster-sync [\-f|\-\-force]
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+certmaster-sync synchronizes client certificates amongst certmaster clients via Func. It is assumed that the hosts who have requested certificates are reachable via Func for synchronization operations.
+.PP
+certmaster-sync by default is called as a post-sign and post-clean trigger. In order to enable synchronization you must set \fBsync_certs\fR to \fBTrue\fR, see \fB\s-1CONFIGURATION\s0 \s-1VALUES\s0\fR below.
+.PP
+The synchronization occurs by querying remote Func methods in \fBcertmastermod\fR on the minion hosts. This will gather information, copy any new certificates, and remove any certificates that have been cleaned.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+.IP "\-f, \-\-force" 4
+.IX Item "-f, --force"
+Override the configuration value for \fBsync_certs\fR in \fI/etc/certmaster/certmaster.conf\fR
+.SH "CONFIGURATION VALUES"
+.IX Header "CONFIGURATION VALUES"
+.IP "sync_certs" 4
+.IX Item "sync_certs"
+\&\fBsync_certs\fR determines whether or not the script will actually synchronize or if it will exit with no operation. You can use \-f|\-\-force to override this configuration value. (Default: False)
+.SH "ADDITONAL RESOURCES"
+.IX Header "ADDITONAL RESOURCES"
+See https://fedorahosted.org/certmaster. It's a Wiki.
+See also https://fedorahosted.org/func
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+John Eckersberg <jeckersb@redhat.com>
|
[-]
[+]
|
Added |
certmaster-0.28.tar.bz2/docs/certmaster-sync.pod
^
|
@@ -0,0 +1,44 @@
+=head1 NAME
+
+certmaster-sync -- synchronize client certificates with Func.
+
+=head1 SYNOPSIS
+
+certmaster-sync [-f|--force]
+
+=head1 DESCRIPTION
+
+certmaster-sync synchronizes client certificates amongst certmaster clients via Func. It is assumed that the hosts who have requested certificates are reachable via Func for synchronization operations.
+
+certmaster-sync by default is called as a post-sign and post-clean trigger. In order to enable synchronization you must set B<sync_certs> to B<True>, see B<CONFIGURATION VALUES> below.
+
+The synchronization occurs by querying remote Func methods in B<certmastermod> on the minion hosts. This will gather information, copy any new certificates, and remove any certificates that have been cleaned.
+
+=head1 OPTIONS
+
+=over
+
+=item -f, --force
+
+Override the configuration value for B<sync_certs> in F</etc/certmaster/certmaster.conf>
+
+=back
+
+=head1 CONFIGURATION VALUES
+
+=over
+
+=item sync_certs
+
+B<sync_certs> determines whether or not the script will actually synchronize or if it will exit with no operation. You can use -f|--force to override this configuration value. (Default: False)
+
+=back
+
+=head1 ADDITONAL RESOURCES
+
+See https://fedorahosted.org/certmaster. It's a Wiki.
+See also https://fedorahosted.org/func
+
+=head1 AUTHOR
+
+John Eckersberg <jeckersb@redhat.com>
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/docs/certmaster.1.gz
^
|
@@ -1,15 +1,7 @@
-.\" Automatically generated by Pod::Man 2.16 (Pod::Simple 3.07)
+.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14)
.\"
.\" Standard preamble:
.\" ========================================================================
-.de Sh \" Subsection heading
-.br
-.if t .Sp
-.ne 5
-.PP
-\fB\\$1\fR
-.PP
-..
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
@@ -53,7 +45,7 @@
.el .ds Aq '
.\"
.\" If the F register is turned on, we'll generate index entries on stderr for
-.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
.\" entries marked with X<> in POD. Of course, you'll have to process the
.\" output yourself in some meaningful fashion.
.ie \nF \{\
@@ -132,7 +124,7 @@
.\" ========================================================================
.\"
.IX Title "CERTMASTER 1"
-.TH CERTMASTER 1 "2008-09-19" "" "certmaster"
+.TH CERTMASTER 1 "2009-11-24" "" "certmaster"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@@ -153,8 +145,9 @@
.SH "ADDITONAL RESOURCES"
.IX Header "ADDITONAL RESOURCES"
See https://fedorahosted.org/certmaster/. It's a Wiki.
-.PP
+See also
See also the manpages for \*(L"certmaster-request\*(R" and \*(L"certmaster-ca\*(R".
.SH "AUTHOR"
.IX Header "AUTHOR"
-Various. See https://hosted.fedoraproject.org/projects/func
+Various. See https://fedorahosted.org/certmaster and
+https://fedorahosted.org/func
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/docs/certmaster.pod
^
|
@@ -18,11 +18,12 @@
=head1 ADDITONAL RESOURCES
See https://fedorahosted.org/certmaster/. It's a Wiki.
-
+See also
See also the manpages for "certmaster-request" and "certmaster-ca".
=head1 AUTHOR
-Various. See https://hosted.fedoraproject.org/projects/func
+Various. See https://fedorahosted.org/certmaster and
+https://fedorahosted.org/func
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/etc/certmaster.conf
^
|
@@ -9,4 +9,4 @@
certroot = /var/lib/certmaster/certmaster/certs
csrroot = /var/lib/certmaster/certmaster/csrs
cert_extension = cert
-
+sync_certs = False
|
[-]
[+]
|
Added |
certmaster-0.28.tar.bz2/etc/version
^
|
@@ -0,0 +1,5 @@
+version: 0.28
+release: 1
+source build date:
+git commit: 224352b0208b651c951d386bdbf9293c3365d531
+git date: Thu Apr 7 13:39:36 2011 -0400
|
[-]
[+]
|
Added |
certmaster-0.28.tar.bz2/etc/version~
^
|
@@ -0,0 +1,5 @@
+version: 0.27.1
+release: 1
+source build date:
+git commit: f33325800add0c2ca5886cc78c05e007a5be5e8e
+git date: Wed Jun 10 13:40:44 2009 -0400
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/init-scripts/certmaster
^
|
@@ -39,6 +39,7 @@
RVAL=3
echo "certmaster is not running"
fi
+ return $RVAL
}
if [ -f /lib/lsb/init-functions ]; then
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/scripts/certmaster-ca
^
|
@@ -7,6 +7,7 @@
import sys
import glob
+import optparse
import os
import certmaster
@@ -15,15 +16,17 @@
-from optparse import OptionParser
def errorprint(stuff):
print >> sys.stderr, stuff
+class CertmasterCAOptionParser(optparse.OptionParser):
+ def get_version(self):
+ return file("/etc/func/version").read().strip()
def parseargs(args):
usage = 'certmaster-ca <option> [args]'
- parser = OptionParser(usage=usage)
+ parser = CertmasterCAOptionParser(usage=usage,version=True)
parser.add_option('-l', '--list', default=False, action="store_true",
help='list signing requests remaining')
@@ -60,7 +63,7 @@
if opts.list:
hns = cm.get_csrs_waiting()
if hns:
- for hn in cm.get_csrs_waiting():
+ for hn in sorted(hns):
print hn
else:
print 'No certificates to sign'
@@ -101,7 +104,7 @@
signed_certs = cm.get_signed_certs(args)
- for i in signed_certs:
+ for i in sorted(signed_certs):
print i
return 0
@@ -113,7 +116,7 @@
cert_hashes = cm.get_cert_hashes(hostglobs)
- for i in cert_hashes:
+ for i in sorted(cert_hashes):
print i
return 0
|
[-]
[+]
|
Added |
certmaster-0.28.tar.bz2/scripts/certmaster-sync
^
|
@@ -0,0 +1,151 @@
+#!/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
+try:
+ import hashlib
+except ImportError:
+ # Python-2.4.z ... gah! (or even 2.3!)
+ import sha
+ class hashlib:
+ @staticmethod
+ def new(algo):
+ if algo == 'sha1':
+ return sha.new()
+ raise ValueError, "Bad checksum type"
+
+
+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 = hashlib.new('sha1')
+ 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()
|
[-]
[+]
|
Changed |
certmaster-0.28.tar.bz2/setup.py
^
|
@@ -4,7 +4,7 @@
#from setuptools import setup,find_packages
NAME = "certmaster"
-VERSION = open("version", "r+").read().split()[0]
+VERSION = "0.28"
SHORT_DESC = "%s remote configuration and management api" % NAME
LONG_DESC = """
A small pluggable xml-rpc daemon used by %s to implement various web services hooks
@@ -18,6 +18,9 @@
initpath = "/etc/init.d/"
logpath = "/var/log/%s/" % NAME
certdir = "/var/lib/%s/" % NAME
+ certmaster_cert_dir = "/var/lib/%s/%s" % (NAME,NAME)
+ certmaster_cert_certs_dir = "/var/lib/%s/%s/certs" % (NAME, NAME)
+ certmaster_cert_csrs_dir = "/var/lib/%s/%s/csrs" % (NAME, NAME)
trigpath = "/var/lib/%s/triggers/"% NAME
pkipath = "/etc/pki/%s" % NAME
rotpath = "/etc/logrotate.d"
@@ -26,12 +29,12 @@
name="%s" % NAME,
version = VERSION,
author = "Lots",
- author_email = "certmaster-list@redhat.com",
- url = "https://hosted.fedoraproject.org/projects/certmaster/",
+ author_email = "func-list@redhat.com",
+ url = "https://fedorahosted.org/certmaster/",
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
@@ -39,17 +42,23 @@
packages = ["%s" % NAME,
],
data_files = [(initpath, ["init-scripts/certmaster"]),
- (etcpath, ["etc/minion.conf"]),
- (etcpath, ["etc/certmaster.conf"]),
+ (etcpath, ["etc/minion.conf",
+ "etc/certmaster.conf",
+ "etc/version"]),
(manpath, ["docs/certmaster.1.gz"]),
(manpath, ["docs/certmaster-request.1.gz"]),
(manpath, ["docs/certmaster-ca.1.gz"]),
+ (manpath, ["docs/certmaster-sync.1.gz"]),
(rotpath, ['etc/certmaster_rotate']),
(logpath, []),
(certdir, []),
+ (certmaster_cert_dir, []),
+ (certmaster_cert_certs_dir, []),
+ (certmaster_cert_csrs_dir, []),
(etcpath, []),
(pkipath, []),
(aclpath, []),
+ ("%s/peers" % certdir, []),
("%s/sign/pre/" % trigpath, []),
("%s/sign/post/" % trigpath, []),
("%s/remove/pre/" % trigpath, []),
|
[-]
[+]
|
Changed |
version
^
|
@@ -1 +1 @@
-0.24 1
+0.28.1
|