digicert 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (138) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.hound.yml +3 -0
  4. data/.rspec +0 -1
  5. data/.rubocop.yml +629 -0
  6. data/.sample.env +4 -0
  7. data/.sample.pryrc +3 -0
  8. data/.travis.yml +5 -2
  9. data/LICENSE.txt +21 -0
  10. data/README.md +812 -9
  11. data/bin/console +2 -5
  12. data/bin/rspec +17 -0
  13. data/digicert.gemspec +7 -14
  14. data/lib/digicert.rb +40 -2
  15. data/lib/digicert/actions.rb +9 -0
  16. data/lib/digicert/actions/all.rb +27 -0
  17. data/lib/digicert/actions/base.rb +11 -0
  18. data/lib/digicert/actions/create.rb +25 -0
  19. data/lib/digicert/actions/fetch.rb +21 -0
  20. data/lib/digicert/actions/update.rb +25 -0
  21. data/lib/digicert/base.rb +35 -0
  22. data/lib/digicert/base_order.rb +39 -0
  23. data/lib/digicert/certificate.rb +43 -0
  24. data/lib/digicert/certificate_downloader.rb +137 -0
  25. data/lib/digicert/certificate_request.rb +19 -0
  26. data/lib/digicert/client_certificate/base.rb +17 -0
  27. data/lib/digicert/client_certificate/digital_signature_plus.rb +13 -0
  28. data/lib/digicert/client_certificate/email_security_plus.rb +13 -0
  29. data/lib/digicert/client_certificate/premium.rb +17 -0
  30. data/lib/digicert/config.rb +21 -0
  31. data/lib/digicert/configuration.rb +26 -0
  32. data/lib/digicert/container.rb +35 -0
  33. data/lib/digicert/container_template.rb +32 -0
  34. data/lib/digicert/csr_generator.rb +43 -0
  35. data/lib/digicert/debugger.rb +34 -0
  36. data/lib/digicert/domain.rb +59 -0
  37. data/lib/digicert/duplicate_certificate.rb +21 -0
  38. data/lib/digicert/duplicate_certificate_finder.rb +42 -0
  39. data/lib/digicert/email_validation.rb +35 -0
  40. data/lib/digicert/errors.rb +30 -0
  41. data/lib/digicert/errors/forbidden.rb +9 -0
  42. data/lib/digicert/errors/request_error.rb +37 -0
  43. data/lib/digicert/errors/server_error.rb +9 -0
  44. data/lib/digicert/errors/unauthorized.rb +9 -0
  45. data/lib/digicert/expiring_order.rb +21 -0
  46. data/lib/digicert/findable.rb +33 -0
  47. data/lib/digicert/order.rb +81 -0
  48. data/lib/digicert/order_cancellation.rb +25 -0
  49. data/lib/digicert/order_duplicator.rb +11 -0
  50. data/lib/digicert/order_manager.rb +39 -0
  51. data/lib/digicert/order_reissuer.rb +11 -0
  52. data/lib/digicert/organization.rb +43 -0
  53. data/lib/digicert/product.rb +14 -0
  54. data/lib/digicert/request.rb +123 -0
  55. data/lib/digicert/response.rb +30 -0
  56. data/lib/digicert/ssl_certificate/base.rb +9 -0
  57. data/lib/digicert/ssl_certificate/ssl_ev_plus.rb +13 -0
  58. data/lib/digicert/ssl_certificate/ssl_plus.rb +13 -0
  59. data/lib/digicert/ssl_certificate/ssl_wildcard.rb +13 -0
  60. data/lib/digicert/version.rb +23 -1
  61. data/spec/acceptance/certificate_download_spec.rb +68 -0
  62. data/spec/acceptance/duplicating_certificate_spec.rb +86 -0
  63. data/spec/acceptance/reissuing_certificate_spec.rb +104 -0
  64. data/spec/digicert/actions/all_spec.rb +26 -0
  65. data/spec/digicert/actions/create_spec.rb +47 -0
  66. data/spec/digicert/actions/fetch_spec.rb +28 -0
  67. data/spec/digicert/actions/update_spec.rb +39 -0
  68. data/spec/digicert/certificate_downloader_spec.rb +89 -0
  69. data/spec/digicert/certificate_request_spec.rb +49 -0
  70. data/spec/digicert/certificate_spec.rb +93 -0
  71. data/spec/digicert/client_certificate/digital_signature_plus_spec.rb +32 -0
  72. data/spec/digicert/client_certificate/email_security_plus_spec.rb +36 -0
  73. data/spec/digicert/client_certificate/premium_spec.rb +34 -0
  74. data/spec/digicert/config_spec.rb +39 -0
  75. data/spec/digicert/container_spec.rb +44 -0
  76. data/spec/digicert/container_template_spec.rb +32 -0
  77. data/spec/digicert/csr_generator_spec.rb +31 -0
  78. data/spec/digicert/domain_spec.rb +89 -0
  79. data/spec/digicert/duplicate_certificate_finder_spec.rb +27 -0
  80. data/spec/digicert/duplicate_certificate_spec.rb +15 -0
  81. data/spec/digicert/email_validation_spec.rb +26 -0
  82. data/spec/digicert/expiring_order_spec.rb +16 -0
  83. data/spec/digicert/findable_spec.rb +19 -0
  84. data/spec/digicert/order_cancellation_spec.rb +24 -0
  85. data/spec/digicert/order_duplicator_spec.rb +35 -0
  86. data/spec/digicert/order_reissuer_spec.rb +35 -0
  87. data/spec/digicert/order_spec.rb +134 -0
  88. data/spec/digicert/organization_spec.rb +61 -0
  89. data/spec/digicert/product_spec.rb +28 -0
  90. data/spec/digicert/request_spec.rb +47 -0
  91. data/spec/digicert/ssl_certificate/ssl_ev_plus_spec.rb +35 -0
  92. data/spec/digicert/ssl_certificate/ssl_plus_spec.rb +36 -0
  93. data/spec/digicert/ssl_certificate/ssl_wildcard_spec.rb +35 -0
  94. data/spec/fixtures/certificate.pem +79 -0
  95. data/spec/fixtures/certificate.zip +0 -0
  96. data/spec/fixtures/certificate_request.json +116 -0
  97. data/spec/fixtures/certificate_requests.json +59 -0
  98. data/spec/fixtures/certificate_revoked.json +13 -0
  99. data/spec/fixtures/container.json +15 -0
  100. data/spec/fixtures/container_created.json +3 -0
  101. data/spec/fixtures/container_template.json +15 -0
  102. data/spec/fixtures/container_templates.json +14 -0
  103. data/spec/fixtures/containers.json +14 -0
  104. data/spec/fixtures/domain.json +71 -0
  105. data/spec/fixtures/domain_created.json +3 -0
  106. data/spec/fixtures/domains.json +49 -0
  107. data/spec/fixtures/email_validations.json +17 -0
  108. data/spec/fixtures/empty.json +0 -0
  109. data/spec/fixtures/errors.json +6 -0
  110. data/spec/fixtures/expiring_orders.json +20 -0
  111. data/spec/fixtures/order.json +107 -0
  112. data/spec/fixtures/order_created.json +9 -0
  113. data/spec/fixtures/order_duplicated.json +8 -0
  114. data/spec/fixtures/order_duplications.json +57 -0
  115. data/spec/fixtures/order_reissued.json +8 -0
  116. data/spec/fixtures/orders.json +93 -0
  117. data/spec/fixtures/organization.json +35 -0
  118. data/spec/fixtures/organization_created.json +3 -0
  119. data/spec/fixtures/organizations.json +84 -0
  120. data/spec/fixtures/ping.json +3 -0
  121. data/spec/fixtures/product.json +71 -0
  122. data/spec/fixtures/products.json +100 -0
  123. data/spec/fixtures/rsa4096.key +51 -0
  124. data/spec/requests/certificate_duplication_spec.rb +41 -0
  125. data/spec/requests/certificate_generation_spec.rb +93 -0
  126. data/spec/requests/certificate_reissuing_spec.rb +38 -0
  127. data/spec/requests/container_management_spec.rb +36 -0
  128. data/spec/requests/domain_management_spec.rb +64 -0
  129. data/spec/requests/order_client_email_security_plus_spec.rb +38 -0
  130. data/spec/requests/order_management_spec.rb +24 -0
  131. data/spec/requests/order_ssl_ev_plus_spec.rb +57 -0
  132. data/spec/requests/order_ssl_wildcard_spec.rb +57 -0
  133. data/spec/requests/organization_management_spec.rb +22 -0
  134. data/spec/requests/product_management_spec.rb +24 -0
  135. data/spec/requests/request_management_spec.rb +24 -0
  136. data/spec/spec_helper.rb +35 -0
  137. data/spec/support/fake_digicert_api.rb +324 -0
  138. metadata +162 -5
@@ -0,0 +1,30 @@
1
+ require "digicert/errors/request_error"
2
+ require "digicert/errors/forbidden"
3
+ require "digicert/errors/server_error"
4
+ require "digicert/errors/unauthorized"
5
+
6
+ module Digicert
7
+ module Errors
8
+ def self.server_errors
9
+ [
10
+ OpenSSL::SSL::SSLError,
11
+ Errno::ETIMEDOUT,
12
+ Errno::EHOSTUNREACH,
13
+ Errno::ENETUNREACH,
14
+ Errno::ECONNRESET,
15
+ Net::OpenTimeout,
16
+ SocketError,
17
+ Net::HTTPServerError
18
+ ]
19
+ end
20
+
21
+ def self.error_klass_for(response)
22
+ case response
23
+ when *server_errors then Errors::ServerError
24
+ when Net::HTTPUnauthorized then Errors::Unauthorized
25
+ when Net::HTTPForbidden then Errors::Forbidden
26
+ else Errors::RequestError
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,9 @@
1
+ module Digicert
2
+ module Errors
3
+ class Forbidden < RequestError
4
+ def explanation
5
+ "A request to Digicert API was considered forbidden by the server"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,37 @@
1
+ require "digicert/config"
2
+
3
+ module Digicert
4
+ module Errors
5
+ class RequestError < StandardError
6
+ def initialize(msg = {})
7
+ @msg = msg
8
+ super msg
9
+ end
10
+
11
+ def message
12
+ <<-MSG.gsub(/^ {8}/, '')
13
+ #{explanation}:
14
+ #{response_body}
15
+ MSG
16
+ end
17
+
18
+ def explanation
19
+ "A request to Digicert API failed"
20
+ end
21
+
22
+ def kind
23
+ response_body.fetch("code", {})
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :msg
29
+
30
+ def response_body
31
+ JSON[msg] rescue {}
32
+ end
33
+ end
34
+ end
35
+
36
+ Error = Errors::RequestError
37
+ end
@@ -0,0 +1,9 @@
1
+ module Digicert
2
+ module Errors
3
+ class ServerError < RequestError
4
+ def explanation
5
+ "A request to Digicert API caused an unexpected server error"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Digicert
2
+ module Errors
3
+ class Unauthorized < RequestError
4
+ def explanation
5
+ "A request to Digicert API was sent without a valid authentication"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ require "digicert/base"
2
+
3
+ module Digicert
4
+ class ExpiringOrder < Digicert::Base
5
+ include Digicert::Actions::All
6
+
7
+ def self.all(container_id:, **filter_params)
8
+ new(resource_id: container_id, params: filter_params).all
9
+ end
10
+
11
+ private
12
+
13
+ def resources_key
14
+ "expiring_orders"
15
+ end
16
+
17
+ def resource_path
18
+ ["report", "order", resource_id, "expiring"].join("/")
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,33 @@
1
+ module Digicert
2
+ module Findable
3
+ # The `.find` interface is just an alternvatie to instantiate
4
+ # a new object, and please remeber this does not perform any
5
+ # actual API Request. Use this interface whenever you need to
6
+ # instantite an object from an existing id and then perform
7
+ # some operation throught the objec's instnace methods, like
8
+ # `#active`, `#reissue` and etc
9
+ #
10
+ # If you need an actual API response then use the `.fetch`
11
+ # API, that will perform an actual API Reqeust and will return
12
+ # the response from the Digicer API.
13
+ #
14
+ # We are not going to implement this right away, but in long
15
+ # run may be we cna add some sort to lazy evaluation on this
16
+ # interface, but that's not for sure.
17
+ #
18
+ def find(resource_id)
19
+ new(resource_id: resource_id)
20
+ end
21
+
22
+ # Find by object
23
+ #
24
+ # This `find_by_object` interface works more likely a wrapper
25
+ # around `find` interface, it expects the `object` to response
26
+ # to the `id` method. Then it delegates object initialization
27
+ # behavior to the `find` interface.
28
+ #
29
+ def find_by_object(object)
30
+ find(object.id)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,81 @@
1
+ require "digicert/base"
2
+ require "digicert/findable"
3
+
4
+ require "digicert/ssl_certificate/ssl_plus"
5
+ require "digicert/ssl_certificate/ssl_ev_plus"
6
+ require "digicert/ssl_certificate/ssl_wildcard"
7
+
8
+ require "digicert/client_certificate/premium"
9
+ require "digicert/client_certificate/email_security_plus"
10
+ require "digicert/client_certificate/digital_signature_plus"
11
+
12
+ module Digicert
13
+ class Order < Digicert::Base
14
+ extend Digicert::Findable
15
+
16
+ include Digicert::Actions::All
17
+ include Digicert::Actions::Fetch
18
+
19
+ def create
20
+ certificate_klass.create(attributes)
21
+ end
22
+
23
+ def self.create(name_id, attributes)
24
+ new(name_id: name_id, **attributes).create
25
+ end
26
+
27
+ def reissue(attributes = {})
28
+ Digicert::OrderReissuer.create(order_id: resource_id, **attributes)
29
+ end
30
+
31
+ def duplicate(attributes = {})
32
+ Digicert::OrderDuplicator.create(order_id: resource_id, **attributes)
33
+ end
34
+
35
+ def duplicate_certificates
36
+ Digicert::DuplicateCertificate.all(order_id: resource_id)
37
+ end
38
+
39
+ def email_validations
40
+ Digicert::EmailValidation.all(order_id: resource_id)
41
+ end
42
+
43
+ def cancel(note:, **attrs)
44
+ Digicert::OrderCancellation.create(
45
+ order_id: resource_id, note: note, **attrs,
46
+ )
47
+ end
48
+
49
+ private
50
+
51
+ attr_reader :name_id
52
+
53
+ def extract_local_attribute_ids
54
+ @name_id = attributes.delete(:name_id)
55
+ end
56
+
57
+ def resource_path
58
+ "order/certificate"
59
+ end
60
+
61
+ def resources_key
62
+ "orders"
63
+ end
64
+
65
+ def certificate_klass
66
+ certificate_klass_hash[name_id.to_sym] ||
67
+ Digicert::SSLCertificate::SSLPlus
68
+ end
69
+
70
+ def certificate_klass_hash
71
+ {
72
+ ssl_plus: Digicert::SSLCertificate::SSLPlus,
73
+ ssl_wildcard: Digicert::SSLCertificate::SSLWildcard,
74
+ ssl_ev_plus: Digicert::SSLCertificate::SSLEVPlus,
75
+ client_premium: Digicert::ClientCertificate::Premium,
76
+ email_security_plus: Digicert::ClientCertificate::EmailSecurityPlus,
77
+ digital_signature_plus: Digicert::ClientCertificate::DigitalSignaturePlus,
78
+ }
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,25 @@
1
+ require "digicert/base"
2
+
3
+ module Digicert
4
+ class OrderCancellation < Digicert::Base
5
+ def create
6
+ request_klass.new(
7
+ :put, resource_path, default_attributes.merge(attributes),
8
+ ).run
9
+ end
10
+
11
+ def self.create(order_id:, note:, **attributes)
12
+ new(attributes.merge(resource_id: order_id, note: note)).create
13
+ end
14
+
15
+ private
16
+
17
+ def resource_path
18
+ ["order", "certificate", resource_id, "status"].join("/")
19
+ end
20
+
21
+ def default_attributes
22
+ { status: "CANCELED", send_emails: false }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ require "digicert/order_manager"
2
+
3
+ module Digicert
4
+ class OrderDuplicator < Digicert::OrderManager
5
+ private
6
+
7
+ def resource_creation_path
8
+ ["order", "certificate", order_id, "duplicate"].join("/")
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,39 @@
1
+ require "digicert/base"
2
+
3
+ module Digicert
4
+ class OrderManager < Digicert::Base
5
+ include Digicert::Actions::Create
6
+
7
+ def self.create(order_id:, **attributes)
8
+ new(resource_id: order_id, **attributes).create
9
+ end
10
+
11
+ private
12
+
13
+ def validate(attributes)
14
+ order_attributes.merge(attributes)
15
+ end
16
+
17
+ def order_attributes
18
+ {
19
+ certificate: {
20
+ common_name: order.certificate.common_name,
21
+ dns_names: order.certificate.dns_names,
22
+ csr: order.certificate.csr,
23
+ signature_hash: order.certificate.signature_hash,
24
+ server_platform: { id: order.certificate.server_platform.id },
25
+ }
26
+ }
27
+ end
28
+
29
+ def order
30
+ @order ||= Digicert::Order.fetch(order_id)
31
+ end
32
+
33
+ # Expose the resource_id as order_id, as it sounds
34
+ # more readable and all of it's subclasses are only
35
+ # gonna deal with order.
36
+ #
37
+ alias_method :order_id, :resource_id
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ require "digicert/order_manager"
2
+
3
+ module Digicert
4
+ class OrderReissuer < Digicert::OrderManager
5
+ private
6
+
7
+ def resource_creation_path
8
+ ["order", "certificate", order_id, "reissue"].join("/")
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,43 @@
1
+ require "digicert/base"
2
+
3
+ module Digicert
4
+ class Organization < Digicert::Base
5
+ include Digicert::Actions::All
6
+ include Digicert::Actions::Fetch
7
+ include Digicert::Actions::Create
8
+
9
+ private
10
+
11
+ def resource_path
12
+ "organization"
13
+ end
14
+
15
+ def validate(name:, address:, zip:, city:, state:, country:,
16
+ telephone:, container:, organization_contact:, **attributes)
17
+ required_attributes = {
18
+ name: name,
19
+ address: address,
20
+ zip: zip,
21
+ city: city,
22
+ state: state,
23
+ country: country,
24
+ telephone: telephone,
25
+ container: container,
26
+ organization_contact: validate_contact(organization_contact),
27
+ }
28
+
29
+ required_attributes.merge(attributes)
30
+ end
31
+
32
+ def validate_contact(first_name:, last_name:, email:, telephone:, **attrs)
33
+ required_attributes = {
34
+ first_name: first_name,
35
+ last_name: last_name,
36
+ email: email,
37
+ telephone: telephone
38
+ }
39
+
40
+ required_attributes.merge(attrs)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,14 @@
1
+ require "digicert/base"
2
+
3
+ module Digicert
4
+ class Product < Digicert::Base
5
+ include Digicert::Actions::All
6
+ include Digicert::Actions::Fetch
7
+
8
+ private
9
+
10
+ def resource_path
11
+ "product"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,123 @@
1
+ require "uri"
2
+ require "json"
3
+ require "net/http"
4
+ require "digicert/response"
5
+ require "digicert/errors"
6
+
7
+ module Digicert
8
+ class Request
9
+ def initialize(http_method, end_point, params: {}, **attributes)
10
+ @end_point = end_point
11
+ @http_method = http_method
12
+ @attributes = attributes
13
+ @query_params = params
14
+ end
15
+
16
+ def run
17
+ valid_response || raise_response_error
18
+ end
19
+
20
+ def parse
21
+ Digicert::Response.new(run).parse
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :attributes
27
+
28
+ def valid_response
29
+ log_details_in_debug_mode
30
+ return response if valid_response?
31
+ end
32
+
33
+ def valid_response?
34
+ response.is_a?(Net::HTTPSuccess)
35
+ end
36
+
37
+ def response
38
+ @response ||= send_http_request
39
+ rescue *server_errors => error
40
+ @response ||= error
41
+ end
42
+
43
+ def send_http_request
44
+ Net::HTTP.start(*net_http_options) do |http|
45
+ http.request(http_request)
46
+ end
47
+ end
48
+
49
+ def http_request
50
+ @http_request ||= constanize_net_http_class.new(uri).tap do |request|
51
+ set_request_body!(request)
52
+ set_request_headers!(request)
53
+ end
54
+ end
55
+
56
+ def raise_response_error
57
+ raise response_error, error_message
58
+ end
59
+
60
+ def net_http_options
61
+ [uri.host, uri.port, use_ssl: true]
62
+ end
63
+
64
+ def uri
65
+ URI::HTTPS.build(
66
+ host: Digicert.configuration.api_host,
67
+ path: digicert_api_path_with_base,
68
+ query: build_query_params
69
+ )
70
+ end
71
+
72
+ def constanize_net_http_class
73
+ Object.const_get("Net::HTTP::#{@http_method.capitalize}")
74
+ end
75
+
76
+ def set_request_body!(request)
77
+ unless attributes.empty?
78
+ request.body = attributes.to_json
79
+ end
80
+ end
81
+
82
+ def set_request_headers!(request)
83
+ request.initialize_http_header(
84
+ "Content-Type" => "application/json",
85
+ "X-DC-DEVKEY" => Digicert.configuration.api_key
86
+ )
87
+ end
88
+
89
+ def build_query_params
90
+ if @query_params
91
+ URI.encode_www_form(@query_params)
92
+ end
93
+ end
94
+
95
+ def digicert_api_path_with_base
96
+ ["", Digicert.configuration.base_path, @end_point].join("/").squeeze("/")
97
+ end
98
+
99
+ def response_error
100
+ Digicert::Errors.error_klass_for(response)
101
+ end
102
+
103
+ def error_message
104
+ JSON(response.body)["errors"]
105
+ rescue response.inspect
106
+ end
107
+
108
+ def server_errors
109
+ Digicert::Errors.server_errors
110
+ end
111
+
112
+ def debug_mode_on?
113
+ @debug_mode ||= Digicert.configuration.debug_mode?
114
+ end
115
+
116
+ def log_details_in_debug_mode
117
+ if debug_mode_on?
118
+ require "digicert/debugger"
119
+ Digicert::Debugger.new(request: http_request, response: response).debug
120
+ end
121
+ end
122
+ end
123
+ end