digicert-cli 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []