pull/4/merge
gwaters 2017-03-22 01:01:44 +00:00 committed by GitHub
commit 3869b008c0
3 changed files with 86 additions and 41 deletions

View File

@ -22,3 +22,11 @@ csrgen <hostname> -s <san0> <san1>
``` ```
python csrgen test.test.com -s mushu.test.com pushu.test.com python csrgen test.test.com -s mushu.test.com pushu.test.com
``` ```
When you do not want to be prompted for locality, you can use a config file.
This can be acheived by adding -c. (SAN request still work)
Usage: csrgen <hostnaem> -c your_config -s <san0> <san1>
```
python csrgen test.test.com -c csrgen.conf -s mushu.test.com pushu.test.com
```

113
csrgen.py
View File

@ -9,16 +9,18 @@
# #
# Author: Courtney Cotton <cotton@cottoncourtney.com> 06-25-2014 # Author: Courtney Cotton <cotton@cottoncourtney.com> 06-25-2014
# Libraries/Modules # Contributor: Gary Waters <gwaters@caltech.edu> 01-05-2017 (added external config file)
# Libraries/Modules
import argparse import argparse
import ConfigParser
from OpenSSL import crypto from OpenSSL import crypto
# Generate Certificate Signing Request (CSR) # Generate Certificate Signing Request (CSR)
def generateCSR(nodename, sans = []): def generateCSR(nodename, sans = [], config_file = None):
while True: while not config_file:
C = raw_input("Enter your Country Name (2 letter code) [US]: ") C = raw_input("Enter your Country Name (2 letter code) [US]: ")
if len(C) != 2: if len(C) != 2:
print "You must enter two letters. You entered %r" % (C) print "You must enter two letters. You entered %r" % (C)
@ -40,53 +42,80 @@ def generateCSR(nodename, sans = []):
print "Please enter your OU." print "Please enter your OU."
continue continue
# Allows you to permanently set values required for CSR # Allows you to permanently set values required for CSR
# To use, comment raw_input and uncomment this section. # To use, comment raw_input and uncomment this section.
# C = 'US' # C = 'US'
# ST = 'New York' # ST = 'New York'
# L = 'Location' # L = 'Location'
# O = 'Organization' # O = 'Organization'
# OU = 'Organizational Unit' # OU = 'Organizational Unit'
csrfile = 'host.csr' csrfile = 'host.csr'
keyfile = 'host.key' keyfile = 'host.key'
TYPE_RSA = crypto.TYPE_RSA TYPE_RSA = crypto.TYPE_RSA
# Appends SAN to have 'DNS:' # Appends SAN to have 'DNS:'
ss = [] ss = []
for i in sans: for i in sans:
ss.append("DNS: %s" % i) ss.append("DNS: %s" % i)
ss = ", ".join(ss) ss = ", ".join(ss)
req = crypto.X509Req() req = crypto.X509Req()
req.get_subject().CN = nodename req.get_subject().CN = nodename
if config_file:
config = ConfigParser.ConfigParser()
conf = {}
try:
file = open(config_file, 'r')
config.read(config_file)
conf.update({"country_name": config.get("location", "country_name")})
conf.update({"state_or_province_name": config.get("location", "state_or_province_name")})
conf.update({"locality_name": config.get("location", "locality_name")})
conf.update({"organization_name": config.get("location", "organization_name")})
conf.update({"organizational_unit_name": config.get("location", "organizational_unit_name")})
req.get_subject().countryName = conf['country_name']
req.get_subject().stateOrProvinceName = conf['state_or_province_name']
req.get_subject().localityName = conf['locality_name']
req.get_subject().organizationName = conf['organization_name']
req.get_subject().organizationalUnitName = conf['organizational_unit_name']
file.close()
except IOError:
print "Error: File not found: %s" % config_file
exit(-1)
except Exception, error:
print "Error: %s " % error
exit(-1)
else:
req.get_subject().countryName = C req.get_subject().countryName = C
req.get_subject().stateOrProvinceName = ST req.get_subject().stateOrProvinceName = ST
req.get_subject().localityName = L req.get_subject().localityName = L
req.get_subject().organizationName = O req.get_subject().organizationName = O
req.get_subject().organizationalUnitName = OU req.get_subject().organizationalUnitName = OU
# Add in extensions
base_constraints = ([
crypto.X509Extension("keyUsage", False, "Digital Signature, Non Repudiation, Key Encipherment"),
crypto.X509Extension("basicConstraints", False, "CA:FALSE"),
])
x509_extensions = base_constraints
# If there are SAN entries, append the base_constraints to include them.
if ss:
san_constraint = crypto.X509Extension("subjectAltName", False, ss)
x509_extensions.append(san_constraint)
req.add_extensions(x509_extensions)
# Utilizes generateKey function to kick off key generation.
key = generateKey(TYPE_RSA, 2048)
req.set_pubkey(key)
#update sha? # Add in extensions
#req.sign(key, "sha1") base_constraints = ([
req.sign(key, "sha256") crypto.X509Extension("keyUsage", False, "Digital Signature, Non Repudiation, Key Encipherment"),
crypto.X509Extension("basicConstraints", False, "CA:FALSE"),
])
x509_extensions = base_constraints
# If there are SAN entries, append the base_constraints to include them.
if ss:
san_constraint = crypto.X509Extension("subjectAltName", False, ss)
x509_extensions.append(san_constraint)
req.add_extensions(x509_extensions)
# Utilizes generateKey function to kick off key generation.
key = generateKey(TYPE_RSA, 2048)
req.set_pubkey(key)
generateFiles(csrfile, req) #update sha?
generateFiles(keyfile, key) #req.sign(key, "sha1")
req.sign(key, "sha256")
return req generateFiles(csrfile, req)
generateFiles(keyfile, key)
return req
# Generate Private Key # Generate Private Key
def generateKey(type, bits): def generateKey(type, bits):
@ -116,9 +145,11 @@ def generateFiles(mkFile, request):
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("name", help="Provide the FQDN", action="store") parser.add_argument("name", help="Provide the FQDN", action="store")
parser.add_argument("-s", "--san", help="SANS", action="store", nargs='*', default="") parser.add_argument("-s", "--san", help="SANS", action="store", nargs='*', default="")
parser.add_argument("-c", "--config", help="Config_File", action="store", default="")
args = parser.parse_args() args = parser.parse_args()
hostname = args.name hostname = args.name
sans = args.san sans = args.san
config_file = args.config
generateCSR(hostname, sans) generateCSR(hostname, sans, config_file)

6
example-csrgen.conf Normal file
View File

@ -0,0 +1,6 @@
[location]
country_name = US
state_or_province_name = California
locality_name = San Francisco
organization_name = FTW Enterprise
organizational_unit_name = WOW