digicert 0.1.0 → 0.1.1

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 (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