diff --git a/.gitignore b/.gitignore index db10d98..2586158 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ Gemfile.lock bin/* .bundle/* .kitchen +logstash.* diff --git a/CHANGELOG.md b/CHANGELOG.md index 9209a6d..529a0f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # ELLK changelog + +## [unreleased] +#### Changed +- added Thorfile with certificate helpers + ## [v0.3.4] #### Changed - cleaned up changelog @@ -20,6 +25,7 @@ ## [v0.3.1] #### Submission for feedback +[unreleased]: https://github.com/dearing/ellk/compare/v0.3.4...HEAD [v0.3.4]: https://github.com/dearing/ellk/compare/v0.3.3...v0.3.4 [v0.3.3]: https://github.com/dearing/ellk/compare/v0.3.2...v0.3.3 [v0.3.2]: https://github.com/dearing/ellk/compare/v0.3.1...v0.3.2 diff --git a/Gemfile b/Gemfile index 4e5b70b..a64d361 100644 --- a/Gemfile +++ b/Gemfile @@ -5,3 +5,7 @@ group :lint do gem 'foodcritic-rackspace-rules' gem 'rubocop' end + +group :utils do + gem 'thor' +end diff --git a/README.md b/README.md index 0466fd8..a753d49 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,21 @@ Default installed versions You can override any of these by passing the url for the zip/tar package, a checksum (sha256) and a version to tag it by. See the resource files in the libraries folder for the accepted attributes and [ellktest] for examples and flexibility.. +Thor +------------ +``` +Commands: + thor utils:create_bag # create a Chef data bag of cert and key + thor utils:create_cert # create a certificate with a key + thor utils:create_key # create a RSA 2048 key + thor utils:help [COMMAND] # Describe available commands or one specific command + thor utils:quick_bag # executes create_cert, create_key & create_bag with defaults + +Options: + [--fields=FIELDS] + # Default: CN=localhost +``` + TODO & Help Wanted ------------ - see [issues] diff --git a/Thorfile b/Thorfile new file mode 100644 index 0000000..c9b3073 --- /dev/null +++ b/Thorfile @@ -0,0 +1,74 @@ +require 'openssl' +require 'json' +require 'base64' + +# rubocop:disable MethodLength, Metrics/AbcSize + +class Utils < Thor + class_option :fields, default: 'CN=localhost' + + desc 'create_key', 'create a RSA 2048 key' + option :keyfile, default: 'logstash.key' + def create_key + key = OpenSSL::PKey::RSA.new 2048 + open options[:keyfile], 'w' do |io| + io.write key.to_pem + end + puts "wrote #{options[:keyfile]}" + end + + desc 'create_cert', 'create a certificate with a key' + option :keyfile, default: 'logstash.key' + option :crtfile, default: 'logstash.crt' + def create_cert + key = OpenSSL::PKey::RSA.new File.read options[:keyfile] + cert = OpenSSL::X509::Certificate.new + cert.subject = cert.issuer = OpenSSL::X509::Name.parse options[:fields] + cert.version = 2 + cert.serial = 0 + cert.not_before = Time.now + cert.not_after = Time.now + 3600 + cert.public_key = key.public_key + ext = OpenSSL::X509::ExtensionFactory.new + ext.subject_certificate = cert + ext.issuer_certificate = cert + cert.extensions = [ + ext.create_extension('basicConstraints', 'CA:TRUE', true), + ext.create_extension('subjectKeyIdentifier', 'hash'), + ext.create_extension('keyUsage', 'cRLSign,keyCertSign', true) + ] + cert.sign key, OpenSSL::Digest::SHA256.new + open options[:crtfile], 'w' do |io| + io.write cert.to_pem + end + puts "wrote #{options[:crtfile]} with #{options[:keyfile]} using #{options[:fields]}" + end + + desc 'create_bag', 'create a Chef data bag of cert and key' + option :keyfile, default: 'logstash.key' + option :crtfile, default: 'logstash.crt' + option :bagfile, default: 'logstash.json' + def create_bag + key = Base64.encode64 File.read options[:keyfile] + crt = Base64.encode64 File.read options[:crtfile] + bag = { + id: 'logstash', + certificate: crt, + key: key + } + open options[:bagfile], 'w' do |io| + io.write JSON.pretty_generate(bag) + end + puts "wrote #{options[:bagfile]} with base64 contents of #{options[:keyfile]} and #{options[:crtfile]}" + end + + desc 'quick_bag', 'executes create_cert, create_key & create_bag with defaults' + option :keyfile, default: 'logstash.key' + option :crtfile, default: 'logstash.crt' + option :bagfile, default: 'logstash.json' + def quick_bag + create_key + create_cert + create_bag + end +end diff --git a/test/integration/data_bags/secrets/logstash.json b/test/integration/data_bags/secrets/logstash.json index 0cdb649..577f79c 100755 --- a/test/integration/data_bags/secrets/logstash.json +++ b/test/integration/data_bags/secrets/logstash.json @@ -1,5 +1,5 @@ -{ - "id": "logstash", - "key": "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2QUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktZd2dnU2lBZ0VBQW9JQkFRQ1VtQklWRHVjUVdXRzgKUTJmaU1LcHJoMXlNKzdrSmpxa0FpL2JUck5VZVNFQ2lxUmVaZ0JGZzdIODRrOWl5YlJVRlFNU3lzWUhuODE0OQpYTEFkNWwrRGxFMEFuVGFpcVRNa2FCZWtWYXg0R1pLcDJtNGRMdm1VK1lDVVFJYUFWayszdzVpeExCUTl3NnVrCmxJaXJ4N2xJbWt0OWZrQzNZYldLbi9LeUJYWGEwdHpSc0taN1puMG1meHh0UWxETUpleXB5bHU0ZUxZR3RQaTIKZk5HdUpRTktSeCtITFdGSThMWmg5OUI1RUhGWHBzMVE2Rkh3VzE0WGFrV3FJc3ArTTFFYnltbVFDcUdSbUMvVgpiS2ZwWDZaNHNSWEVBdzBwcUtQMmtmTy9tUEh6UzFMSm9HazJNMTVHN2ViQ0l0Q0NwVjZObDhuZXZHL2xrVUlKCjFkWEZjRS9sQWdNQkFBRUNnZ0VBUDAzSjVrN0RBYVFTanpIb1ArU2J0ZE9sQ2lyeldhNzlNTTV3Q1IzSWJXNDYKbXhHT2pFYVRJTWVnSzJwUkZ6S0JrZ3RWd1FyK1hPTEJjMExaaE9Od0xZNHdmK0o2TkRJQko3Rnc0UUhleUF1YwovOStlcWJBcGc5NEhlU0ZFSzhpWmphQTJuTVE2bTFXUStqeU5QU0dKUGZUOTFDakZTVnJIREplM3ZUKzJSZEtKCk1hSVN2eTBlVjFhVnd2Sm1JK1JDS0syV0JPSm1qRGp1a1Rzc1J1d29tWVIycTkvb1JVYUhkWjZCNlRmKy90cXQKSGxnWXJIcFRFMjZxVm13dUgvR284MkdFQ2FuOTM0SkxITW1ybjJVRUdwVGE5V3ZBRkVBOG9hWU53NHFkMFdwMQorNEZCK3RsbkFpT1B4VDE2UVBsM2E2c1BtT1JiemlJc0lhQmNVNXZJd1FLQmdRRERmQ3VHL21jNldxUm5yMEhuClFiUnJEWVZ2aHUzWXRLck5YWFN5VEVhQ1dldWtZdnN2VXNBcWYvRiszenFDQjFRMWR2RktTTW5lcDFvUnZDQnoKeFRwSFBBWHRvTjFwV1UwTnRRcFE4b3RJY2ovZHR5TW9hY2lHUWNyVVUxRXV2MFpMN2xpYlFWc3B0OUFuWitXNwozS1BjZUk0aFJTMnZZK01OMnl3ekxKQ1J2d0tCZ1FEQ2w5Ky9GM3FFQ2dNVGtxWWEvdnA1SVMrcGtSM25tamtwCnBBNHBDNjBSaWJEY2pPSU9hVjBzdE81N3gvVDEvOWIxT0QrVm4zamJBSTAzUWQxVDB2RUk4cGl5c3d1enFJVnMKcVRkSEx3TDh3M1p6RkFCcFh1YVFIbUYyTHl5Y0VjTHhGdXhJb3l3YWZJalRFN0xqcWNrK1FlZ2JTV3VsZlhIUQpZMXlpUkhHL1d3S0JnRXRjWmlkZmtnb2tBWGRiVUF2SC83YTVlclI1RHQ1WkgvT1YwTFFmeFpyZzhYL3BESzY4CnR3cHJVbjAzcjRXTEw4S0F2UnFISHhPdjdvQWh4MXo2THJKaGlHT0lmWExzazFEeWR5eW5wRnhrZHd5UldvTnMKN0hvZGlRVDdyYk5ZMTgvVDdlTEVlbEdGNUVBY3hLcjhyMHNDU3NDMnU1cis1ZnhrZnhDbllJQmZBb0dBTWNwcwpqTmUwR0k3N1JJblVpTG5QV3lrYnFmYWd3VDhiKzBTbi91YW03UUxmUnoraEkvRGZ6MjJvUy9IWkF3em9jcXhtCjBLRVNhbThVc3h2ZVJ2R0ZqVFdOenNPemJjL2orKzY4WHpGdlFUKytVaW0vQlRjc0pab3djKzRVS3diOGEzWGoKRlo3eXpRQXFmbC9lK1JQYmsxdUh5VnVhK0toRmMvM0ltUmlNUmxzQ2dZQktTWTZhN2NFZUt0RklIS0hHaHI5dAp3RkVMYzA5anRqMldDelQ5R1JzZHVkeUJVUjZtZCtEeHpnYlBXWCtyZFBoNGgvZXZsNEl2U2NqaG5JaHo2Y2RNCmdJWFJYd1k1ZXNCQ0RhcmN6K2d3a1pNUEZpNjlENDBQUzcyNDhQZCtmdk4zM3NZb21YR0d1d2pPY043NlpWc3oKM1RieENJK2pnTnMvSHJZU2lTSXlpdz09Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K", - "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURoVENDQW0yZ0F3SUJBZ0lKQVBHd3RXdDdkVXByTUEwR0NTcUdTSWIzRFFFQkN3VUFNRmt4Q3pBSkJnTlYKQkFZVEFrRlZNUk13RVFZRFZRUUlEQXBUYjIxbExWTjBZWFJsTVNFd0h3WURWUVFLREJoSmJuUmxjbTVsZENCWAphV1JuYVhSeklGQjBlU0JNZEdReEVqQVFCZ05WQkFNTUNXeHZZMkZzYUc5emREQWVGdzB4TlRBM01USXhOVFV3Ck1qbGFGdzB4T0RBME1EY3hOVFV3TWpsYU1Ga3hDekFKQmdOVkJBWVRBa0ZWTVJNd0VRWURWUVFJREFwVGIyMWwKTFZOMFlYUmxNU0V3SHdZRFZRUUtEQmhKYm5SbGNtNWxkQ0JYYVdSbmFYUnpJRkIwZVNCTWRHUXhFakFRQmdOVgpCQU1NQ1d4dlkyRnNhRzl6ZERDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSlNZCkVoVU81eEJaWWJ4RForSXdxbXVIWEl6N3VRbU9xUUNMOXRPczFSNUlRS0twRjVtQUVXRHNmemlUMkxKdEZRVkEKeExLeGdlZnpYajFjc0IzbVg0T1VUUUNkTnFLcE15Um9GNlJWckhnWmtxbmFiaDB1K1pUNWdKUkFob0JXVDdmRAptTEVzRkQzRHE2U1VpS3ZIdVVpYVMzMStRTGRodFlxZjhySUZkZHJTM05Hd3BudG1mU1ovSEcxQ1VNd2w3S25LClc3aDR0Z2EwK0xaODBhNGxBMHBISDRjdFlVand0bUgzMEhrUWNWZW16VkRvVWZCYlhoZHFSYW9peW40elVSdksKYVpBS29aR1lMOVZzcCtsZnBuaXhGY1FERFNtb28vYVI4NytZOGZOTFVzbWdhVFl6WGtidDVzSWkwSUtsWG8yWAp5ZDY4YitXUlFnblYxY1Z3VCtVQ0F3RUFBYU5RTUU0d0hRWURWUjBPQkJZRUZIN0VBbHQraGcxb3RnUnk3cElTCkxEMzJxaDhMTUI4R0ExVWRJd1FZTUJhQUZIN0VBbHQraGcxb3RnUnk3cElTTEQzMnFoOExNQXdHQTFVZEV3UUYKTUFNQkFmOHdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBREt2Qk9MUnVwV3lMTXFuVHFrMEoyRnUxd1pKNlZSVApuMXFrVzIyUlJLdXlFa0tQYUZoZDdCTXpENjZ1N3crTnV2djN3dDhXNkNMU0tEck1GZE5YVzdCRDkyNE5SckpiCkpTNTJnUnh0eTdnTDRqTW5RdG9PdHYzVEZ6c2o0b014LzFhVVVMYkJrdTVwN1lEYjVEYkN3VGsyMlUrWExqanEKRTdDY0N2SHVOMHVBUHdnVGJ0eWd3bmdvTjNLdlNxNkJpeU81Y3BLUjVxTTl2WjQ2OEtFTy9ZOXJweUJVL1l1awo3akRoMDZHODk3V1hiK25kenVQQVdrNTNxZEtVb3VBQlNhSjNPUFUyUnI2MFJ0ZmhDdEhlenEvRFVGOXo2ZkhyCldvTDI4NS9jcHBoUlBmd3F0VUxDZmYvbG5MZXFVNE1NdURhbDRvY0VtVXpheVlQeXJnbG9KaWs9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" -} +{ + "id": "logstash", + "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1VENDQWMyZ0F3SUJB\nZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFVTVJJd0VBWURWUVFEREFsc2Iy\nTmgKYkdodmMzUXdIaGNOTVRVd09EQTNNakl4TURVMFdoY05NVFV3T0RBM01q\nTXhNRFUwV2pBVU1SSXdFQVlEVlFRRApEQWxzYjJOaGJHaHZjM1F3Z2dFaU1B\nMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRREtwaGY2CkFy\nTjkzdGhFcFFLOS9NMU5HWW5YY0FtY3pwUTlmNGFKMzM5L3N6aGozZXhXdGJP\nUXdhOTlvSGNta1dxVGJyQzYKcDJqT1BhOE5UK3pBcW9SNWQ5MUpoQ2lnQkhD\nb2drazRSOWtIOHpLQlhXcjVOdlI3eHhDcVZpaTBoVDlVdm1kdApvMjZTN0t4\nT3FJWHRGcmR4dEs1UnJQa0NKMW9KZU4wWlBZMjZURStlUElDNzBNL1hlQU1G\nSkh1d3FwdjRXWWp3CmRHbFcxZlhtTGxVV21nSzlPTzJPakJlVDZQQTNFOXVy\nQXFrM0Q5dkQyMnZkUjVOaE1EWWpSWjN1MHVjZm1tYjgKTFlLUXZzVWpWV1N1\nM2lyQ2lSMVV3T3FiUXpORVJySnJ1VDU3RGE3Tk1FMFFjMmQ1cDEwVkRRbmpY\nTXc0ZlJmaQpnTUVzaEFVWlFPNUdMNjJGQWdNQkFBR2pRakJBTUE4R0ExVWRF\nd0VCL3dRRk1BTUJBZjh3SFFZRFZSME9CQllFCkZFWS81VHl1eHdRS1E4VzIr\nUmo0VmlxY01kVHJNQTRHQTFVZER3RUIvd1FFQXdJQkJqQU5CZ2txaGtpRzl3\nMEIKQVFzRkFBT0NBUUVBZUJ4Rm44UkdUc1p5UjRCS3g2NmxBWWZRSWdUUFJi\nQ0JZWVlsd05oTzFtTVlzR0VIWTlLSApIYzlVMnFxNGUxK0JyMUtpVXBJTjRW\nek15UnZGdE54OFNUVE5Qck9CN0RpWWRacVl0MkxaZ2VwUFNWNW51elAwCm1D\nQ3lOR2p0d3d1RW5BZEtwQ1hleXFEWmpjQmFveWhPMG5KUndKaEVWZEd3YjYr\ndU1jSzhQd2ZwS0ExWmQxMFkKM1NTd0htUFliVHFhR2UxNUlGWWJjZnBsNENJ\nVGxPMGx1dWFIZm9LOXRna0dueXhCU3Z6dkhNZGFsVGRqVTF4eQozQTRjUEFj\ndGk4N3NyL0krSXRHZGc3TDc2T0xOWjVTN3N6MkxjZHBjQkJybFNZdzQyNms3\nMER6dEZWUWNxZzJ1CksvcjFabEV5RW1VbzRDWXAxcndYVUl5NUROTGxRbDAr\nK1E9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==\n", + "key": "LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NB\nUUVBeXFZWCtnS3pmZDdZUktVQ3Zmek5UUm1KMTNBSm5NNlVQWCtHaWQ5L2Y3\nTTRZOTNzClZyV3prTUd2ZmFCM0pwRnFrMjZ3dXFkb3pqMnZEVS9zd0txRWVY\nZmRTWVFvb0FSd3FJSkpPRWZaQi9NeWdWMXEKK1RiMGU4Y1FxbFlvdElVL1ZM\nNW5iYU51a3V5c1RxaUY3UmEzY2JTdVVhejVBaWRhQ1hqZEdUMk51a3hQbmp5\nQQp1OURQMTNnREJTUjdzS3FiK0ZtSThIUnBWdFgxNWk1VkZwb0N2VGp0am93\nWGsrandOeFBicXdLcE53L2J3OXRyCjNVZVRZVEEySTBXZDd0TG5INXBtL0My\nQ2tMN0ZJMVZrcnQ0cXdva2RWTURxbTBNelJFYXlhN2srZXcydXpUQk4KRUhO\nbmVhZGRGUTBKNDF6TU9IMFg0b0RCTElRRkdVRHVSaSt0aFFJREFRQUJBb0lC\nQUdSR1RjVHpnemU4aGsxcApUWE1QWGROUjJNaFc4eHE1aWRib2ZIMUtyMzlV\nQW9wQUxRczIrL1NjTXFjNk9OdEh4M0hPcXZxaGpoWEhwaEF6ClJWYU15ZUtG\nTW1XSFZNYmhpNUdHYm82LzFwKzljbmRhNzIwRUNYUWFLNS90NUZSM1BzQkRP\nMUNnTnozU2lPeWYKTFM0Rk9KNjJKaS9hSkpreE9iZElMRGVxSXJCVTR3R2VI\nQjh5K2QvVndNNVBPSHE2dUVJZ3p6cXdmQXZmUjVrdAo0ZTRYTnNrcGRxVXBx\nNFBBdzg4K0FQNVlSRnlBZXlGUU1oNllqcVhWRkZsNzRkMTBzYnNDTzlQK0p0\nZlVmQkFrCitzbk43YjFmY1dKNjB4YlNuTjdvaWJaQzFnbXM3MytrSGVicE1O\nRVF4S05XekxTemhZbDNUbVdVWldwcTdmUmoKamNKaDZ6MENnWUVBNVo4MSt4\nVldkYzQzNThtV2Nub3FDUUVYenFIU2RTYW9jbkdoSWEzWlZmbTE0UTZMREVn\neQpKOTEzcXNYSStqVHVTV1hHdXo0RmtzaXdYNXNwcThZYWw4NEt3WEJpeVEw\ncjNPNHFlZjYyZVlSSUwvYXFwQyszCmd5bkJFcUdpcmo4L09MeVVJMGZ3WFpn\nN1RZWGR5bENBcThUaWtQRXNLYkVVUHJ0a1J5bnI4Z01DZ1lFQTRlMm0KUlVG\nUU9sT2w0NFBkZmhJWHYxMGxjS3lmZEJnM1pyTjY1cm0yenVFYzhublVEc3dr\nVzIwZU90TFNiQjF1TUFRRApnRHVFZmpSalBuQXNGaldGRjB2SWFqZzNhN2VS\nOWVvMlVRT1hPNC83QXE2eFZmTmlDbXFyRWJnNktldlFxWXZOCk1vKzBaeW4z\nQkNyTWdmbTRGb2RaSWdaSWYzWXhNZUg1aDBvZHo5Y0NnWUVBM2NDckJnZHVU\neWpQVHJhYzU0TloKTXdidU1leVBiZm5lZFYrTlNCUTNydE1RTmYrd2d6VDUw\nd3dMZEUyOE1QNkxIVEVBQW5YOE5leEFnS1E5VXhsbgpOekdScTR4WXFtZGc4\nK1RCK3J6bEJtZWN1MDFSTUd5d29pZmh3SmQrbng2UGRNQ1JvNXptNGN5UmdP\nV0Y4c3RaCjZBaWs4V3NueGord0dJRXFiNXRwdEhjQ2dZQmZHOUZFRkZPMnlp\nSHFua2R1M0NUOUhUUTJzNlRJbGEwMDRkZWEKSzVJbWt5UEJlOEhtbk0rdFlV\nazVrQ2llOU9DKysrR1JhUHpFdUQ4VE9OdUdXZTkyT0NQZGUxN3hUS3o0Ymlt\nQgpmMVo1NzRuR3ZrM1BGZzh1dldyWW9jcHlmV0F4RDdaSlU2K3BRa1JIajlE\nWjRvczVpSzdnSU84Q0lYcGlPblAyCkhTQmhyd0tCZ0IzZW5EYk1ndGdBTGh1\ncGttZzBDRzVLeEkwanFZTU9ibVpDZmYxbmhKTGRhL0JESTAzNEVmUkMKSFhN\nTk55aC9Caks1bUt5L2NscFZPd3NFRmtHRi9kS1J0Rzl5YTZHZUVxdU5BNTk4\naythTUt3TXdlR0duek1QMgp4M21KSW1haDZFTW5uRnVzb0J1NU9WeTJneHhV\nY0x6TVhnT3FRWFR3bVNFYzBmaWNlaTIyCi0tLS0tRU5EIFJTQSBQUklWQVRF\nIEtFWS0tLS0tCg==\n" +} \ No newline at end of file