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
data/.sample.env DELETED
@@ -1 +0,0 @@
1
- DIGICERT_API_KEY=YOUR_DIGICERT_API_KEY
data/bin/console DELETED
@@ -1,14 +0,0 @@
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/legacy_cli.sh DELETED
@@ -1,301 +0,0 @@
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
@@ -1,50 +0,0 @@
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
@@ -1,43 +0,0 @@
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
@@ -1,16 +0,0 @@
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
@@ -1,50 +0,0 @@
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