digicert-cli 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.hound.yml +3 -0
  3. data/.rubocop.yml +637 -0
  4. data/.travis.yml +0 -1
  5. data/Gemfile +0 -2
  6. data/LICENSE.txt +21 -0
  7. data/README.md +218 -21
  8. data/bin/digicert +1 -2
  9. data/digicert-cli.gemspec +3 -12
  10. data/lib/digicert/cli.rb +33 -9
  11. data/lib/digicert/cli/auth.rb +6 -3
  12. data/lib/digicert/cli/base.rb +19 -0
  13. data/lib/digicert/cli/certificate.rb +75 -0
  14. data/lib/digicert/cli/certificate_downloader.rb +51 -0
  15. data/lib/digicert/cli/command.rb +14 -48
  16. data/lib/digicert/cli/commands/certificate.rb +37 -0
  17. data/lib/digicert/cli/commands/csr.rb +31 -0
  18. data/lib/digicert/cli/commands/order.rb +45 -0
  19. data/lib/digicert/cli/csr.rb +48 -0
  20. data/lib/digicert/cli/filter_builder.rb +54 -0
  21. data/lib/digicert/cli/order.rb +9 -23
  22. data/lib/digicert/cli/order_reissuer.rb +60 -11
  23. data/lib/digicert/cli/order_retriever.rb +48 -0
  24. data/lib/digicert/cli/rcfile.rb +48 -0
  25. data/lib/digicert/cli/util.rb +5 -1
  26. data/lib/digicert/cli/version.rb +23 -1
  27. data/spec/acceptance/certificate_spec.rb +66 -0
  28. data/spec/acceptance/config_spec.rb +16 -0
  29. data/spec/acceptance/csr_spec.rb +51 -0
  30. data/spec/acceptance/order_spec.rb +6 -21
  31. data/spec/acceptance/reissuing_order_spec.rb +33 -0
  32. data/spec/digicert/cli/certificate_downloader_spec.rb +30 -0
  33. data/spec/digicert/cli/certificate_spec.rb +104 -0
  34. data/spec/digicert/cli/csr_spec.rb +47 -0
  35. data/spec/digicert/cli/filter_builder_spec.rb +25 -0
  36. data/spec/digicert/cli/order_reissuer_spec.rb +74 -0
  37. data/spec/digicert/cli/order_retriever_spec.rb +23 -0
  38. data/spec/digicert/{order_spec.rb → cli/order_spec.rb} +2 -2
  39. data/spec/digicert/cli/rcfile_spec.rb +18 -0
  40. data/spec/digicert/cli_spec.rb +6 -5
  41. data/spec/fixtures/.digicertrc +2 -0
  42. data/spec/fixtures/rsa4096.csr +51 -0
  43. data/spec/fixtures/rsa4096.key +51 -0
  44. data/spec/spec_helper.rb +8 -1
  45. data/spec/support/disable-logging.rb +12 -0
  46. metadata +70 -22
  47. data/.sample.env +0 -1
  48. data/bin/console +0 -14
  49. data/legacy_cli.sh +0 -301
  50. data/lib/digicert/cli/command/order.rb +0 -50
  51. data/lib/digicert/cli/order_filterer.rb +0 -43
  52. data/spec/digicert/command_spec.rb +0 -16
  53. data/spec/digicert/order_filterer_spec.rb +0 -50
  54. data/spec/digicert/order_reissuer_spec.rb +0 -19
@@ -0,0 +1,51 @@
1
+ module Digicert
2
+ module CLI
3
+ class CertificateDownloader
4
+ def initialize(certificate_id:, path:, **options)
5
+ @path = path
6
+ @options = options
7
+ @certificate_id = certificate_id
8
+ @filename = options.fetch(:filename, certificate_id)
9
+ end
10
+
11
+ def download
12
+ if certificate_contents
13
+ write_certificate_contents(certificate_contents)
14
+ end
15
+ end
16
+
17
+ def self.download(attributes)
18
+ new(attributes).download
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :certificate_id, :path, :filename, :options
24
+
25
+ def certificate_contents
26
+ @certificate_contents ||=
27
+ Digicert::CertificateDownloader.fetch_content(certificate_id)
28
+ end
29
+
30
+ def write_certificate_contents(contents)
31
+ say("Downloaded certificate to:")
32
+
33
+ write_to_path("root", contents[:root_certificate])
34
+ write_to_path("certificate", contents[:certificate])
35
+ write_to_path("intermediate", contents[:intermediate_certificate])
36
+ end
37
+
38
+ def write_to_path(key, content)
39
+ certificate_name = [filename, key, "crt"].join(".")
40
+ certificate_path = [path, certificate_name].join("/")
41
+
42
+ say(certificate_path)
43
+ File.open(certificate_path, "w") { |file| file.write(content) }
44
+ end
45
+
46
+ def say(message)
47
+ Digicert::CLI::Util.say(message)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,57 +1,23 @@
1
- require "optparse"
2
- require "digicert/cli/order"
1
+ require "digicert/cli/rcfile"
2
+ require "digicert/cli/commands/csr"
3
+ require "digicert/cli/commands/order"
4
+ require "digicert/cli/commands/certificate"
3
5
 
4
6
  module Digicert
5
7
  module CLI
6
- module Command
7
- def self.run(command, subcommand, args = {})
8
- command_klass = command_handler(command)
9
- attributes = parse_option_arguments(args)
8
+ class Command < Thor
9
+ desc "csr", "Fetch/generate Certificate CSR"
10
+ subcommand :csr, Digicert::CLI::Commands::Csr
10
11
 
11
- command_klass.new(attributes).send(subcommand.to_sym)
12
- end
13
-
14
- def self.parse(command)
15
- command_handlers[command.to_sym] || raise(ArgumentError)
16
- end
17
-
18
- def self.command_handlers
19
- @commands ||= { order: "Order" }
20
- end
21
-
22
- def self.command_handler(command)
23
- Object.const_get(
24
- ["Digicert", "CLI", parse(command)].join("::")
25
- )
26
- end
27
-
28
- def self.parse_option_arguments(args)
29
- attributes = {}
30
-
31
- option_parser = OptionParser.new do |parser|
32
- parser.banner = "Usage: digicert resource:action [options]"
12
+ desc "order", "Manage Digicert Orders"
13
+ subcommand :order, Digicert::CLI::Commands::Order
33
14
 
34
- global_options.each do |option|
35
- attribute_name = option[1].split.first.gsub("--", "").to_sym
36
- parser.on(*option) { |value| attributes[attribute_name] = value}
37
- end
38
- end
39
-
40
- if args.first
41
- option_parser.parse!(args)
42
- end
43
-
44
- attributes
45
- end
15
+ desc "certificate", "Manage Digicert Certificates"
16
+ subcommand :certificate, Digicert::CLI::Commands::Certificate
46
17
 
47
- def self.global_options
48
- [
49
- ["-o", "--order_id ORDER_ID", "The Digicert Order Id"],
50
- ["-q", "--quiet", "Flag to return resource Id only"],
51
- ["-s", "--status STATUS", "Use to specify the order status"],
52
- ["-c", "--common_name COMMON_NAME", "The common name for the order"],
53
- ["-p", "--product_type NAME_ID", "The Digicert product name Id"],
54
- ]
18
+ desc "config API_KEY", "Configure The CLI Client"
19
+ def config(api_key)
20
+ Digicert::CLI::RCFile.set_key(api_key)
55
21
  end
56
22
  end
57
23
  end
@@ -0,0 +1,37 @@
1
+ require "digicert/cli/certificate"
2
+
3
+ module Digicert
4
+ module CLI
5
+ module Commands
6
+ class Certificate < Thor
7
+ desc "fetch ORDER_ID", "Find an order's certificate"
8
+ option :quiet, type: :boolean, aliases: "-q", desc: "Retrieve only id"
9
+ option :output, aliases: "-o", desc: "Path to download the certificate"
10
+
11
+ def fetch(order_id)
12
+ say(certificate_instance(order_id: order_id).fetch)
13
+ end
14
+
15
+ desc "download [RSOURCE_OPTION]", "Download a certificate"
16
+ option :order_id, aliases: "-i", desc: "Digicert order ID"
17
+ option :certificate_id, aliases: "-c", desc: "The certificate ID"
18
+ option :output, aliases: "-o", desc: "Path to download the certificate"
19
+
20
+ def download
21
+ say(certificate_instance.download)
22
+ end
23
+
24
+ desc "duplicates ORDER_ID", "List duplicate certificates"
25
+ def duplicates(order_id)
26
+ say(certificate_instance(order_id: order_id).duplicates)
27
+ end
28
+
29
+ private
30
+
31
+ def certificate_instance(id_attribute = {})
32
+ Digicert::CLI::Certificate.new(options.merge(id_attribute))
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,31 @@
1
+ require "digicert/cli/csr"
2
+
3
+ module Digicert
4
+ module CLI
5
+ module Commands
6
+ class Csr < Thor
7
+ desc "fetch ORDER_ID", "Fetch an existing CSR"
8
+
9
+ def fetch(order_id)
10
+ say(csr_instance(order_id: order_id).fetch)
11
+ end
12
+
13
+ desc "generate", "Generate certificate CSR"
14
+ option :common_name, aliases: "-c", desc: "The common name"
15
+ option :san, type: :array, desc: "The subject alternative names"
16
+ option :key, aliases: "-k", desc: "Complete path to the rsa key file"
17
+ option :order_id, required: true, aliases: "-o", desc: "An Order ID"
18
+
19
+ def generate
20
+ say(csr_instance.generate)
21
+ end
22
+
23
+ private
24
+
25
+ def csr_instance(id_attribute = {})
26
+ Digicert::CLI::CSR.new(options.merge(id_attribute))
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,45 @@
1
+ require "digicert/cli/order"
2
+ require "digicert/cli/order_reissuer"
3
+
4
+ module Digicert
5
+ module CLI
6
+ module Commands
7
+ class Order < Thor
8
+ desc "list", "List digicert orders"
9
+ method_option :filter, type: :hash, desc: "Specify filter options"
10
+
11
+ def list
12
+ say(order_instance.list)
13
+ end
14
+
15
+ desc "find", "Find a digicert order"
16
+ method_option :filter, type: :hash, desc: "Specify filter options"
17
+ option :quiet, type: :boolean, aliases: "-q", desc: "Retrieve only id"
18
+
19
+ def find
20
+ say(order_instance.find)
21
+ end
22
+
23
+ desc "reissue ORDER_ID", "Reissue digicert order"
24
+ option :crt, desc: "The CSR content from a file"
25
+ option :output, aliases: "-o", desc: "Path to download certificates"
26
+
27
+ def reissue(order_id)
28
+ say(reissue_an_order(order_id))
29
+ end
30
+
31
+ private
32
+
33
+ def order_instance
34
+ Digicert::CLI::Order.new(options)
35
+ end
36
+
37
+ def reissue_an_order(order_id)
38
+ Digicert::CLI::OrderReissuer.new(
39
+ options.merge(order_id: order_id),
40
+ ).create
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,48 @@
1
+ module Digicert
2
+ module CLI
3
+ class CSR < Digicert::CLI::Base
4
+ def fetch
5
+ if order
6
+ order.certificate.csr
7
+ end
8
+ end
9
+
10
+ def generate
11
+ if order
12
+ generate_csr_for(order)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :rsa_key
19
+
20
+ def extract_local_attributes(options)
21
+ @rsa_key = options.fetch(:key, nil)
22
+ end
23
+
24
+ def order
25
+ @order ||= Digicert::Order.fetch(order_id)
26
+ end
27
+
28
+ def generate_csr_for(order)
29
+ if rsa_key && File.exists?(rsa_key)
30
+ Digicert::CSRGenerator.generate(csr_attributes(order))
31
+ end
32
+ end
33
+
34
+ def csr_attributes(order)
35
+ Hash.new.tap do |csr|
36
+ csr[:rsa_key] = File.read(rsa_key)
37
+ csr[:organization] = order.organization
38
+ csr[:common_name] =
39
+ options[:common_name] || order.certificate.common_name
40
+
41
+ if options[:san]
42
+ csr[:san_names] = options[:san]
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,54 @@
1
+ module Digicert
2
+ module CLI
3
+ class FilterBuilder
4
+ attr_reader :options, :filters_hash
5
+
6
+ def initialize(options)
7
+ @options = options
8
+ @filters_hash = {}
9
+ end
10
+
11
+ def build
12
+ build_filters
13
+ filters_hash
14
+ end
15
+
16
+ def self.build(options)
17
+ new(options).build
18
+ end
19
+
20
+ private
21
+
22
+ def build_filters
23
+ options.each do |key, value|
24
+ add_to_filters(key.to_s, value)
25
+ end
26
+ end
27
+
28
+ def add_to_filters(key, value)
29
+ if supported_filters.include?(key) && !value.empty?
30
+ @filters_hash[key] = prepare_filter_value(value)
31
+ end
32
+ end
33
+
34
+ def prepare_filter_value(value)
35
+ values = value.split(",")
36
+ build_nested_values(values) || values.first
37
+ end
38
+
39
+ def build_nested_values(values)
40
+ if values.length > 1
41
+ Hash.new.tap do |value_hash|
42
+ values.length.times do |num|
43
+ value_hash[num.to_s] = values[num].strip
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ def supported_filters
50
+ %w(date_created valid_till status search common_name product_name_id)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,44 +1,30 @@
1
- require "digicert/cli/order_filterer"
2
- require "digicert/cli/order_reissuer"
1
+ require "digicert/cli/filter_builder"
3
2
 
4
3
  module Digicert
5
4
  module CLI
6
- class Order
7
- attr_reader :order_id, :options
8
-
9
- def initialize(attributes = {})
10
- @options = attributes
11
- @order_id = options.delete(:order_id)
12
- end
13
-
5
+ class Order < Digicert::CLI::Base
14
6
  def list
15
- filtered_orders = apply_filters(orders)
16
- display_orders_in_table(filtered_orders)
7
+ display_orders_in_table(orders)
17
8
  end
18
9
 
19
10
  def find
20
- filtered_orders = apply_filters(orders)
21
- apply_ouput_flag(filtered_orders.first)
22
- end
23
-
24
- def reissue
25
- Digicert::CLI::OrderReissuer.new(
26
- order_id: order_id, **options
27
- ).create
11
+ apply_ouput_flag(orders.first)
28
12
  end
29
13
 
30
14
  private
31
15
 
32
16
  def orders
33
- @orders ||= order_api.all
17
+ @orders ||= order_api.all(filter_options)
34
18
  end
35
19
 
36
20
  def order_api
37
21
  Digicert::Order
38
22
  end
39
23
 
40
- def apply_filters(orders)
41
- Digicert::CLI::OrderFilterer.filter(orders, options)
24
+ def filter_options
25
+ if options[:filter]
26
+ { filters: Digicert::CLI::FilterBuilder.build(options[:filter]) }
27
+ end
42
28
  end
43
29
 
44
30
  def apply_ouput_flag(order)
@@ -1,26 +1,75 @@
1
+ require "date"
2
+
3
+ require "digicert/cli/order_retriever"
4
+ require "digicert/cli/certificate_downloader"
5
+
1
6
  module Digicert
2
7
  module CLI
3
- class OrderReissuer
4
- attr_reader :order_id, :options
5
-
6
- def initialize(order_id:, **options)
7
- @order_id = order_id
8
- @options = options
8
+ class OrderReissuer < Digicert::CLI::Base
9
+ def create
10
+ apply_output_options(reissue_an_order)
9
11
  end
10
12
 
11
- def create
12
- reissue = Digicert::OrderReissuer.create(order_id: order_id)
13
- apply_output_options(reissue)
13
+ def self.create(attributes)
14
+ new(attributes).create
14
15
  end
15
16
 
16
17
  private
17
18
 
19
+ attr_reader :csr_file, :output_path
20
+
21
+ def extract_local_attributes(options)
22
+ @csr_file = options.fetch(:crt, nil)
23
+ @output_path = options.fetch(:output, "/tmp")
24
+ end
25
+
26
+ def reissue_an_order
27
+ Digicert::OrderReissuer.create(order_params)
28
+ end
29
+
30
+ def order_params
31
+ Hash.new.tap do |order_params|
32
+ order_params[:order_id] = order_id
33
+
34
+ if csr_file && File.exists?(csr_file)
35
+ order_params[:certificate] = { csr: File.read(csr_file) }
36
+ end
37
+ end
38
+ end
39
+
18
40
  def apply_output_options(reissue)
19
41
  if reissue
20
- request_id = reissue.requests.first.id
21
- "Reissue request #{request_id} created for order - #{order_id}"
42
+ print_request_details(reissue.requests.first)
43
+ fetch_and_download_certificate(reissue.id)
22
44
  end
23
45
  end
46
+
47
+ def print_request_details(request)
48
+ Digicert::CLI::Util.say(
49
+ "Reissue request #{request.id} created for order - #{order_id}",
50
+ )
51
+ end
52
+
53
+ def fetch_and_download_certificate(reissued_order_id)
54
+ if options[:output]
55
+ order = fetch_reissued_order(reissued_order_id)
56
+ download_certificate_order(order.certificate.id)
57
+ end
58
+ end
59
+
60
+ def fetch_reissued_order(reissued_order_id)
61
+ Digicert::CLI::OrderRetriever.fetch(
62
+ reissued_order_id,
63
+ wait_time: options[:wait_time],
64
+ number_of_times: options[:number_of_times]
65
+ )
66
+ end
67
+
68
+ def download_certificate_order(certificate_id)
69
+ Digicert::CLI::CertificateDownloader.download(
70
+ filename: order_id, path: output_path, certificate_id: certificate_id
71
+ )
72
+ end
24
73
  end
25
74
  end
26
75
  end