SSLKeyAndCSRCreator
Problem this snippet solves:
This is a script will generate a private key and output a certificate signing request. This is all done from a workstation command line and communicated to the BIG-IP via iControl.
How to use this snippet:
Requirements
- Ruby
- Ruby Gems
- F5 iControl for Ruby library
- other dependencies will be installed with the iControl gem
Installation Steps
- Install Ruby, Ruby's ""OpenSSL"" library, Ruby Gems, and the Ruby iControl libraries
- Copy this code to /usr/local/bin and chmod +x to make the script executable
-
Run it!
- minimal options: ssl-key-and-csr-creator.rb -b 192.168.1.245 -u admin -i test-key-001
- full options: ssl-key-and-csr-creator.rb -b 192.168.1.245 -u admin -p admin -i test-key-001 -t RSA -l 4096 -s fips --common-name=www.example.com --country=US --state=Washington --locality=Seattle --organization="Example Company, Inc." --division="Information Technology" -o /my-ssl-directory/ -k -c
Code :
#!/usr/bin/ruby require "rubygems" require "f5-icontrol" require "getoptlong" options = GetoptLong.new( [ "--bigip-address", "-b", GetoptLong::REQUIRED_ARGUMENT ], [ "--bigip-user", "-u", GetoptLong::REQUIRED_ARGUMENT ], [ "--bigip-pass", "-p", GetoptLong::REQUIRED_ARGUMENT ], [ "--key-id", "-i", GetoptLong::REQUIRED_ARGUMENT ], [ "--key-type", "-t", GetoptLong::OPTIONAL_ARGUMENT ], [ "--key-bit-length", "-l", GetoptLong::OPTIONAL_ARGUMENT ], [ "--key-security", "-s", GetoptLong::OPTIONAL_ARGUMENT ], [ "--common-name", GetoptLong::OPTIONAL_ARGUMENT ], [ "--country", GetoptLong::OPTIONAL_ARGUMENT ], [ "--state", GetoptLong::OPTIONAL_ARGUMENT ], [ "--locality", GetoptLong::OPTIONAL_ARGUMENT ], [ "--organization", GetoptLong::OPTIONAL_ARGUMENT ], [ "--division", GetoptLong::OPTIONAL_ARGUMENT ], [ "--output-dir", "-o", GetoptLong::OPTIONAL_ARGUMENT ], [ "--key-output", "-k", GetoptLong::NO_ARGUMENT ], [ "--csr-output", "-c", GetoptLong::NO_ARGUMENT ], [ "--help", "-h", GetoptLong::NO_ARGUMENT ] ) def usage puts $0 + " -b-u -i " puts puts "BIG-IP connection parameters" puts "-" * 20 puts " -b (--bigip-address) BIG-IP management-accessible address" puts " -u (--bigip-user) BIG-IP username" puts " -p (--bigip-pass) BIG-IP password (will prompt if left blank" puts puts "Private key parameters" puts "-" * 20 puts " -i (--key-id) key ID: must be unique and should be indicative of the purpose (required)" puts " -t (--key-type) key type: [RSA|DSA] (default is 'RSA')" puts " -l (--key-bit-length) key bit length: should be a minimum of 1024-bit (default is 2048; most CAs won't sign weaker keys)" puts " -s (--key-security) key security: [normal|fips|password] (default is 'normal' with no passphrase)" puts puts "X.509 data parameters (if blank, you'll be prompted for the answers)" puts "-" * 20 puts " (--common-name) common name: FQDN for virtual server (www.example.com)" puts " (--country) country: two letter country abbreviation (US, CN, etc.)" puts " (--state) state: two letter state abbreviation (WA, OR, CA, etc.)" puts " (--locality) locality: locality or city name (Seattle, Portland, etc.)" puts " (--organization) organization: organization or company name (F5 Networks, Company XYZ, etc.)" puts " (--division) division: department or division name (IT, HR, Finance, etc.)" puts puts "Output options" puts "-" * 20 puts " -o (--output-dir) CSR/key output directory: location to output private key and CSR files (defaults to current working directory)" puts " -k (--key-output) key output: save private key to a local file (saved as key_id.key)" puts " -c (--csr-output) CSR output: save certificate signing request to a local file (saved as key_id.csr)" puts puts "Help and usage" puts "-" * 20 puts " -h (--help) shows this help/usage dialog" puts exit end # set STDOUT buffer to synchronous STDOUT.sync = true # global variables KEY_TYPES = { "RSA" => "KTYPE_RSA_PRIVATE", "DSA" => "KTYPE_DSA_PRIVATE" } KEY_SECURITIES = { "normal" => "STYPE_NORMAL", "fips" => "STYPE_FIPS", "password" => "STYPE_PASSWORD" } # initial parameter values overwrite_key = false # key/CSR default output file values key_output = false csr_output = false output_dir = Dir.pwd # BIG-IP connection parameters bigip = {} bigip['address'] = '' bigip['user'] = '' bigip['pass'] = '' # private key parameters key_data = {} key_data['id'] = '' key_data['key_type'] = KEY_TYPES["RSA"] key_data['bit_length'] = 2048 key_data['security'] = KEY_SECURITIES["normal"] # X.509 data parameters x509_data = {} x509_data['common_name'] = '' x509_data['country_name'] = '' x509_data['state_name'] = '' x509_data['locality_name'] = '' x509_data['organization_name'] = '' x509_data['division_name'] = '' # loop through command line options options.each do |option, arg| case option when "--bigip-address" bigip['address'] = arg when "--bigip-user" bigip['user'] = arg when "--bigip-pass" bigip['pass'] = arg when "--key-id" key_data['id'] = arg when "--key-type" if KEY_TYPES.keys.include? arg.upcase key_data['key_type'] = KEY_TYPES[arg.upcase] else puts "Error: Invalid key type. Exiting." exit 1 end when "--key-bit-length" key_data['bit_length'] = arg.to_i when "--key-security" if KEY_SECURITIES.keys.include? arg.downcase key_data['security'] = KEY_SECURITIES[arg.downcase] else puts "Error: Invalid key security type. Exiting." exit 1 end when "--common-name" x509_data['common_name'] = arg when "--country" if arg =~ /[a-z]{2}/i x509_data['country_name'] = arg.upcase else puts "Error: Use exactly two letters for the country code. Exiting." exit 1 end when "--state" x509_data['state_name'] = arg when "--locality" x509_data['locality_name'] = arg when "--organization" x509_data['organization_name'] = arg when "--division" x509_data['division_name'] = arg when "--output-dir" if File.directory? arg output_dir = arg else puts "Error: Invalid directory for output. Exiting." end when "--key-output" key_output = true when "--csr-output" csr_output = true when "--help" usage end end # we need at least the BIG-IP's address, user, and a key ID to proceed usage if bigip['address'].empty? or bigip['user'].empty? or key_data['id'].empty? if bigip['pass'].empty? puts "Please enter the BIG-IPs password..." print "Password: " system("stty", "-echo") bigip['pass'] = gets.chomp system("stty", "echo") puts end # set up connection to BIG-IP and Management.KeyCertificate interface bigip = F5::IControl.new(bigip['address'], bigip['user'], bigip['pass'], ["Management.KeyCertificate"]).get_interfaces #grab a list of existing keys and confirm overwrite if a conflict exists existing_keys = bigip["Management.KeyCertificate"].get_key_list('MANAGEMENT_MODE_DEFAULT').collect { |key| key["key_info"]["id"] } if existing_keys.include? key_data['id'] print "A key with an ID of '#{key_data['id']}' already exists. Overwrite it? (yes/no) " answer = gets.chomp if answer !~ /^yes$/i puts "Will not overwrite existing key. Exiting." exit else overwrite_key = true end end # time to play 20 questions with the X.509 data if x509_data.values.delete_if { |value| !value.empty? }.size > 0 puts "Please fill in the following X.509 data parameters..." end x509_data.sort.each do |key, value| if value.empty? print key.capitalize.gsub('_', ' ') + "? " x509_data[key] = gets.chomp end end bigip["Management.KeyCertificate"].key_generate('MANAGEMENT_MODE_DEFAULT', [key_data], [x509_data], true, overwrite_key) # write private key to local file if specified by user if key_output key_output_file = output_dir + "/" + key_data['id'] + ".key" key = bigip["Management.KeyCertificate"].key_export_to_pem('MANAGEMENT_MODE_DEFAULT', [key_data['id']])[0] File.open(key_output_file, 'w') { |file| file.write(key) } end # display subject information for CSR as well as the CSR puts "Certificate Request" puts "-" * 20 puts "Subject: C=#{x509_data['country_name']}, ST=#{x509_data['state_name']}, L=#{x509_data['locality_name']}, O=#{x509_data['organization_name']}, OU=#{x509_data['division_name']}, CN=#{x509_data['common_name']}" csr = bigip["Management.KeyCertificate"].certificate_request_export_to_pem('MANAGEMENT_MODE_DEFAULT', [key_data['id']]) # write csr key to local file if specified by user if csr_output csr_output_file = output_dir + "/" + key_data['id'] + ".csr" File.open(csr_output_file, 'w') { |file| file.write(csr) } end puts puts csr
Published Mar 09, 2015
Version 1.0George_Watkins_
Historic F5 Account
Joined September 17, 2008
George_Watkins_
Historic F5 Account
Joined September 17, 2008
No CommentsBe the first to comment