def submit_domain(did): choices = ['ov', 'ev', 'ovcs', 'evcs'] type = input('Validate for [ov, ev, ovcs, evcs]? ') while type not in choices: colorize('red') choices = input( 'Please choose one of the following validation types: [ov, ev, ovcs, evcs] ' ) colorize_edit('reset') type = choices payload = json.dumps( {"validations": [{ "type": type, "user": { "id": did } }]}) req_url = url + '/' + did + '/validation' req = requests.post(req_url, headers=headers_post, data=payload) rest_status(req) if req.status_code == 204: colorize('green') print('Domain submitted for ' + type + ' validation.\n') colorize_edit('reset') return req
def gen_key(alg): if alg == 'rsa': print('Generating new private key') size = int(input('Choose a bit size between [2048-4096]: ')) while not size >= 2048 and size <= 4096: print('Choose 2048, 3072, or 4096.') size = int(input('')) key = rsa.generate_private_key( public_exponent=65537, key_size=size, backend=default_backend() ) elif alg == 'ecc': curve = input('Use a p256, p384, or p521 curve? ') while not curve in ['p256','p384','p521']: colorize('red') curve = input('Use a p256, p384, or p521 curve? ') colorize_edit('reset') if curve == 'p256': key = ec.generate_private_key(ec.SECP256R1(), default_backend()) elif curve == 'p384': key = ec.generate_private_key(ec.SECP384R1(), default_backend()) elif curve == 'p521': key = ec.generate_private_key(ec.SECP521R1(), default_backend()) return key
def delete_usr(uid): req_url = url + '/' + str(uid) req = requests.delete(req_url, headers=headers_get) rest_status(req) if req.status_code == 204: colorize('green') print('Successfully deleted user.\n') colorize_edit('reset')
def update_request(rid, status, comment): req_url = 'https://www.digicert.com/services/v2/request/' + str(rid) + '/status' if status == 'submitted' or 'pending' or 'approved' or 'rejected': payload = json.dumps({ 'status': status, 'processor_comment': comment}) req = requests.put(req_url, headers=headers_post, data=payload) rest_status(req) else: colorize('red') print('Please enter valid status. [ submitted, pending, approved, rejected ]') colorize_edit('reset')
def revoke_cert(cid, comment): req_url = 'https://www.digicert.com/services/v2/order/certificate/' + cid + '/revoke' payload = json.dumps( { 'comments': comment } ) req = requests.put(req_url, headers=headers_post, data=payload) rest_status(req) resp = req.json() if resp.get('status'): colorize('cyan') print('A request to revoke order ' + cid + ' was successfully submitted on ' + resp['date']) colorize_edit('reset') return resp
def decode_cert(cert_path): # Open certificate and deserialize with open(str(cert_path),'rb') as rf: pem_obj = rf.read() if pem.detect(pem_obj): type, _, _ = pem.unarmor(pem_obj) # Determine type of certificate if type == "PKCS7": pkcs7 = crypto.load_pkcs7_data(crypto.FILETYPE_PEM,pem_obj) certs = get_certificates(pkcs7) count = 0 for cert in certs: pem_cert = x509.load_pem_x509_certificate(cert, default_backend()) # Print cert issued to colorize('green') print('Issued to: (Chain ' + str(count) + ')') count += 1 colorize_edit('reset') print(pem_cert.subject.rfc4514_string()) print("Serial No: " + str(pem_cert.serial_number)) print("Fingerprint: " + str(base64.b64encode(pem_cert.fingerprint(hashes.SHA256())), 'utf-8')) print("Valid from: " + str(pem_cert.not_valid_before)) print("Valid to: " + str(pem_cert.not_valid_after)) print("Signature hash algorithm: " + pem_cert.signature_hash_algorithm.name) # Print issued by colorize('green') print('Issued by: ') colorize_edit('reset') print(pem_cert.issuer.rfc4514_string()) print('\n') elif type == "CERTIFICATE": cert = x509.load_pem_x509_certificate(pem_obj, default_backend()) # Print cert issued to colorize('green') print('Issued to: ') colorize_edit('reset') print(cert.subject.rfc4514_string()) print("Serial No: " + str(cert.serial_number)) print("Fingerprint: " + str(base64.b64encode(cert.fingerprint(hashes.SHA256())), 'utf-8')) print("Valid from: " + str(cert.not_valid_before)) print("Valid to: " + str(cert.not_valid_after)) print("Signature hash algorithm: " + cert.signature_hash_algorithm.name) # Print issued by colorize('green') print('Issued by: ') colorize_edit('reset') print(cert.issuer.rfc4514_string()) else: raise TypeError('Not a PEM or PKCS7 file.')
def edit_usr(uid): req_url = url + '/' + str(uid) uname = input('Enter a new username: '******'Enter a new first name: ') lname = input('Enter a new last name: ') email = input('Enter a new email: ') job = input('Enter a new job title: ') phone = input('Enter a new phone number: ') payload = json.dumps({ 'username': uname, 'first_name': fname, 'last_name': lname, 'email': email, 'job_title': job, 'telephone': phone }) req = requests.put(req_url, headers=headers_post, data=payload) rest_status(req) if req.status_code == 204: colorize('green') print('Successfully updated user.\n') colorize_edit('reset')
def new_usr(): username = input("Enter a username: "******"Enter a firstname: ") l_name = input("Enter a lastname: ") email = input("Enter a email: ") job = input("Enter a job title: ") phone = input("Enter a phone number: ") payload = json.dumps({ 'username': username, 'first_name': f_name, 'last_name': l_name, 'email': email, 'job_title': job, 'telephone': phone, 'container': { 'id': root_container() }, 'access_roles': [{ 'id': rid }] }) req = requests.post(url, headers=headers_post, data=payload) rest_status(req) if req.status_code == 201: colorize('green') print('Successfully created new user. New User ID: ' + str(req.json()['id'])) print('\n') colorize_edit('reset') else: colorize('red') print('Error: ' + str(req.status_code)) colorize_edit('reset') else: colorize('red') print("Username is taken. Try a different one.\n") colorize_edit('reset')
def dcli(): # Main ArgParse Parser parser = argparse.ArgumentParser(prog='dcli', add_help=True) subparsers = parser.add_subparsers(dest='cmd') # Main options parser.add_argument("--init", help="Initialize configuration scripts", action="store_true") parser.add_argument("--init-org", help="Validate a organization", action="store_true") parser.add_argument("--init-dom", help="Validate a domain", action="store_true") # Argparse Certificate Management Sub Parser parser_cert = subparsers.add_parser('crt') parser_cert.add_argument("-l", "--list-crt", help="List all orders", action='store_true') parser_cert.add_argument("-v", "--view-crt", help="View order details by id") parser_cert.add_argument("-n", "--new-crt", help="New order, requires csr", choices=['ov', 'ev', 'cs', 'evcs']) parser_cert.add_argument("-r", "--revoke-crt", help="Revoke order") parser_cert.add_argument("-e", "--edit-crt", help="Edit order (reissue)") parser_cert.add_argument("-d", "--duplicate-crt", help="Create copy of an order with a different CSR") parser_cert.add_argument("-a", "--duplicate-list", help="List the duplicate certificates of an order") # Argparse Domain Management Sub Parser parser_dom = subparsers.add_parser('dom') parser_dom.add_argument("-l", "--list-dom", help="List active domains", action="store_true") parser_dom.add_argument("-a", "--activate-dom", help="Activate domain") parser_dom.add_argument("-d", "--deactivate-dom", help="Deactivate domain") parser_dom.add_argument("-s", "--submit-dom", help="Submit domain for validation") parser_dom.add_argument("-dcv", help="Domain control verification", choices=['txt', 'cname', 'email', 'http']) parser_dom.add_argument("-dns", help ="Test DNS to complete DCV", choices=['txt','cname']) parser_dom.add_argument("-n", "--new-dom", help="New domain", choices=['ov','ev']) parser_dom.add_argument("-v", "--view-dom", help="View domain details by id") # Argparse Organization Management Sub Parser parser_org = subparsers.add_parser('org') parser_org.add_argument("-l", "--list-org", help="List organizations", action="store_true") parser_org.add_argument("-v", "--view-org", help="View details of organization by org id") # argparse Request Management Sub Parser parser_req = subparsers.add_parser('req') parser_req.add_argument('-l', '--list-req', help='List all pending requests', choices=['pending','all']) parser_req.add_argument('-v', '--view-req', help='View request details') parser_req.add_argument('-r', '--reject-req', help='Reject a pending certificate request by id.') parser_req.add_argument('-a', '--approve-req', help='Approve a pending certificate request by id.') # Argparse User Management Sub Parser parser_usr = subparsers.add_parser('usr') parser_usr.add_argument("-n", "--new-usr", help="New user account", action='store_true') parser_usr.add_argument("-e", "--edit-usr", help="Edit user account") parser_usr.add_argument("-v", "--view-usr", help="View existing user account") parser_usr.add_argument("-d", "--delete-usr", help="Delete user account") parser_usr.add_argument("-l", "--list-usr", help="List user accounts", action="store_true") parser_usr.add_argument("-c", "--check-api", help="Check Digicert API key for permissions.", action="store_true") # Argparse Cryptography Sub Parser parser_crypto = subparsers.add_parser('crypto') parser_crypto.add_argument('--new-csr', help="Create a new CSR and private key", choices=['ecc', 'rsa']) parser_crypto.add_argument('--new-key', help='Create a new private key', choices=['ecc', 'rsa']) parser_crypto.add_argument('--decode-crt', help='View encoded details in the certificate') parser_crypto.add_argument('--decode-csr', help='View encoded details in the CSR') parser_crypto.add_argument('--test-csr', help='Generate hash of CSR') parser_crypto.add_argument('--test-key', help='Generate hash of private key') parser_crypto.add_argument('--test-crt', help='Generate hash of certificate') # Parse argument list args = parser.parse_args() # Initial configuration if args.init: print("Running configuration scripts. This will overwrite any existing files.") # Collect user input key = input("Enter your Digicert API key: ") dir = Path(input("Where do you want to save everything? [./] ")) conf = Path(dir / 'conf.d') file = str(Path(conf / 'init.conf')) # If dir exists if dir.exists(): print('Directory already exists') # Else create dir else: os.mkdir(str(dir)) os.mkdir(str(conf)) # Delete existing init.conf if main_conf.exists(): os.remove(str(main_conf.resolve())) # Create init.conf parser = configparser.ConfigParser() parser.read(file) parser.add_section('DigiUtil-Cli Conf') parser.add_section('Organization Validation') parser.add_section('Domain Validation') parser.set('DigiUtil-Cli Conf', 'api_key', key) parser.set('DigiUtil-Cli Conf', 'cert_lib', str(dir.resolve())) with open(file, "w+") as f: parser.write(f) print('init.conf was saved in: ' + str(conf.resolve())) else: # Create init.conf parser = configparser.ConfigParser() parser.read('init.conf') parser.add_section('DigiUtil-Cli Conf') parser.add_section('Organization Validation') parser.add_section('Domain Validation') parser.set('DigiUtil-Cli Conf', 'api_key', key) parser.set('DigiUtil-Cli Conf', 'cert_lib', str(dir)) with open(file, 'w+') as f: parser.write(f) print('init.conf was saved in: ' + str(conf.resolve())) # Validate org if args.init_org: reval = input('Is this the FIRST time registering the org with Digicert? (Create new org) [y/n] ') if reval == 'y': new_org() elif reval == 'n': list = list_org('n', 'y') pages = paginate(list, 5) org = input('Enter the id of the org you want to validate: ') # Get org name and confd path org_name = view_org(org)['name'] conf = Path(confd_org / str(org + '.conf')) if os.path.exists(str(conf)): os.remove(str(conf)) # Add org to init.conf p1 = configparser.ConfigParser() p1.read(str(main_conf.resolve())) p1.set('Organization Validation', str('org_' + org), str(Path(conf))) with open(str(main_conf.resolve()), 'w') as f: p1.write(f) # Create org entry in key.d key_dir = Path( keyd / org_name ) if not os.path.exists(str(key_dir)): os.makedirs(str(key_dir)) # Get active org validations vals = active_org_val(org) a = [] if vals.get('validations'): for val in vals['validations']: # If active, set in configuration file if val['status'] == 'active': a.append(val['type']) # Else submit for validation else: submit_org(org) # Create org.conf p2 = configparser.ConfigParser() p2.read(str(conf)) p2.add_section('Initialized Org') p2.set('Initialized Org', 'id', org) p2.set('Initialized Org', 'name', org_name) p2.set('Initialized Org', 'validated_for', ', '.join(a)) p2.set('Initialized Org', 'key_dir', str(key_dir.resolve())) with open(str(conf), 'w+') as f: p2.write(f) else: 'Please choose y or n' # If no active validations, submit for validation print('Org ' + org + ' was initialized: ' + str(conf)) # Validate domain if args.init_dom: print('Initializing domain...') # Pick from list of existing domains resp = list_domains() list = [] col = ['Domain ID', 'Domain', 'Activated', 'Validation Status'] list.append(col) for dom in resp["domains"]: if dom.get('validations'): array = [] array.append(str(dom['id'])) array.append(dom['name']) if dom['is_active'] == True: array.append('yes') else: array.append('no') for validated in dom['validations']: val_array = [] val_array.append(validated['type']) array.append(', '.join(val_array)) list.append(array) else: array = [] array.append(str(dom['id'])) array.append(dom['name']) if dom['is_active'] == True: array.append('yes') else: array.append('no') array.append('') list.append(array) paginate(list, 10) # Get domain info by did did = input('Which domain do you want to configure? (Use domain id) ') dom_resp = view_domain(did,'json') # Get org.conf path x = str(dom_resp['organization']['id']) + '.conf' org_conf = Path(confd_org / x) # Print error if org.conf doesnt exist if not os.path.exists(str(org_conf)): print('Error: Initialize org ' + str(dom_resp['organization']['id'])) else: conf = Path(confd_dom / str(did + '.conf')) if os.path.exists(str(conf)): os.remove(str(conf)) # Add domain to init.conf p1 = configparser.ConfigParser() p1.read(str(main_conf)) p1.set('Domain Validation', str('dom_' + did), str(Path(conf))) with open(str(main_conf), 'w') as f: p1.write(f) # Create domain.conf p2 = configparser.ConfigParser() p2.read(str(conf)) p2.add_section('Initialized Domain') p2.set('Initialized Domain', 'id', did) p2.set('Initialized Domain', 'name', dom_resp['name']) p2.set('Initialized Domain', 'org', str(dom_resp['organization']['id'])) p2.set('Initialized Domain', 'dcv_status', dom_resp['status']) # If domain is validated, set validation if dom['is_active'] == True: p2.set('Initialized Domain', 'activated', 'yes') # Else submit domain for validation else: p2.set('Initialized Domain', 'activated', 'no') submit_domain(did) with open(str(conf), 'w+') as f: p2.write(f) print('Domain ' + did + ' was initialized: ' + str(conf)) # If crt subparser if args.cmd == 'crt': # List orders on account if args.list_crt: try: resp = list_cert() paginate(resp,10) except: raise Exception('Unable to list certificates.') # View a orders details if args.view_crt: try: resp = view_cert(args.view_crt, 'list') paginate(resp,10) except: raise TypeError('Argument is not an integer.') # Enroll in new certificate if args.new_crt: try: new_cert(args.new_crt) except: raise Exception('Unable to enroll new certificate.') # Revoke certificate if args.revoke_crt: try: cmt = input('Why are you revoking this order? ') revoke_cert(args.revoke_crt, cmt) except: raise Exception('Unable to revoke certificate.') # Edit certificate order if args.edit_crt: try: reissue_cert(args.edit_crt) except: raise Exception('Unable to reissue certificate.') # Get duplicate certificate if args.duplicate_crt: try: duplicate_cert(args.duplicate_crt) except: raise Exception('Unable to request duplicate certificate.') # List all created duplicates on an order if args.duplicate_list: try: resp = list_duplicates(args.duplicate_list) # Create pages from json list = [] col = ['Commmon Name', 'Serial Number', 'Status', 'Date Issued', 'Valid Till', 'Key Size', 'Requested By'] list.append(col) for i in resp['certificates']: array = [] array.append(i['common_name']) array.append(i['serial_number']) array.append(i['status']) array.append(i['valid_from']) array.append(i['valid_till']) array.append(str(i['key_size'])) fname = i['firstname'] lname = i['lastname'] usrname = fname + ' ' + lname array.append(usrname) list.append(array) paginate(list,10) except: raise Exception('Unable to list duplicate certificates of order ' + str(args.duplicate_list)) # If dom subparser if args.cmd == 'dom': # List Domains if args.list_dom: try: resp = list_domains() list = [] col = ['Domain ID','Domain Name','Parent Org','Parent Org ID','DCV Method','Validated For'] list.append(col) for domain in resp['domains']: if domain['is_active'] == True: array = [] array.append(str(domain['id'])) array.append(domain['name']) array.append(domain['organization']['name']) array.append(str(domain['organization']['id'])) if domain.get('dcv_method'): if domain['dcv_method'] == 'dns-cname-token': array.append('cname') elif domain['dcv_method'] == 'dns-txt-token': array.append('txt') elif domain['dcv_method'] == 'http-token': array.append('http') elif domain['dcv_method'] == 'email': array.append('email') else: array.append('') array_val = [] if domain.get('validations'): for val in domain['validations']: if val['status'] == 'active': array_val.append(val['type']) array.append(', '.join(array_val)) list.append(array) paginate(list,10) except: raise LookupError('Unable to list domains on account.') # Activate domain if args.activate_dom: try: resp = activate_domain(args.activate_dom) if resp.status_code == 204: colorize('green') print('Domain ' + str(args.activate_dom) + ' has been activated.\n') colorize_edit('reset') except: raise LookupError('Unable to activate the domain with Digicert.') # Deactivate domain if args.deactivate_dom: try: resp = deactivate_domain(args.deactivate_dom) if resp.status_code == 204: colorize('green') print('Domain ' + str(args.deactivate_dom) + ' has been deactivated.\n') colorize_edit('reset') except: raise LookupError('Unable to deactivate the domain with Digicert.') # Submit domain for validation if args.submit_dom: try: resp = submit_domain(args.submit_dom) except: raise LookupError('Unable to submit domain for validation.') # Domain control verification if args.dcv: try: do_dcv(args.dcv) except: raise LookupError('Unable to submit domain for domain control verification.') # Check DNS for DCV if args.dns: try: token = input('Enter the random string: ') did = input('Enter the domain ID: ') resp = test_dns(did, args.dns, token) print('Domain ID ' + did + ' has been approved. Status: ' + resp['status']) except: raise LookupError('Failed to test DNS records.') # Add a new domain if args.new_dom: try: print('Org must first be approved for OV or EV to create domain.') dom_name = input('Enter the new domain name: ') while not regex_test.match(dom_name): dom_name = input('Enter a valid domain name: ') list = [] col = ['Org ID','Org Name','St Address', 'Validation Status'] list.append(col) org_list = list_org('y','y') paginate(org_list,10) oid = input('Create domain under which org? [Enter Org ID] ') resp = new_domain(dom_name, oid, args.new_dom) print('Domain ' + dom_name + ' has been created. Domain ID: ' + str(resp['id'])) except: raise LookupError('Unable to create new domain with Digicert.') # View domain information by domain id if args.view_dom: try: resp = view_domain(args.view_dom, 'list') paginate(resp,10) except: raise LookupError('Unable to grab domain information from Digicert.') # If crt subparser if args.cmd == 'org': # List organization if args.list_org: try: resp = list_org('y','y') paginate(resp,10) except: raise LookupError('Unable to retrieve information from Digicert.') # View organization details if args.view_org: try: resp = view_org(args.view_org) list = [] col = ['Org ID', 'Org Name', 'Address', 'Phone', 'Org Contact', 'Activated'] list.append(col) array = [] array.append(str(resp['id'])) array.append(resp['name']) array.append(resp['address']) array.append(resp['telephone']) contact = resp['organization_contact']['first_name'] + ' ' + resp['organization_contact']['last_name'] array.append(contact) array.append(str(resp['is_active'])) list.append(array) paginate(list,10) except: raise LookupError('Unable to vretrieve org information from Digicert.') # If request subparser if args.cmd == 'req': # List requests if args.list_req: try: if args.list_req == 'pending': resp = list_requests('y','y') paginate(resp,10) if args.list_req == 'all': resp = list_requests('y','n') paginate(resp,10) except: raise LookupError('Unable to retrieve request information from Digicert.') # View request if args.view_req: try: req = view_request(args.view_req) list = [] col = ['Request ID', 'Date Requested', 'Status', 'Type', 'Order ID', 'Requested By', 'Approved By'] list.append(col) array = [] array.append(str(req['id'])) array.append(req['date']) array.append(req['status']) array.append(req['type']) array.append(str(req['order']['id'])) requester_fname = req['requester']['first_name'] requester_lname = req['requester']['last_name'] requester_name = requester_fname + ' ' + requester_lname array.append(requester_name) if req.get('processor'): approver_fname = req['processor']['first_name'] approver_lname = req['processor']['last_name'] approver_name = approver_fname + ' ' + approver_lname array.append(approver_name) else: approver_name = ' ' array.append(approver_name) list.append(array) paginate(list,10) except: raise LookupError('Unable to retrieve request information from Digicert.') # Reject pending request if args.reject_req: try: cmt = input('Why are you rejecting this request? ') update_request(args.reject_req,'rejected',cmt) colorize('cyan') print('Successfully rejected request.') colorize_edit('reset') except: raise LookupError('Unable to update request status with Digicert.') # Approve pending request if args.approve_req: try: cmt = input('Why are you approving this request? ') update_request(args.approve_req,'approved',cmt) colorize('cyan') print('Successfully approved request.') colorize_edit('reset') except: raise LookupError('Unable to update request status with Digicert.') # If user subparser if args.cmd == 'usr': # Add a new user if args.new_usr: try: resp = new_usr() except: raise LookupError('Unable to create new user with Digicert.') # Edit an existing user if args.edit_usr: try: edit_usr(args.edit_usr) except: raise LookupError('Unable to edit user information with Digicert.') # View information about a user if args.view_usr: try: view_usr(args.view_usr) except: raise LookupError('Unable to retrieve user information from Digicert.') # Delete a user if args.delete_usr: try: delete_usr(args.del_usr) except: raise LookupError('Unable to delete user from the Digicert account.') # List all users on account if args.list_usr: try: resp = list_usr('y') paginate(resp,10) except: raise LookupError('Unable to retrieve user information from Digicert.') # Check API Key permissions if args.check_api: try: resp = check_api_key() list = [] col = ['Username', 'Status', 'Access Role', 'Division'] list.append(col) array = [] array.append(resp['username']) array.append(resp['status']) roles = [] for role in resp['access_roles']: roles.append(role['name']) array.append(', '.join(roles)) array.append(resp['container']['name']) list.append(array) paginate(list, 10) except: raise Exception('Unable to check status of API key.') # If cryptography subparser if args.cmd == 'crypto': if args.new_csr: try: # Get UTF 8 encoded CSR gen_custom_csr(args.new_csr) except: raise Exception('Failed to generate new CSR and private key.') if args.new_key: try: # Get UTF 8 encoded key key = gen_key(args.new_key) with open('private.key','wb') as sf: sf.write(key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() )) except: raise Exception('Failed to generate new private key') if args.decode_crt: cert_path = Path(str(args.decode_crt)) # Validate filepath to cert try: if cert_path.exists() and cert_path.is_file(): serialized = decode_cert(cert_path) except: raise Exception('Failed to decode certificate.')
def new_cert(type): # Pick org orgs = get_active_org() list = [] col = ['Org id', 'Org Name', 'Display Name'] list.append(col) for org in orgs['organizations']: array = [] array.append(str(org['id'])) array.append(org['name']) array.append(org['display_name']) list.append(array) paginate(list,10) oid = input('Pick organization id: ') # Get org name with oid org_name = view_org(oid)['name'] # Test common name cn = input('Enter a common name: ') while not regex_test.match(cn): cn = input('Enter a valid common name: ') # Get array of SANs sans = [] print('Type Subject Alternate Name and press enter (Enter d when done):') while 1 == 1: san = input('') if san == 'd': break elif not regex_test.match(san): print(san + ' is not a valid SAN') else: sans.append(san) # Create new entry in key.d for order x = oid + '.conf' org_conf = Path(confd_org / x) if not os.path.exists(str(org_conf)): print('Error: Initialize org ' + oid) else: # Saves key and csr temporarily in the org folder until order id is created with open(str(org_conf)) as oc: p = ConfigParser() p.read(str(org_conf)) safe = p.get('Initialized Org', 'key_dir') key_path = safe + '/private.key' csr_path = safe + '/request.csr' # Generate and save private key alg = input('Create a ECC or RSA private key? ' ) while not alg in ['ecc','rsa']: colorize('red') alg = input('Enter ECC or RSA: ') colorize_edit('reset') key = gen_key(alg) with open(key_path, 'wb+') as f: f.write(key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() )) # Generate a CSR from private key csr = gen_csr(key) # Save csr with open(csr_path, 'w+') as f: f.write(csr) # Choose signature hash algs = ['1] sha256', '2] sha384', '3] sha512'] print('Signature hash algorithms') print(*algs, sep='\t') alg = int(input('Choose an algorithm [1-3]: ')) if alg == 1: hash_alg = 'sha256' elif alg == 2: hash_alg = 'sha384' elif alg == 3: hash_alg = 'sha512' else: hash_alg = 'sha256' print('Default delected: sha256') # Choose validity period val_periods = ['1] 1 year', '2] 2 year', '3] Custom Expiration'] print(*val_periods, sep='\t') val_period = int(input('Choose certificate lifetime [1-3]: ')) if val_period == 1: time = 1 elif val_period == 2: time = 2 else: time = 3 custom = input('Pick a custom certificate lifetime in format YYYY-MM-DD: ') regx = re.compile('([0-9]{4}(\-){1}([0-9]){2}(\-){1}([0-9]){2})') while not regx.match(custom): print('Incorrect format. Try again.') custom = input('Pick a custom certificate lifetime in format YYYY-MM-DD: ') # List options for file format formats = ['1] p7b', '2] pem', '3] pem bundle', '4] code signing', '5] other'] print('Possible file formats: ') print(*formats, sep='\t') format = int(input('Choose a format [1-5]: ')) # Choose server platform if format == 1: platform = 10 elif format == 2: platform = 2 elif format == 3: platform = 45 elif format == 4: platform = 55 elif format == 5: platform = -1 # Set server platform to Sun Java for code signing elif args.new_cert == 'cs': platform = 55 else: print('Default chosen: pem format') platform = -1 # If custom expiraion, include correct payload if time == 1 or time == 2: payload = { 'certificate': { 'common_name': cn, 'dns_names': sans, 'csr': csr, 'server_platform': { 'id': int(platform) }, 'signature_hash': hash_alg }, 'organization': { 'id': int(oid) }, 'validity_years': int(time), 'product': { 'type_hint': type } } else: print('Time == 3') payload = { 'certificate': { 'common_name': cn, 'dns_names': sans, 'csr': str(csr.public_bytes(serialization.Encoding.PEM), 'utf-8'), 'server_platform': { 'id': int(platform) }, 'signature_hash': hash_alg }, 'organization': { 'id': int(oid) }, 'validity_years': 1, 'custom_expiration_date': custom, 'product': { 'type_hint': type } } payload_data = json.dumps(payload) req_url = url + '/ssl' req = requests.post(req_url, headers=headers_post, data=payload_data) rest_status(req) # Move key to new key.d with open(str(org_conf)): p = ConfigParser() p.read(str(org_conf)) safe = p.get('Initialized Org', 'key_dir') temp_key = safe + '/private.key' dir = Path(safe + '/' + str(req.json()['id']) + '.d') if not os.path.exists(str(dir)): os.makedirs(str(dir)) key_name = Path(str(str(req.json()['id']) + '.key')) saved_key = Path( dir / key_name ) with open(temp_key, 'r') as tk: t = tk.read() with open(str(saved_key), 'w+') as sk: sk.write(t) os.remove(temp_key) # Move csr to order.d temp_csr = Path( safe + '/request.csr') saved_csr = Path( dir / Path(str(str(req.json()['id']) + '.csr')) ) with open(str(temp_csr), 'r') as tc: tcsr = tc.read() with open(str(saved_csr), 'w+') as sc: sc.write(tcsr) os.remove(str(temp_csr)) # Create pending req in cert.d conf_name = str(req.json()['id']) + '.conf' cert_conf = Path( confd_cert / conf_name ) with open(str(cert_conf), 'w+') as cc: scp = ConfigParser() scp.read(str(cert_conf)) scp.add_section('Initialized Cert') scp.set('Initialized Cert', 'id', str(req.json()['id'])) scp.set('Initialized Cert', 'key_dir', str(dir)) scp.set('Initialized Cert', 'status', 'pending') scp.write(cc) print('Successfully placed new order # ' + str(req.json()['id']) + '\n') return req.json()
def duplicate_cert(cid): # Get order information and load cert conf try: info = view_cert(cid,'json') ordernum = info['id'] cert_path = Path(str(confd_cert) + '/' + cid + '.conf') r = ConfigParser() r.read(str(cert_path)) cert_keyd = r.get('Initialized Cert', 'key_dir') except: raise LookupError('Missing cert.d entry. Reissue order with --reissue-crt.') # Get org information to create key.d org_id = info['organization']['id'] org_name = info['organization']['name'] # Generate and save private key alg = input('Create a ECC or RSA private key? ' ) while not alg in ['ecc','rsa']: colorize('red') alg = input('Enter ECC or RSA: ') colorize_edit('reset') key = gen_key(alg) # Generate a CSR from private key dup_csr = gen_csr(key) # Get duplicate certificate information dups = list_duplicates(cid) # If no duplicates, create folder 001 if not dups.get('certificates'): dup_keyd = Path(str(cert_keyd) + '/01.d') os.makedirs(str(dup_keyd)) # Else count the number of dups and create new dup folder else: count = len(dups['certificates']) dup_num = count + 1 dup_keyd = Path(str(cert_keyd) + '/0' + str(dup_num) + '.d') if dup_keyd.exists(): try: shutil.rmtree(str(dup_keyd)) except OSError as e: print("Error: %s - %s." % (e.filename,e.strerror)) os.makedirs(str(dup_keyd)) # Write CSR and KEY to new dup folder key_path = Path(str(dup_keyd) + '/private.key') with open(str(key_path), 'wb+') as f: f.write(key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() )) csr_path = Path(str(dup_keyd) + '/request.csr') with open(str(csr_path), 'w+') as f: f.write(dup_csr) # List options for file format formats = ['1] p7b', '2] pem', '3] pem bundle', '4] code signing', '5] other'] print('Possible file formats: ') print(*formats, sep='\t') format = int(input('Choose a format [1-5]: ')) # Choose server platform if format == 1: platform = 10 elif format == 2: platform = 2 elif format == 3: platform = 45 elif format == 4: platform = 55 elif format == 5: platform = -1 else: print('Default chosen: pem format') platform = -1 # Choose signature hash algs = ['1] sha256', '2] sha384', '3] sha512'] print('Signature hash algorithms') print(*algs, sep='\t') alg = int(input('Choose an algorithm [1-3]: ')) if alg == 1: hash_alg = 'sha256' elif alg == 2: hash_alg = 'sha384' elif alg == 3: hash_alg = 'sha512' else: hash_alg = 'sha256' print('Default selected: sha256') # Set common name cn = info['certificate']['common_name'] colorize('blue') print("Current common name: " + cn) colorize_edit('reset') if info['product']['name_id'] == 'ssl_multi_domain' or info['product']['name_id'] == 'ssl_ev_multi_domain': # Convert sans list to array sans = info['certificate']['dns_names'] if info['product']['name_id'] == 'ssl_cloud_wildcard' or info['product']['name_id'] == 'ssl_wildcard': # Get array of SANs sans = [] print('Type Subject Alternate Name and press enter (Enter d when done):') while 1 == 1: san = input('') if san == 'd': break elif not regex_test.match(san): print(san + ' is not a valid SAN') else: sans.append(san) # Make payload and submit to Digicert payload = json.dumps({ 'certificate': { 'common_name': cn, 'dns_names': sans , 'csr': dup_csr, 'server_platform': { 'id': platform }, 'signature_hash': 'sha256' } }) req_url = url + '/' + str(ordernum) + '/duplicate' req = requests.post(req_url, headers=headers_post, data=payload) rest_status(req) # Get certificate id by listing new duplicate ld = list_duplicates(ordernum) cert_id = ld['certificates'][0]['id'] # Download based on server platform if format == 1: # Download new duplicate from Digicert dup_cert = download_cert_by_format(cert_id,'p7b') # Set filename based on server platform to p7b dup_cert_path = Path( str(dup_keyd) + '/cert.p7b' ) with open(str(dup_cert_path), 'wb+') as save: save.write(dup_cert) elif format == 2: # Download new duplicate from Digicert dup_cert = download_cert_by_format(cert_id,'apache') # Set filename based on server platform to pem (individual pem without root) dup_cert_path = Path( str(dup_keyd) + '/cert.zip' ) with open(str(dup_cert_path), 'wb+') as save: save.write(dup_cert) elif format == 3: # Download new duplicate from Digicert dup_cert = download_cert_by_format(cert_id,'pem_all') # Set filename based on server platform to pem bundle dup_cert_path = Path( str(dup_keyd) + '/cert.pem' ) with open(str(dup_cert_path), 'wb+') as save: save.write(dup_cert) elif format == 4: # Download new duplicate from Digicert dup_cert = download_cert_by_format(cert_id,'cer') # Set filename based on server platform to code signing dup_cert_path = Path( str(dup_keyd) + '/cert.cer' ) with open(str(dup_cert_path), 'wb+') as save: save.write(dup_cert) elif format == 5: # Download new duplicate from Digicert dup_cert = download_cert_by_format(cert_id,'default_pem') # Set filename based on server platform to other (individual pem including root) dup_cert_path = Path( str(dup_keyd) + '/cert.zip' ) with open(str(dup_cert_path), 'wb+') as save: save.write(dup_cert) colorize('green') print('Duplicate successfully created in:\n' + str(dup_cert_path)) colorize_edit('reset')
def reissue_cert(cid): # Get cid cert_info = view_cert(cid, 'json') order_no = str(cert_info['id']) req_url = url + '/' + order_no + '/reissue' # Get request org info org_name = cert_info['organization']['name'] org_city = cert_info['organization']['city'] org_state = cert_info['organization']['state'] org_country = cert_info['organization']['country'] oid = cert_info['organization']['id'] # Print current information old_cn = str(cert_info['certificate']['common_name']) old_sans = ', '.join(cert_info['certificate']['dns_names']) colorize('blue') print('Current Certificate:') print('CN = ' + old_cn) print('SANs = ' + old_sans) colorize_edit('reset') # Get common name cn = input('Enter a new common name: ') while not regex_test.match(cn): cn = input('Enter a valid common name: ') # Get array of SANs sans = [] print('Type Subject Alternate Name and press enter (Enter d when done):') while 1 == 1: san = input('') if san == 'd': break elif not regex_test.match(san): print(san + ' is not a valid SAN') else: sans.append(san) # Load existing conf and private key if exists order_conf = Path( str(confd_cert) + '/' + str(order_no) + '.conf') org_conf = Path( str(confd_org) + '/' + str(oid) + '.conf' ) if os.path.exists(str(order_conf)): with open(str(order_conf), 'r'): scp = ConfigParser() scp.read(str(order_conf)) key_dir = scp.get('Initialized Cert', 'key_dir') key_path = Path( key_dir + '/' + str(order_no) + '.key') csr_path = Path( key_dir + '/' + str(order_no) + '.csr') with open(str(key_path), 'rb') as f: key_bytes = f.read() key = load_pem_private_key(key_bytes, None, default_backend()) # Generate a CSR from private key and org info signed_req = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([ x509.NameAttribute(NameOID.COUNTRY_NAME, org_country), x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, org_state), x509.NameAttribute(NameOID.LOCALITY_NAME, org_city), x509.NameAttribute(NameOID.ORGANIZATION_NAME, org_name), x509.NameAttribute(NameOID.COMMON_NAME, cn), ])).sign(key, hashes.SHA256(), default_backend()) csr = str(signed_req.public_bytes(serialization.Encoding.PEM), 'utf-8') # Save CSR with open(str(csr_path), 'w+') as f: f.write(csr) # Create new conf file else: order_keyd = Path( str(keyd) + '/' + org_name + '/' + str(order_no) + '.d' ) with open(str(order_conf), 'w+') as f: scp = ConfigParser() scp.read(str(order_conf)) scp.add_section('Initialized Cert') scp.set('Initialized Cert', 'id', str(order_no)) scp.set('Initialized Cert', 'key_dir', str(order_keyd)) scp.set('Initialized Cert', 'status', cert_info['status']) scp.write(f) # Generate and save private key alg = input('Create a ECC or RSA private key? ' ) while not alg in ['ecc','rsa']: colorize('red') alg = input('Enter ECC or RSA: ') colorize_edit('reset') key = gen_key(alg) key_path = Path( str(order_keyd) + '/' + str(order_no) + '.key' ) if not os.path.exists(str(order_keyd)): os.makedirs(str(order_keyd)) with open(str(key_path), 'wb+') as f: f.write(key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() )) # Generate csr csr_path = Path( str(order_keyd) + '/' + str(order_no) + '.csr' ) csr = gen_csr(key) with open(str(csr_path), 'w+') as f: f.write(csr, 'utf-8') # Choose signature hash algs = ['1] sha256', '2] sha384', '3] sha512'] print('Signature hash algorithms') print(*algs, sep='\t') alg = int(input('Choose an algorithm [1-3]: ')) if alg == 1: hash_alg = 'sha256' elif alg == 2: hash_alg = 'sha384' elif alg == 3: hash_alg = 'sha512' else: hash_alg = 'sha256' print('Default selected: sha256') # Create payload payload = json.dumps({ 'certificate': { 'common_name': cn, 'dns_names': sans, 'csr': csr, 'signature_hash': hash_alg } }) req = requests.post(req_url, headers=headers_post, data=payload) rest_status(req) colorize('green') print('Reissue for ' + cn + ' has been submitted to Digicert for processing.\n') colorize_edit('reset') return req.json()
def do_dcv(type): # List pending/expired domains resp = list_domains() list = [] col = ['Domain ID', 'Domain Name', 'Status'] list.append(col) for dom in resp['domains']: if dom.get('validations'): for val in dom['validations']: if val.get('dcv_status'): if val['dcv_status'] == 'expired': array = [] array.append(dom['id']) array.append(dom['name']) array.append(val['dcv_status']) list.append(array) elif val['dcv_status'] == 'pending': array = [] array.append(dom['id']) array.append(dom['name']) array.append(val['dcv_status']) list.append(array) print('Showing Pending/Expired DCV\'s: ') paginate(list, 10) # Prompt user for domain id to submit DCV for did = input('\nEnter Domain ID: ') # Choose DCV option by switch value if type == 'email': # Change domain to new DCV payload = json.dumps({'dcv_method': 'email'}) choose_dcv(did, payload) # Get domain control emails emails = dcv_emails(did) colorize('green') print('\nEmails were sent to:\n') colorize_edit('reset') for email in emails['base_emails']: print(' ' + email) for email in emails['whois_emails']: print(' ' + email) print('\n') if type == 'txt': # Change domain to new DCV payload = json.dumps({'dcv_method': 'dns-txt-token'}) resp = choose_dcv(did, payload) dcv = resp['dcv_token'] colorize('green') print('Create a TXT record in your domains DNS: \n') colorize_edit('reset') print('Random String: ' + dcv['token']) print('Status: ' + dcv['status']) print('String Expires On: ' + dcv['expiration_date']) print('\n') if type == 'cname': # Change domain to new DCV payload = json.dumps({'dcv_method': 'dns-cname-token'}) resp = choose_dcv(did, payload) dcv = resp['dcv_token'] colorize('green') print('Create a CNAME record in your DNS: \n') colorize_edit('reset') print('Random String: ' + dcv['token']) print('Target: ' + dcv['verification_value']) print('Domain Status: ' + dcv['status']) print('Example: ' + dcv['token'] + '.[yourdomain].com -> ' + dcv['verification_value']) print('\n')
def gen_custom_csr(alg): # Generate private key key = gen_key(alg) with open('private.key','xb') as sf: sf.write(key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption() )) # Compile custom csr info try: ctry = input('What country are you located in: ') ctry_code = get_ctry_code(ctry) except: raise LookupError('Unable to find matching country code for ' + ctry) st = input('What locality are you located in: ') city = input('What city are you located in: ') org = input('What organization is the request for (Example, Inc): ') cn = input('Enter a common name (example.com): ') while not regex_test.match(cn): colorize('red') print(cn + ' is not a valid common name.') colorize_edit('reset') cn = input('Enter a common name (example.com): ') # Get array of SANs test = input('Enter SANs? [y/n]: ') while not test in [ 'y', 'n']: print('Choose y or n') test = input('Enter SANs? [y/n]: ') if test == 'y': sans = [] print('Type Subject Alternate Name and press enter (Enter d when done):') while 1 == 1: san = input('') if san == 'd': break elif not regex_test.match(san): print(san + ' is not a valid SAN') else: sans.append(san) csr_sans = [] for san in sans: string = x509.DNSName("(%s)" % san) csr_sans.append(string) csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([ x509.NameAttribute(NameOID.COUNTRY_NAME, ctry_code ), x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, st ), x509.NameAttribute(NameOID.LOCALITY_NAME, city ), x509.NameAttribute(NameOID.ORGANIZATION_NAME, org ), x509.NameAttribute(NameOID.COMMON_NAME, cn ), ])).add_extension( # Define SANs x509.SubjectAlternativeName(csr_sans), critical=False, # Sign the CSR with key ).sign(key, hashes.SHA256(), default_backend()) else: csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([ x509.NameAttribute(NameOID.COUNTRY_NAME, ctry_code ), x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, st ), x509.NameAttribute(NameOID.LOCALITY_NAME, city ), x509.NameAttribute(NameOID.ORGANIZATION_NAME, org ), x509.NameAttribute(NameOID.COMMON_NAME, cn ), ])).add_extension( # Define SANs x509.SubjectAlternativeName(''), critical=False, # Sign the CSR with key ).sign(key, hashes.SHA256(), default_backend()) with open('request.csr', 'xt') as sf: sf.write(str(csr.public_bytes(serialization.Encoding.PEM), 'utf-8'))