digicert-cli 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d58010c165e4fb5ca8dab1177536629119f55bf2
4
+ data.tar.gz: 4d1d6c1db358babe1cbb25b46991a1d3452c600e
5
+ SHA512:
6
+ metadata.gz: e260958d36db163a0d06c9cce128d98bce2212f4d89f07b5a20d2ff7157d60db3dcb0cef6cafd168ccafbdac1b8368479023e15719c3fba1125cb4904ddf69f8
7
+ data.tar.gz: d488abf8b7bad01d645f64ff2030481759c752a0f2b16fadfa764b1ecf987d8801753a53d3465c4d944905c2b5b895f38550f30d0825edf1addcd798f02f16b1
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ source_credentials.sh
2
+ .DS_Store
3
+ /.bundle/
4
+ /.yardoc
5
+ /.pryrc
6
+ /Gemfile.lock
7
+ /_yardoc/
8
+ /coverage/
9
+ /doc/
10
+ /pkg/
11
+ /spec/reports/
12
+ /tmp/
13
+
14
+ # rspec failure tracking
15
+ .rspec_status
data/.sample.env ADDED
@@ -0,0 +1 @@
1
+ DIGICERT_API_KEY=YOUR_DIGICERT_API_KEY
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.1
5
+
6
+ before_install:
7
+ - cp .sample.env .env
8
+ - gem install bundler -v 1.14.6
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in digicert-cli.gemspec
4
+ gemspec
5
+
6
+ gem "digicert", github: "riboseinc/digicert", ref: "f122a4b"
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # Digicert CLI
2
+
3
+ [![Build
4
+ Status](https://travis-ci.org/riboseinc/digicert-cli.svg?branch=master)](https://travis-ci.org/riboseinc/digicert-cli)
5
+
6
+ The CLI for the Digicert API
7
+
8
+ ## Usages
9
+
10
+ ### Orders
11
+
12
+ This CLI provides an easier interface to list the orders from the Digicert API.
13
+ To retrieve the list of the certificate orders we can use
14
+
15
+ ```sh
16
+ digicert order list
17
+ ```
18
+
19
+ Digicert does not have any a direct interface to filter certificate orders,
20
+ but we have added partial support for filtering, to filter the orders by any
21
+ specific criteria please pass those as option to the `order list` interface.
22
+ Currently supported options are `common_name` and `product_type`.
23
+
24
+ ```sh
25
+ digicert order list -c "ribosetest.com" -p "ssl_plus"
26
+ ```
27
+
28
+ ### Single Order
29
+
30
+ Use `find` interface to retrieve a single order, this interface supports all
31
+ default filters.
32
+
33
+ ```sh
34
+ digicert order find -c "ribosetest.com" -p "ssl_plus" --status expired
35
+ ```
36
+
37
+ This interface also allow us to specific a flag in case we only want to find
38
+ the `id` for the resource.
39
+
40
+ ```sh
41
+ digicert order find -c "ribosetest.com" -p "ssl_plus" --status expired --quiet
42
+ ```
43
+
44
+ ### Reissue an order
45
+
46
+ To reissue an existing order, we can use the following interface.
47
+
48
+ ```sh
49
+ digicert order reissue --order_id 12345
50
+ ```
51
+
52
+ ## Development
53
+
54
+ We are following Sandi Metz's Rules for this gem, you can read the
55
+ [description of the rules here][sandi-metz] All new code should follow these
56
+ rules. If you make changes in a pre-existing file that violates these rules you
57
+ should fix the violations as part of your contribution.
58
+
59
+ ### Setup
60
+
61
+ Clone the repository.
62
+
63
+ ```sh
64
+ git clone https://github.com/abunashir/digicert-cli
65
+ ```
66
+
67
+ Setup your environment.
68
+
69
+ ```sh
70
+ bin/setup
71
+ ```
72
+
73
+ Run the test suite
74
+
75
+ ```sh
76
+ bin/rspec
77
+ ```
78
+
79
+ ## Contributing
80
+
81
+ First, thank you for contributing! We love pull requests from everyone. By
82
+ participating in this project, you hereby grant [Ribose Inc.][riboseinc] the
83
+ right to grant or transfer an unlimited number of non exclusive licenses or
84
+ sub-licenses to third parties, under the copyright covering the contribution
85
+ to use the contribution by all means.
86
+
87
+ Here are a few technical guidelines to follow:
88
+
89
+ 1. Open an [issue][issues] to discuss a new feature.
90
+ 1. Write tests to support your new feature.
91
+ 1. Make sure the entire test suite passes locally and on CI.
92
+ 1. Open a Pull Request.
93
+ 1. [Squash your commits][squash] after receiving feedback.
94
+ 1. Party!
95
+
96
+
97
+ ## Credits
98
+
99
+ This gem is developed, maintained and funded by [Ribose Inc.][riboseinc]
100
+
101
+ [riboseinc]: https://www.ribose.com
102
+ [issues]: https://github.com/abunashir/digicert-cli/issues
103
+ [squash]: https://github.com/thoughtbot/guides/tree/master/protocol/git#write-a-feature
104
+ [sandi-metz]: http://robots.thoughtbot.com/post/50655960596/sandi-metz-rules-for-developers
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "digicert/cli"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/digicert ADDED
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # resolve bin path, ignoring symlinks
5
+ require "pathname"
6
+ bin_file = Pathname.new(__FILE__).realpath
7
+
8
+ # add self to libpath
9
+ $:.unshift File.expand_path("../../lib", bin_file)
10
+
11
+ # Fixes https://github.com/rubygems/rubygems/issues/1420
12
+ require "rubygems/specification"
13
+
14
+ class Gem::Specification
15
+ def this; self; end
16
+ end
17
+
18
+ # start up the CLI
19
+ require "bundler/setup"
20
+ require "digicert/cli"
21
+
22
+ Digicert::CLI.start(*ARGV)
data/bin/rspec ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'rspec' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("rspec-core", "rspec")
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,41 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "digicert/cli/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "digicert-cli"
8
+ spec.version = Digicert::CLI::VERSION
9
+ spec.authors = ["Ribose Inc."]
10
+ spec.email = ["operations@ribose.com"]
11
+
12
+ spec.summary = %q{The CLI for digicert API}
13
+ spec.description = %q{The CLI for digicert API}
14
+ spec.homepage = "https://www.ribose.com"
15
+
16
+ spec.files = `git ls-files`.split("\n")
17
+ spec.test_files = `git ls-files -- {spec}/*`.split("\n")
18
+
19
+ spec.require_paths = ["lib"]
20
+ spec.bindir = "bin"
21
+ spec.executables = "digicert"
22
+
23
+ # Digicert gem dpendenceis
24
+ #
25
+ # We are developing this cli and the digicert gem at the same time
26
+ # and we might not instantly push the digicert gems to rubygems while
27
+ # we are adding any new features. So let's use the one from our github
28
+ # and once we are close to finalize then we will switch to the actual
29
+ # digicert gem from rubygems.
30
+ #
31
+ # spec.add_dependency "digicert", "~> 0.1.1"
32
+ #
33
+
34
+ spec.add_dependency "terminal-table"
35
+
36
+ spec.add_development_dependency "bundler", "~> 1.14"
37
+ spec.add_development_dependency "dotenv"
38
+ spec.add_development_dependency "rake", "~> 10.0"
39
+ spec.add_development_dependency "rspec", "~> 3.0"
40
+ spec.add_development_dependency "webmock", "~> 2.0"
41
+ end
data/legacy_cli.sh ADDED
@@ -0,0 +1,301 @@
1
+ #!/bin/bash
2
+
3
+ # USAGE:
4
+ # export API_DIGICERT_KEY="MY KEY"
5
+ # export API_DIGICERT_ACCOUNT_ID="ACCOUNT ID"
6
+ # ./build_cert.sh reissue -o 00900495 -n star_ribose_com -c "*.ribose.com"
7
+ # ./build_cert.sh retrieve -o 00900495 -n star_ribose_com
8
+
9
+ # TODO: as certificate generation takes time, if we run two "reissues" in
10
+ # parallel, only the last one will be generated and therefore we lose the first
11
+ # request! Use the "comments" field to store some unique number that we can
12
+ # match later on retrieval to ensure it is the same request.
13
+
14
+ readonly __progname=$(basename $0)
15
+ readonly api_digicert_key="${API_DIGICERT_KEY}"
16
+ readonly digicert_account_id="${API_DIGICERT_ACCOUNT_ID}"
17
+
18
+ #digicert_orders="
19
+ #star_ribose_com:00900495
20
+ #www_ribose_com:00900495
21
+ #"
22
+ #star_ribose_com:00427785
23
+
24
+ readonly digicert_api_user="-u \"${digicert_account_id}:${api_digicert_key}\""
25
+ readonly digicert_contenttype="-H \"Content-Type: application/vnd.digicert.rest-v1+json\""
26
+ readonly curl_cmd="curl -s"
27
+
28
+ errx() {
29
+ printf "$__progname: $@\n" >&2
30
+ exit 1
31
+ }
32
+
33
+ mkjson() {
34
+ local readonly tmpfile=$(mktemp) || \
35
+ errx "Failed to create temp file"
36
+ echo '{
37
+ "comments": "COMMENTS",
38
+ "common_name": "COMMONNAME",
39
+ "sans": "SANS",
40
+ "server_type": 2,
41
+ "csr": "CSRS"
42
+ }' > ${tmpfile} || \
43
+ errx "Failed to write temp json file"
44
+
45
+ echo ${tmpfile}
46
+ }
47
+
48
+ retrieve_cert() {
49
+ local order_id=$1
50
+ local name=$2
51
+ local destination=$3
52
+
53
+ local digicert_api_url_retrieve="https://api.digicert.com/order/${order_id}/certificate"
54
+ local responsejson=${destination}/retrieve.response.json
55
+
56
+ cmd="${curl_cmd} \
57
+ ${digicert_api_user} \
58
+ ${digicert_contenttype} \
59
+ -o ${responsejson} \
60
+ ${digicert_api_url_retrieve}"
61
+
62
+ echo "------- CURL COMMAND IS -------" >&2
63
+ echo ${cmd} >&2
64
+ echo "------- CURL COMMAND END -------" >&2
65
+
66
+ eval ${cmd} >&2 || \
67
+ errx "curl failed"
68
+
69
+ # If the certificate is not yet available, CURL still returns success.
70
+ # However, the response json will be:
71
+ # {"errors":[{"code":"cert_unavailable_processing","description":"Unable to download certificate, the certificate has not yet been issued. Try back in a bit."}]}
72
+
73
+ # exit 2 if the cert isn't ready
74
+ cat ${responsejson} | grep -q "the certificate has not yet been issued" && \
75
+ exit 2
76
+
77
+ echo "------- JSON RETRIEVED IS -------" >&2
78
+ cat ${responsejson} >&2
79
+ printf "\n" >&2
80
+ echo "------- JSON RETRIEVED END -------" >&2
81
+
82
+ local has_error=$(jq -r '.errors[]? | has("description")' ${responsejson})
83
+
84
+ if [ "${has_error}" == "true" ]; then
85
+ printf "\n\n******** Retrieval error ********: \n $(jq -r '.errors[]' ${responsejson})\n\n" >&2
86
+ errx "Failed to retrieve certificate."
87
+ fi
88
+
89
+ local filename=""
90
+ for key in certificate intermediate root pkcs7; do
91
+ filename=${destination}/${name}.${key}
92
+ echo "Generating $filename..." >&2
93
+ # sed removes the empty lines
94
+ # tr removes the \r's (Ctrl-M's)
95
+ jq -r ".certs.${key}" ${responsejson} | sed '/^$/d' | tr -d $'\r' > ${filename}
96
+ done
97
+
98
+ filename=${destination}/${name}.chain
99
+ echo "Generating $filename..." >&2
100
+ cat ${destination}/${name}.{intermediate,root} > ${filename}
101
+
102
+ filename=${destination}/${name}.pem
103
+ echo "Generating $filename..." >&2
104
+ cat ${destination}/${name}.{certificate,intermediate,root} > ${filename}
105
+
106
+ echo "Retrieve certificate complete." >&2
107
+ }
108
+
109
+ # Note: if we change the Common Name, there will be a long wait before the cert
110
+ # is ready.
111
+ reissue_cert() {
112
+ local order_id=$1
113
+ local name=$2
114
+ local destination=$3
115
+
116
+ local cn="*.ribose.com"
117
+ [[ "$4" ]] && \
118
+ cn=$4
119
+
120
+ local cipher_type=$5
121
+ local sans="" # "www-afnj8x.ribose.com,www-xfgho3.ribose.com"
122
+ [[ "$6" ]] && \
123
+ sans=$6
124
+
125
+ local method_reissue="-X REISSUE"
126
+ local digicert_api_url_reissue="https://api.digicert.com/order/${order_id}"
127
+ local responsejson=${destination}/reissue.response.json
128
+ local jsonpath=$(mkjson)
129
+ local keypath=${destination}/${name}.key
130
+ local pkeypath=${destination}/${name}.pkey
131
+ local csrpath=${destination}/${name}.csr
132
+ local csrsubj="/C=US/ST=Delaware/L=Wilmington/O=Ribose Inc./CN=${cn}"
133
+ local genkey_cmd=""
134
+ local gencsr_cmd=""
135
+
136
+ if [ "${cipher_type}" == "rsa" ]; then
137
+ gencsr_cmd="openssl req -new -newkey rsa:2048 -nodes -out ${csrpath} -keyout ${keypath} -subj \"${csrsubj}\""
138
+ echo "${gencsr_cmd}" >&2
139
+ eval "$gencsr_cmd" || \
140
+ errx "Failed to generate CSR (certificate signing request)"
141
+ else
142
+ genkey_cmd="openssl ecparam -out ${pkeypath} -name prime256v1 -genkey"
143
+ gencsr_cmd="openssl req -new -key ${pkeypath} -nodes -out ${csrpath} -subj \"${csrsubj}\""
144
+
145
+ if [ "${genkey_cmd}" ]; then
146
+ echo ${genkey_cmd} >&2
147
+ $genkey_cmd || \
148
+ errx "Failed to generate certificate key"
149
+ fi
150
+
151
+ # AWS IAM EC certificate needs to remove ""
152
+ # http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/ssl-server-cert.html
153
+ # When you specify an ECDHE-ECDSA private key for a certificate that you will
154
+ # upload to IAM, you must delete the lines containing "-----BEGIN EC
155
+ # PARAMETERS-----" and "-----END EC PARAMETERS-----", and the line in between
156
+ # these lines.
157
+
158
+ local readonly key_demarc="/^-----BEGIN EC PRIVATE KEY-----\$/,\$!d"
159
+ local keypath=${destination}/${name}.key
160
+ echo "Generating $keypath..." >&2
161
+ extract_key_cmd="cat ${pkeypath} | sed '${key_demarc}' > ${keypath}"
162
+ echo ${extract_key_cmd} >&2
163
+ eval ${extract_key_cmd} || \
164
+ errx "Failed to extract private key from pkey file"
165
+
166
+ echo "${gencsr_cmd}" >&2
167
+ eval "$gencsr_cmd" || \
168
+ errx "Failed to generate CSR (certificate signing request)"
169
+ fi
170
+
171
+ # input
172
+ local csrcontent=$(<${csrpath})
173
+ # template
174
+ local jsoncontent=$(<${jsonpath})
175
+ echo "${jsoncontent//COMMONNAME/${cn}}" > ${jsonpath}
176
+ local jsoncontent=$(<${jsonpath})
177
+ echo "${jsoncontent//COMMENTS/${sans}}" > ${jsonpath}
178
+ local jsoncontent=$(<${jsonpath})
179
+ echo "${jsoncontent//SANS/${sans}}" > ${jsonpath}
180
+ local jsoncontent=$(<${jsonpath})
181
+ echo "${jsoncontent//CSRS/${csrcontent}}" > ${jsonpath}
182
+
183
+ echo "------- JSON TO BE SUBMITTED IS -------" >&2
184
+ cat ${jsonpath} >&2
185
+ echo "------- JSON TO BE SUBMITTED END -------" >&2
186
+
187
+ cmd="${curl_cmd} \
188
+ ${digicert_api_user} \
189
+ ${method_reissue} \
190
+ ${digicert_contenttype} \
191
+ -o ${responsejson} \
192
+ --data @${jsonpath} \
193
+ ${digicert_api_url_reissue}"
194
+
195
+ echo "------- CURL COMMAND IS -------" >&2
196
+ echo ${cmd} >&2
197
+ echo "------- CURL COMMAND END -------" >&2
198
+
199
+ eval ${cmd} >&2 || \
200
+ errx "curl failed"
201
+
202
+ echo "------- JSON RETRIEVED IS -------" >&2
203
+ cat ${responsejson} >&2
204
+ printf "\n" >&2
205
+ echo "------- JSON RETRIEVED END -------" >&2
206
+
207
+ local has_error=$(jq -r '.errors[]? | has("description")' ${responsejson})
208
+ if [ "${has_error}" == "true" ]; then
209
+ printf "\n\n******** Reissue error ********:\n $(jq -r '.errors[]' ${responsejson})\n\n" >&2
210
+ errx "Failed to reissue certificate."
211
+ fi
212
+
213
+ echo "Reissue certificate request submitted. Waiting for it to be available." >&2
214
+ }
215
+
216
+ usage() {
217
+ local progname=$(basename $__progname)
218
+ echo "Usage: $progname"
219
+ echo " $progname (command: reissue | retrieve) (options)"
220
+ echo " $progname retrieve -n <certificate-name> -o <order-id> [-p <path>]"
221
+ echo " $progname reissue -n <certificate-name> -o <order-id> -c '<common-name>' [-s <comma-separated SANS: abc.com,bbc.com>] [-p <path>] [-t <cipher type: ec | rsa>]"
222
+ echo " Note: if you want to generate a wildcard certificate (common name starts with *), remember to quote it in the -c option!!!"
223
+
224
+ exit 1;
225
+ } >&2
226
+
227
+ main() {
228
+ if ([ -z $API_DIGICERT_KEY ] || [ -z $API_DIGICERT_ACCOUNT_ID ]); then
229
+ echo "You must specify these environment variables for authentication: API_DIGICERT_KEY, API_DIGICERT_ACCOUNT_ID" >&2
230
+ exit 1
231
+ fi
232
+
233
+ [ ! $1 ] && \
234
+ usage
235
+
236
+ local readonly cmd=$1;
237
+ shift
238
+
239
+ ([ "${cmd}" != "retrieve" ] && [ "${cmd}" != "reissue" ]) && \
240
+ usage
241
+
242
+ local sans=""
243
+ local cipher_type="rsa"
244
+
245
+ while getopts ":n:o:c:s:p:i:h:t:" o; do
246
+ case "${o}" in
247
+ n)
248
+ name=${OPTARG}
249
+ ;;
250
+ o)
251
+ order_id=${OPTARG}
252
+ ;;
253
+ c)
254
+ common_name=${OPTARG}
255
+ ;;
256
+ s)
257
+ sans=${OPTARG}
258
+ ;;
259
+ p)
260
+ certpath=${OPTARG}
261
+ ;;
262
+ t)
263
+ cipher_type=${OPTARG}
264
+ ;;
265
+ i)
266
+ iid=${OPTARG}
267
+ ;;
268
+ h)
269
+ usage
270
+ ;;
271
+ *)
272
+ usage
273
+ ;;
274
+ esac
275
+ done
276
+ shift $((OPTIND-1))
277
+
278
+ [ -z "${name}" ] && \
279
+ errx "Must provide '-n' certificate name"
280
+
281
+ [ -z "${order_id}" ] && \
282
+ errx "Must provide '-o' order_id"
283
+
284
+ if [ -z ${certpath} ]; then
285
+ certpath=$(pwd)/${name}
286
+ mkdir -p ${certpath} || \
287
+ errx "mkdir -p ${certpath}"
288
+ fi
289
+
290
+ [ ${cmd} == "reissue" ] && [ -z "${common_name}" ] && \
291
+ errx "Must provide '-c' common name for reissue"
292
+
293
+ ${cmd}_cert ${order_id} ${name} ${certpath} ${common_name} ${cipher_type} "${sans}"
294
+ echo
295
+ }
296
+
297
+ main "$@"
298
+
299
+ # ./reissue_certificate.sh -o 00900495 -n star_ribose_com -c *.ribose.com
300
+
301
+ exit 0
@@ -0,0 +1,5 @@
1
+ require "dotenv/load"
2
+
3
+ Digicert.configure do |config|
4
+ config.api_key = ENV["DIGICERT_API_KEY"]
5
+ end
@@ -0,0 +1,50 @@
1
+ module Digicert
2
+ module CLI
3
+ module Command
4
+ class Order
5
+ attr_reader :order_id, :options
6
+
7
+ def initialize(attributes = {})
8
+ @options = attributes
9
+ @order_id = options[:order_id]
10
+ end
11
+
12
+ def list
13
+ find_order || order_api.all
14
+ end
15
+
16
+ def find
17
+ find_order || filter_order
18
+ end
19
+
20
+ private
21
+
22
+ def find_order
23
+ if order_id
24
+ order_api.fetch(order_id)
25
+ end
26
+ end
27
+
28
+ def filter_order
29
+ list.select do |order|
30
+ filter_by_common_name(order) && filter_by_product_type(order)
31
+ end
32
+ end
33
+
34
+ def filter_by_common_name(order)
35
+ !options[:common_name] ||
36
+ options[:common_name] == order.certificate.common_name
37
+ end
38
+
39
+ def filter_by_product_type(order)
40
+ !options[:product_type] ||
41
+ options[:product_type] == order.product_name_id
42
+ end
43
+
44
+ def order_api
45
+ Digicert::Order
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,58 @@
1
+ require "optparse"
2
+ require "digicert/cli/order"
3
+
4
+ module Digicert
5
+ module CLI
6
+ module Command
7
+ def self.run(command, subcommand, args = {})
8
+ command_klass = command_handler(command)
9
+ attributes = parse_option_arguments(args)
10
+
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]"
33
+
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
46
+
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
+ ]
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,66 @@
1
+ require "digicert/cli/order_filterer"
2
+ require "digicert/cli/order_reissuer"
3
+
4
+ module Digicert
5
+ 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
+
14
+ def list
15
+ filtered_orders = apply_filters(orders)
16
+ display_orders_in_table(filtered_orders)
17
+ end
18
+
19
+ 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
28
+ end
29
+
30
+ private
31
+
32
+ def orders
33
+ @orders ||= order_api.all
34
+ end
35
+
36
+ def order_api
37
+ Digicert::Order
38
+ end
39
+
40
+ def apply_filters(orders)
41
+ Digicert::CLI::OrderFilterer.filter(orders, options)
42
+ end
43
+
44
+ def apply_ouput_flag(order)
45
+ options[:quiet] ? order.id : order
46
+ end
47
+
48
+ def display_orders_in_table(orders)
49
+ orders_attribtues = orders.map do |order|
50
+ [
51
+ order.id,
52
+ order.product_name_id,
53
+ order.certificate.common_name,
54
+ order.status,
55
+ order.certificate.valid_till,
56
+ ]
57
+ end
58
+
59
+ Digicert::CLI::Util.make_it_pretty(
60
+ rows: orders_attribtues,
61
+ headings: ["Id", "Product Type", "Common Name", "Status", "Expiry"],
62
+ )
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,43 @@
1
+ module Digicert
2
+ module CLI
3
+ class OrderFilterer
4
+ attr_reader :orders
5
+
6
+ def initialize(orders:, filters:)
7
+ @orders = orders
8
+ @status = filters.fetch(:status, nil)
9
+ @common_name = filters.fetch(:common_name, nil)
10
+ @product_type = filters.fetch(:product_type, nil)
11
+ end
12
+
13
+ def filter
14
+ orders.select {|order| apply_option_filters(order) }
15
+ end
16
+
17
+ def self.filter(orders, filter_options)
18
+ new(orders: orders, filters: filter_options).filter
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :status, :common_name, :product_type
24
+
25
+ def apply_option_filters(order)
26
+ filter_by_common_name(order) &&
27
+ filter_by_product_type(order) && filter_by_status(order)
28
+ end
29
+
30
+ def filter_by_status(order)
31
+ !status || status == order.status
32
+ end
33
+
34
+ def filter_by_common_name(order)
35
+ !common_name || common_name == order.certificate.common_name
36
+ end
37
+
38
+ def filter_by_product_type(order)
39
+ !product_type || product_type == order.product.name_id
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,26 @@
1
+ module Digicert
2
+ 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
9
+ end
10
+
11
+ def create
12
+ reissue = Digicert::OrderReissuer.create(order_id: order_id)
13
+ apply_output_options(reissue)
14
+ end
15
+
16
+ private
17
+
18
+ def apply_output_options(reissue)
19
+ if reissue
20
+ request_id = reissue.requests.first.id
21
+ "Reissue request #{request_id} created for order - #{order_id}"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,16 @@
1
+ require "terminal-table"
2
+
3
+ module Digicert
4
+ module CLI
5
+ module Util
6
+ def self.make_it_pretty(headings:, rows:, table_wdith: 80)
7
+ Terminal::Table.new do |table|
8
+ table.headings = headings
9
+ table.style = { width: table_wdith }
10
+
11
+ table.rows = rows
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ module Digicert
2
+ module CLI
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,20 @@
1
+ require "optparse"
2
+ require "digicert"
3
+
4
+ require "digicert/cli/util"
5
+ require "digicert/cli/auth"
6
+ require "digicert/cli/command"
7
+
8
+ module Digicert
9
+ module CLI
10
+ def self.start(*args)
11
+ command = args.shift.strip rescue help
12
+ subcommand = args.first.start_with?("-") ? "list" : args.shift.strip
13
+
14
+ response = Digicert::CLI::Command.run(command, subcommand, args)
15
+
16
+ $stdout.write(response)
17
+ $stdout.write("\n")
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "Order" do
4
+ describe "listing orders" do
5
+ it "retrieves the list of the orders" do
6
+ command = %w(order list -c *.ribostetest.com -p ssl_wildcard)
7
+
8
+ allow($stdout).to receive(:write)
9
+ allow(Digicert::Order).to receive(:all).and_return([])
10
+
11
+ Digicert::CLI.start(*command)
12
+
13
+ expect(Digicert::Order).to have_received(:all)
14
+ end
15
+ end
16
+
17
+ describe "finding an order" do
18
+ it "finds a specific order based on the filters params" do
19
+ command = %w(order find -c ribosetest.com -p -s expired)
20
+ allow(Digicert::CLI::Order).to receive_message_chain(:new, :find)
21
+
22
+ Digicert::CLI.start(*command)
23
+
24
+ expect(Digicert::CLI::Order.new).to have_received(:find)
25
+ end
26
+ end
27
+
28
+ describe "reissuing an order" do
29
+ it "reissues the order and print out the details" do
30
+ command = %w(order reissue --order_id 123456)
31
+ allow(Digicert::OrderReissuer).to receive(:create)
32
+
33
+ Digicert::CLI.start(*command)
34
+
35
+ expect(
36
+ Digicert::OrderReissuer,
37
+ ).to have_received(:create).with(order_id: "123456")
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,15 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Digicert::CLI do
4
+ describe ".start" do
5
+ it "sends run message to command handler" do
6
+ shell_command = %w(order find -n order_id)
7
+ allow(Digicert::CLI::Command).to receive(:run)
8
+
9
+ Digicert::CLI.start(*shell_command)
10
+
11
+ expect(Digicert::CLI::Command).to have_received(:run).
12
+ with(shell_command.shift, shell_command.shift, shell_command)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Digicert::CLI::Command do
4
+ describe ".run" do
5
+ it "runs the command through proper handler" do
6
+ mock_cli_order_command_messages(:new, :list)
7
+ Digicert::CLI::Command.run("order", "list")
8
+
9
+ expect(Digicert::CLI::Order.new).to have_received(:list)
10
+ end
11
+ end
12
+
13
+ def mock_cli_order_command_messages(*messages)
14
+ allow(Digicert::CLI::Order).to receive_message_chain(messages)
15
+ end
16
+ end
@@ -0,0 +1,50 @@
1
+ require "spec_helper"
2
+ require "digicert/cli/order_filterer"
3
+
4
+ RSpec.describe Digicert::CLI::OrderFilterer do
5
+ describe ".filter" do
6
+ context "with common name filter" do
7
+ it "it filters the collection by common name" do
8
+ common_name = "digicert.com"
9
+
10
+ orders = Digicert::CLI::OrderFilterer.filter(
11
+ orders_double, common_name: common_name
12
+ )
13
+
14
+ expect(orders.count).to eq(3)
15
+ expect(orders.first.certificate.common_name).to eq(common_name)
16
+ end
17
+ end
18
+
19
+ context "with product type filter" do
20
+ it "filters the collection by product type" do
21
+ product_type = "ssl_plus"
22
+
23
+ orders = Digicert::CLI::OrderFilterer.filter(
24
+ orders_double, product_type: product_type
25
+ )
26
+
27
+ expect(orders.count).to eq(3)
28
+ expect(orders.first.product.name_id).to eq(product_type)
29
+ end
30
+ end
31
+
32
+ context "with order status filter" do
33
+ it "filters the collection by specified status" do
34
+ order_status = "needs_approval"
35
+
36
+ orders = Digicert::CLI::OrderFilterer.filter(
37
+ orders_double, status: order_status
38
+ )
39
+
40
+ expect(orders.count).to eq(2)
41
+ expect(orders.first.status).to eq(order_status)
42
+ end
43
+ end
44
+ end
45
+
46
+ def orders_double
47
+ stub_digicert_order_list_api
48
+ @orders ||= Digicert::Order.all
49
+ end
50
+ end
@@ -0,0 +1,19 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Digicert::CLI::OrderReissuer do
4
+ describe "#create" do
5
+ context "with only order id passed" do
6
+ it "sends create message to digicert order reissuer" do
7
+ order_id = 123_456
8
+ allow(Digicert::OrderReissuer).to receive(:create)
9
+
10
+ reissuer = Digicert::CLI::OrderReissuer.new(order_id: order_id)
11
+ reissuer.create
12
+
13
+ expect(
14
+ Digicert::OrderReissuer
15
+ ).to have_received(:create).with(order_id: order_id)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Digicert::CLI::Order do
4
+ describe "#list" do
5
+ context "without order_id attributes" do
6
+ it "sends all message to digicert order interface" do
7
+ allow(Digicert::Order).to receive(:all).and_return([])
8
+
9
+ order = Digicert::CLI::Order.new
10
+ order.list
11
+
12
+ expect(Digicert::Order).to have_received(:all)
13
+ end
14
+ end
15
+ end
16
+
17
+ describe "#find" do
18
+ context "without any option" do
19
+ it "returns the first filtered order from digicert" do
20
+ common_name = "digicert.com"
21
+ stub_digicert_order_list_api
22
+
23
+ order = Digicert::CLI::Order.new(common_name: common_name).find
24
+
25
+ expect(order.id).not_to be_nil
26
+ expect(order.certificate.common_name).to eq(common_name)
27
+ end
28
+ end
29
+
30
+ context "with quiet option" do
31
+ it "only returns the id from the order" do
32
+ common_name = "digicert.com"
33
+ stub_digicert_order_list_api
34
+
35
+ order_id= Digicert::CLI::Order.new(
36
+ common_name: common_name, quiet: true
37
+ ).find
38
+
39
+ expect(order_id).to be_a(Integer)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,13 @@
1
+ require "webmock/rspec"
2
+ require "bundler/setup"
3
+ require "digicert/cli"
4
+ require "digicert/rspec"
5
+
6
+ RSpec.configure do |config|
7
+ # Enable flags like --only-failures and --next-failure
8
+ config.example_status_persistence_file_path = ".rspec_status"
9
+
10
+ config.expect_with :rspec do |c|
11
+ c.syntax = :expect
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: digicert-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ribose Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: terminal-table
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.14'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.14'
41
+ - !ruby/object:Gem::Dependency
42
+ name: dotenv
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: webmock
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '2.0'
97
+ description: The CLI for digicert API
98
+ email:
99
+ - operations@ribose.com
100
+ executables:
101
+ - digicert
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - ".sample.env"
107
+ - ".travis.yml"
108
+ - Gemfile
109
+ - README.md
110
+ - Rakefile
111
+ - bin/console
112
+ - bin/digicert
113
+ - bin/rspec
114
+ - bin/setup
115
+ - digicert-cli.gemspec
116
+ - legacy_cli.sh
117
+ - lib/digicert/cli.rb
118
+ - lib/digicert/cli/auth.rb
119
+ - lib/digicert/cli/command.rb
120
+ - lib/digicert/cli/command/order.rb
121
+ - lib/digicert/cli/order.rb
122
+ - lib/digicert/cli/order_filterer.rb
123
+ - lib/digicert/cli/order_reissuer.rb
124
+ - lib/digicert/cli/util.rb
125
+ - lib/digicert/cli/version.rb
126
+ - spec/acceptance/order_spec.rb
127
+ - spec/digicert/cli_spec.rb
128
+ - spec/digicert/command_spec.rb
129
+ - spec/digicert/order_filterer_spec.rb
130
+ - spec/digicert/order_reissuer_spec.rb
131
+ - spec/digicert/order_spec.rb
132
+ - spec/spec_helper.rb
133
+ homepage: https://www.ribose.com
134
+ licenses: []
135
+ metadata: {}
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib
140
+ required_ruby_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ required_rubygems_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 2.5.2
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: The CLI for digicert API
156
+ test_files: []