recursive-include triggers *
include AUTHORS
include LICENSE
-include README
+include README.md
%dir /var/lib/certmaster/triggers/remove/post
/var/lib/certmaster/triggers/sign/post/certmaster-sync
/var/lib/certmaster/triggers/remove/post/certmaster-sync
-%doc AUTHORS README LICENSE
+%doc AUTHORS README.md LICENSE
%{_mandir}/man1/*.1.gz
import traceback
import os
import os.path
+import warnings
from OpenSSL import crypto
try:
@staticmethod
def new(algo):
if algo == 'sha1':
+ # TODO: jude: was warnings even available in 2.4 ?
+ warnings.warn("sha1 is deprecated", DeprecationWarning)
return sha.new()
raise ValueError, "Bad checksum type"
if not os.path.exists(s_cadir):
os.makedirs(s_cadir)
if not os.path.exists(s_ca_key_file) and not os.path.exists(s_ca_cert_file):
- certs.create_ca(CN=mycn, ca_key_file=s_ca_key_file, ca_cert_file=s_ca_cert_file)
+ certs.create_ca(CN=mycn, ca_key_file=s_ca_key_file, ca_cert_file=s_ca_cert_file, hash_function=a_ca.hash_function)
except (IOError, OSError), e:
print 'Cannot make certmaster certificate authority keys/certs for CA %s, aborting: %s' % (s_caname, e)
sys.exit(1)
if os.path.exists(csrfile):
oldfo = open(csrfile)
oldcsrbuf = oldfo.read()
- oldsha = hashlib.new('sha1')
+ oldsha = hashlib.new(certauth.hash_function)
oldsha.update(oldcsrbuf)
olddig = oldsha.hexdigest()
- newsha = hashlib.new('sha1')
+ newsha = hashlib.new(certauth.hash_function)
newsha.update(csrbuf)
newdig = newsha.hexdigest()
if not newdig == olddig:
certfile = '%s/%s.cert' % (certauth.certroot, requesting_host)
self.logger.info("Signing for csr %s requested" % certfile)
- thiscert = certs.create_slave_certificate(csrreq, certauth.cakey, certauth.cacert, certauth.cadir)
+ thiscert = certs.create_slave_certificate(csrreq, certauth.cakey, certauth.cacert, certauth.cadir, certauth.hash_function)
destfo = open(certfile, 'w')
destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, thiscert))
return cert
-def create_ca(CN="Certmaster Certificate Authority", ca_key_file=None, ca_cert_file=None):
+def create_ca(CN="Certmaster Certificate Authority", ca_key_file=None, ca_cert_file=None, hash_function='sha256'):
cakey = make_keypair(dest=ca_key_file)
careq = make_csr(cakey, cn=CN)
cacert = crypto.X509()
xt = crypto.X509Extension('basicConstraints',1,'CA:TRUE')
# FIXME - add subjectkeyidentifier and authoritykeyidentifier extensions, too)
cacert.add_extensions((xt,))
- cacert.sign(cakey, 'sha1')
+ cacert.sign(cakey, hash_function)
if ca_cert_file:
destfo = open(ca_cert_file, 'w')
destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cacert))
f.close()
-def create_slave_certificate(csr, cakey, cacert, cadir, slave_cert_file=None):
+def create_slave_certificate(csr, cakey, cacert, cadir, slave_cert_file=None, hash_function='sha256'):
cert = crypto.X509()
cert.set_serial_number(_get_serial_number(cadir))
cert.gmtime_adj_notBefore(0)
xt = crypto.X509Extension('basicConstraints', False ,'CA:FALSE')
# FIXME - add subjectkeyidentifier and authoritykeyidentifier extensions, too)
cert.add_extensions((xt,))
- cert.sign(cakey, 'sha1')
+ cert.sign(cakey, hash_function)
if slave_cert_file:
destfo = open(slave_cert_file, 'w')
destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
sync_certs = BoolOption(False)
peering = BoolOption(True)
peerroot = Option('/var/lib/certmaster/peers')
+ hash_function = Option('sha256')
class MinionConfig(BaseConfig):
log_level = Option('INFO')
import os
import sys
-import warnings
import copy
import urlparse
from ConfigParser import NoSectionError, NoOptionError, ConfigParser
self.cfg.write(fileobj)
def getConfigOption(self, option, default=None):
- warnings.warn('getConfigOption() will go away in a future version of Yum.\n'
+ warnings.warn('getConfigOption() will go away in a future version of certmaster.\n'
'Please access option values as attributes or using getattr().',
DeprecationWarning)
if hasattr(self, option):
return default
def setConfigOption(self, option, value):
- warnings.warn('setConfigOption() will go away in a future version of Yum.\n'
+ warnings.warn('setConfigOption() will go away in a future version of certmaster.\n'
'Please set option values as attributes or using setattr().',
DeprecationWarning)
if hasattr(self, option):
## Add the default items when just using a single ca
opts.ca[''] = BaseConfigDerived()
+ opts.ca[''].hash_function = None
opts.ca[''].populate(confparser,'main')
+ if opts.ca[''].hash_function == 'sha1':
+ log.warning('hash_function value of sha1 is deprecated', DeprecationWarning)
+ elif opts.ca[''].hash_function == 'md5':
+ print >> sys.stderr, "Error: hash_function of md5 is not supported"
+
## Add additonal ca sections
sections = confparser.sections()
for a_section in sections:
if a_section.startswith('ca:'):
ca_name = a_section[3:]
opts.ca[ca_name] = BaseConfigDerived()
+ opts.ca[ca_name].hash_function = None
opts.ca[ca_name].populate(confparser,a_section)
opts.ca[ca_name].cakey = None
opts.ca[ca_name].cacert = None
+
+ if opts.ca[ca_name].hash_function == 'sha1':
+ warnings.warn('hash_function value of sha1 is deprecated in ca:%s section' % ca_name, DeprecationWarning)
+ elif opts.ca[ca_name].hash_function == 'md5':
+ print >> sys.stderr, "Error: hash_function of md5 is not supported in ca:% section" % ca_name
return opts
import os
import sys
+import warning
try:
import hashlib
except ImportError:
@staticmethod
def new(algo):
if algo == 'sha1':
+ warnings.warn('sha1 is deprecated',DeprecationWarning)
return sha.new()
raise ValueError, "Bad checksum type"
def local_certs():
"""
- Returns (hostname, sha1) hash of local certs
+ Returns (hostname, hashval) hash of local certs
"""
globby = '*.%s' % cm.cfg.cert_extension
globby = os.path.join(cm.cfg.certroot, globby)
for f in files:
hostname = os.path.basename(f).replace('.' + cm.cfg.cert_extension, '')
dirname = os.path.dirname(f)
- digest = checksum(f)
+ digest = checksum(f,cm.cfg.hashfunc)
results.append([hostname, digest, dirname])
return results
-def checksum(f):
- thissum = hashlib.new('sha1')
+def checksum(f,hashfunc):
+ thissum = hashlib.new(hashfunc)
if os.path.exists(f):
fo = open(f, 'r')
data = fo.read()
certroot = /var/lib/certmaster/test/certs
csrroot = /var/lib/certmaster/test/csrs
+[ca:sha1]
+autosign = yes
+cadir = /etc/pki/certmaster/sha1-ca
+cert_dir = /etc/pki/certmaster/sha1
+certroot = /var/lib/certmaster/sha1/certs
+csrroot = /var/lib/certmaster/sha1/csrs
+hash_function = sha224
+
+[ca:sha224]
+autosign = yes
+cadir = /etc/pki/certmaster/sha224-ca
+cert_dir = /etc/pki/certmaster/sha224
+certroot = /var/lib/certmaster/sha224/certs
+csrroot = /var/lib/certmaster/sha224/csrs
+hash_function = sha224
+
[ca:test]
cert_dir = /etc/pki/certmaster-test
+hash_function = sha256
+
+[ca:sha1]
+cert_dir = /etc/pki/certmaster-sha1
+hash_function = sha1
+
+[ca:sha224]
+cert_dir = /etc/pki/certmaster-sha224
+hash_function = sha224
subject=`openssl x509 -in /etc/pki/certmaster-test/testcert.pwan.co.cert -subject -noout`
[[ $subject == *"CN=testcert.pwan.co"* ]]
+ openssl x509 -in /etc/pki/certmaster-test/testcert.pwan.co.cert -text | grep Signature | grep sha256
+ assertTrue "testcert.pwan.co.cert has a sha256 hash" $?
+
openssl rsa -in /etc/pki/certmaster-test/testcert.pwan.co.pem -check > /dev/null 2>&1
assertTrue "test.pwan.co.pem OK" $?
openssl req -text -noout -verify -in /etc/pki/certmaster-test/testcert.pwan.co.csr > /dev/null 2>&1
}
+test_MD5CA_Attempy() {
+
+ # TODO: Verify attempts to create MD5 certs fail
+ assertTrue "TODO" false
+}
+
+test_Sha1CA_Autosigning() {
+
+ # TODO: Verify a deprecation warning was issued ?
+
+ certmaster-request --hostname testcert.pwan.co --ca sha1
+ openssl x509 -in /etc/pki/certmaster-sha1/testcert.pwan.co.cert -text | grep Signature | grep sha1
+ assertTrue "testcert.pwan.co.cert has a sha1 hash" $?
+
+}
+
+test_Sha224CA_Autosigning() {
+
+ # TODO: Verify /etc/pki/certmaster-test/testcert.pwan.co.cert is using sha224
+ certmaster-request --hostname testcert.pwan.co --ca sha224
+ openssl x509 -in /etc/pki/certmaster-sha224/testcert.pwan.co.cert -text | grep Signature | grep sha224
+ assertTrue "testcert.pwan.co.cert has a sha224 hash" $?
+
+}
+
test_DefaultCA_NonAutosigning() {
# Turn on job control, so 'fg' is available