digicert-cli 0.1.0 → 0.2.0

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