varanus 0.2.1 → 0.5.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -6
- data/.travis.yml +1 -2
- data/CHANGELOG.md +18 -1
- data/Gemfile.lock +52 -47
- data/docker-compose.yml +1 -1
- data/lib/varanus.rb +37 -0
- data/lib/varanus/dcv.rb +62 -0
- data/lib/varanus/domain.rb +42 -0
- data/lib/varanus/organization.rb +13 -0
- data/lib/varanus/rest_resource.rb +56 -0
- data/lib/varanus/ssl.rb +42 -60
- data/lib/varanus/ssl/csr.rb +13 -6
- data/lib/varanus/version.rb +1 -1
- data/varanus.gemspec +1 -3
- metadata +8 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 67c52ba9ede6f495a05841bacfbf3046cb41b45cd8bb1d4ef8a1c7491e735644
|
|
4
|
+
data.tar.gz: 921e5bd93bf8caa0378ba15f45276b8100c19239d28e3e22b68e3ae76fa85da1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c2cf7fd0e7ec49ec4b9f6bdef82aae9f7cf8d05f0343cce7d8595dfd6a975cf0fc983045997ec0f6cbc8425b8935ff66bc3a7846cd321a55789508cb4ee03fce
|
|
7
|
+
data.tar.gz: c02ba0dfc6a9132204d50f3bc1453b878c73f34ca981ead6ffd29c35bc91fe637922085ac28ceb831fa0b22fe5fe1a3b61679314b99255e00774346689dc31d8
|
data/.rubocop.yml
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
AllCops:
|
|
2
|
-
|
|
2
|
+
NewCops: disable
|
|
3
|
+
TargetRubyVersion: 2.5
|
|
3
4
|
|
|
4
5
|
Bundler/OrderedGems:
|
|
5
6
|
AutoCorrect: false
|
|
6
7
|
|
|
8
|
+
Layout/LineLength:
|
|
9
|
+
Max: 90
|
|
10
|
+
Exclude:
|
|
11
|
+
- 'test/**/*'
|
|
12
|
+
|
|
7
13
|
Metrics/AbcSize:
|
|
8
14
|
Max: 25
|
|
9
15
|
Exclude:
|
|
@@ -14,11 +20,6 @@ Metrics/ClassLength:
|
|
|
14
20
|
Exclude:
|
|
15
21
|
- 'test/**/*'
|
|
16
22
|
|
|
17
|
-
Metrics/LineLength:
|
|
18
|
-
Max: 90
|
|
19
|
-
Exclude:
|
|
20
|
-
- 'test/**/*'
|
|
21
|
-
|
|
22
23
|
Metrics/MethodLength:
|
|
23
24
|
Max: 20
|
|
24
25
|
Exclude:
|
data/.travis.yml
CHANGED
|
@@ -6,10 +6,9 @@ sudo: false
|
|
|
6
6
|
language: ruby
|
|
7
7
|
cache: bundler
|
|
8
8
|
rvm:
|
|
9
|
-
- 2.3
|
|
10
|
-
- 2.4
|
|
11
9
|
- 2.5
|
|
12
10
|
- 2.6
|
|
11
|
+
- 2.7
|
|
13
12
|
before_install: gem install bundler -v 1.16.5
|
|
14
13
|
before_script:
|
|
15
14
|
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
|
-
### 0.
|
|
1
|
+
### Version 0.5.1 (2021-01-28)
|
|
2
|
+
* Varanus::SSL::CSR - support EC certs
|
|
3
|
+
|
|
4
|
+
### Version 0.5.0 (2021-01-26)
|
|
5
|
+
* Add Varanus::Domain
|
|
6
|
+
* Add Varanus::SSL#list and Varanus::SSL#info
|
|
7
|
+
* Add Varanus::Organization
|
|
8
|
+
|
|
9
|
+
### 0.4.0 (2021-01-06)
|
|
10
|
+
* Add Varanus::DCV
|
|
11
|
+
|
|
12
|
+
### 0.3.1 (2020-10-14)
|
|
13
|
+
* Fix issue when Sectigo reports two identical 'Short Life' certs
|
|
14
|
+
|
|
15
|
+
### 0.3.0 (2020-08-24)
|
|
16
|
+
* Add support for new 'Short Life' certs
|
|
17
|
+
|
|
18
|
+
### 0.2.1 (2018-11-13)
|
|
2
19
|
* Increase timeout value for SSL requests
|
|
3
20
|
|
|
4
21
|
### 0.2.0 (2018-11-09)
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
varanus (0.
|
|
4
|
+
varanus (0.5.1)
|
|
5
5
|
faraday
|
|
6
6
|
faraday_middleware
|
|
7
7
|
savon (~> 2.0)
|
|
@@ -9,58 +9,61 @@ PATH
|
|
|
9
9
|
GEM
|
|
10
10
|
remote: https://rubygems.org/
|
|
11
11
|
specs:
|
|
12
|
-
addressable (2.
|
|
13
|
-
public_suffix (>= 2.0.2, <
|
|
12
|
+
addressable (2.7.0)
|
|
13
|
+
public_suffix (>= 2.0.2, < 5.0)
|
|
14
14
|
akami (1.3.1)
|
|
15
15
|
gyoku (>= 0.4.0)
|
|
16
16
|
nokogiri
|
|
17
|
-
ast (2.4.
|
|
18
|
-
builder (3.2.
|
|
19
|
-
crack (0.4.
|
|
20
|
-
|
|
21
|
-
docile (1.3.
|
|
22
|
-
faraday (
|
|
17
|
+
ast (2.4.1)
|
|
18
|
+
builder (3.2.4)
|
|
19
|
+
crack (0.4.5)
|
|
20
|
+
rexml
|
|
21
|
+
docile (1.3.4)
|
|
22
|
+
faraday (1.3.0)
|
|
23
|
+
faraday-net_http (~> 1.0)
|
|
23
24
|
multipart-post (>= 1.2, < 3)
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
ruby2_keywords
|
|
26
|
+
faraday-net_http (1.0.0)
|
|
27
|
+
faraday_middleware (1.0.0)
|
|
28
|
+
faraday (~> 1.0)
|
|
26
29
|
gyoku (1.3.1)
|
|
27
30
|
builder (>= 2.1.2)
|
|
28
|
-
hashdiff (0.
|
|
29
|
-
httpi (2.4.
|
|
31
|
+
hashdiff (1.0.1)
|
|
32
|
+
httpi (2.4.5)
|
|
30
33
|
rack
|
|
31
34
|
socksify
|
|
32
|
-
|
|
33
|
-
json (2.1.0)
|
|
34
|
-
metaclass (0.0.4)
|
|
35
|
-
mini_portile2 (2.3.0)
|
|
36
|
-
minitest (5.11.3)
|
|
35
|
+
minitest (5.14.3)
|
|
37
36
|
minitest-rg (5.2.0)
|
|
38
37
|
minitest (~> 5.0)
|
|
39
|
-
mocha (1.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
mini_portile2 (~> 2.3.0)
|
|
38
|
+
mocha (1.12.0)
|
|
39
|
+
multipart-post (2.1.1)
|
|
40
|
+
nokogiri (1.11.1-x86_64-linux)
|
|
41
|
+
racc (~> 1.4)
|
|
44
42
|
nori (2.6.0)
|
|
45
|
-
parallel (1.
|
|
46
|
-
parser (
|
|
47
|
-
ast (~> 2.4.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
rack (2.
|
|
43
|
+
parallel (1.20.1)
|
|
44
|
+
parser (3.0.0.0)
|
|
45
|
+
ast (~> 2.4.1)
|
|
46
|
+
public_suffix (4.0.6)
|
|
47
|
+
racc (1.5.2)
|
|
48
|
+
rack (2.2.3)
|
|
51
49
|
rainbow (3.0.0)
|
|
52
50
|
rake (10.5.0)
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
regexp_parser (2.0.3)
|
|
52
|
+
rexml (3.2.4)
|
|
53
|
+
rubocop (1.7.0)
|
|
55
54
|
parallel (~> 1.10)
|
|
56
|
-
parser (>= 2.
|
|
57
|
-
powerpack (~> 0.1)
|
|
55
|
+
parser (>= 2.7.1.5)
|
|
58
56
|
rainbow (>= 2.2.2, < 4.0)
|
|
57
|
+
regexp_parser (>= 1.8, < 3.0)
|
|
58
|
+
rexml
|
|
59
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
|
59
60
|
ruby-progressbar (~> 1.7)
|
|
60
|
-
unicode-display_width (
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
|
62
|
+
rubocop-ast (1.4.0)
|
|
63
|
+
parser (>= 2.7.1.5)
|
|
64
|
+
ruby-progressbar (1.11.0)
|
|
65
|
+
ruby2_keywords (0.0.2)
|
|
66
|
+
savon (2.12.1)
|
|
64
67
|
akami (~> 1.2)
|
|
65
68
|
builder (>= 2.1.2)
|
|
66
69
|
gyoku (~> 1.2)
|
|
@@ -68,21 +71,23 @@ GEM
|
|
|
68
71
|
nokogiri (>= 1.8.1)
|
|
69
72
|
nori (~> 2.4)
|
|
70
73
|
wasabi (~> 3.4)
|
|
71
|
-
simplecov (0.
|
|
74
|
+
simplecov (0.21.1)
|
|
72
75
|
docile (~> 1.1)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
simplecov-html (0.
|
|
76
|
+
simplecov-html (~> 0.11)
|
|
77
|
+
simplecov_json_formatter (~> 0.1)
|
|
78
|
+
simplecov-html (0.12.3)
|
|
79
|
+
simplecov_json_formatter (0.1.2)
|
|
76
80
|
socksify (1.7.1)
|
|
77
|
-
unicode-display_width (1.
|
|
78
|
-
wasabi (3.
|
|
81
|
+
unicode-display_width (1.7.0)
|
|
82
|
+
wasabi (3.6.1)
|
|
83
|
+
addressable
|
|
79
84
|
httpi (~> 2.0)
|
|
80
85
|
nokogiri (>= 1.4.2)
|
|
81
|
-
webmock (3.
|
|
86
|
+
webmock (3.11.0)
|
|
82
87
|
addressable (>= 2.3.6)
|
|
83
88
|
crack (>= 0.3.2)
|
|
84
|
-
hashdiff
|
|
85
|
-
yard (0.9.
|
|
89
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
|
90
|
+
yard (0.9.26)
|
|
86
91
|
|
|
87
92
|
PLATFORMS
|
|
88
93
|
ruby
|
|
@@ -100,4 +105,4 @@ DEPENDENCIES
|
|
|
100
105
|
yard
|
|
101
106
|
|
|
102
107
|
BUNDLED WITH
|
|
103
|
-
1.17.
|
|
108
|
+
1.17.3
|
data/docker-compose.yml
CHANGED
data/lib/varanus.rb
CHANGED
|
@@ -14,6 +14,39 @@ class Varanus
|
|
|
14
14
|
@password = password
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
# :nodoc:
|
|
18
|
+
def connection
|
|
19
|
+
@connection ||= Faraday.new(url: 'https://cert-manager.com/api',
|
|
20
|
+
request: { timeout: 300 }) do |conn|
|
|
21
|
+
conn.request :json
|
|
22
|
+
conn.response :json, content_type: /\bjson$/
|
|
23
|
+
|
|
24
|
+
conn.headers['login'] = @username
|
|
25
|
+
conn.headers['password'] = @password
|
|
26
|
+
conn.headers['customerUri'] = @customer_uri
|
|
27
|
+
|
|
28
|
+
conn.adapter Faraday.default_adapter
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Retrive DCV instance
|
|
33
|
+
# @return [Varanus::DCV]
|
|
34
|
+
def dcv
|
|
35
|
+
@dcv ||= DCV.new(self)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Retrieve Domain instance
|
|
39
|
+
# @return [Varanus::Domain]
|
|
40
|
+
def domain
|
|
41
|
+
@domain ||= Domain.new(self)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Retrieve Organization instance
|
|
45
|
+
# @return [Varanus::Organization]
|
|
46
|
+
def organization
|
|
47
|
+
@organization ||= Organization.new(self)
|
|
48
|
+
end
|
|
49
|
+
|
|
17
50
|
# Retrieve Reports instance
|
|
18
51
|
# @return [Varanus::Reports]
|
|
19
52
|
def reports
|
|
@@ -35,6 +68,10 @@ require 'savon'
|
|
|
35
68
|
|
|
36
69
|
# Require other files in this gem
|
|
37
70
|
require 'varanus/error'
|
|
71
|
+
require 'varanus/rest_resource'
|
|
72
|
+
require 'varanus/dcv'
|
|
73
|
+
require 'varanus/domain'
|
|
74
|
+
require 'varanus/organization'
|
|
38
75
|
require 'varanus/reports'
|
|
39
76
|
require 'varanus/ssl'
|
|
40
77
|
require 'varanus/ssl/csr'
|
data/lib/varanus/dcv.rb
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# An connection to the DCV API. This should not be initialized directly. Instead,
|
|
4
|
+
# use Varanus#dcv
|
|
5
|
+
class Varanus::DCV < Varanus::RestResource
|
|
6
|
+
# Returns an Array of DCV information about searched for domains.
|
|
7
|
+
# This method will automatically page through all results
|
|
8
|
+
# @param opts [Hash] - all opts are optional
|
|
9
|
+
# @option opts [String] :domain Domain to search for
|
|
10
|
+
# @option opts [Integer] :org ID of organization
|
|
11
|
+
# @option opts [Integer] :department ID of department
|
|
12
|
+
# @option opts [String] :dcvStatus
|
|
13
|
+
# @option opts [String] :orderStatus
|
|
14
|
+
# @option opts [Integer] :expiresIn Expires in (days)
|
|
15
|
+
#
|
|
16
|
+
# Results will included an extra 'expiration_date_obj' if 'expirationDate' is in the
|
|
17
|
+
# response
|
|
18
|
+
def search opts = {}
|
|
19
|
+
get_with_size_and_position('dcv/v2/validation', opts).map(&method(:_format_status))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Start domain validation process. This must be called before #submit is called
|
|
23
|
+
# @option domain [String] domain to validate
|
|
24
|
+
# @option type [String] Type of validation. Must be one of 'http', 'https', 'cname',
|
|
25
|
+
# or 'email'
|
|
26
|
+
def start domain, type
|
|
27
|
+
post("dcv/v1/validation/start/domain/#{type}", domain: domain)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Retrieve DCV status for a single domain
|
|
31
|
+
# Result will included an extra 'expiration_date_obj' if 'expirationDate' is in the
|
|
32
|
+
# response
|
|
33
|
+
def status domain
|
|
34
|
+
_format_status(post('dcv/v2/validation/status', domain: domain))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Submit domain validation for verficiation. This must be called after #start
|
|
38
|
+
# @option domain [String] domain to validate
|
|
39
|
+
# @option type [String] Type of validation. Must be one of 'http', 'https', 'cname',
|
|
40
|
+
# or 'email'
|
|
41
|
+
# @option email_address [String] This is required of +type+ is 'email'. Otherwise, it is
|
|
42
|
+
# ignored.
|
|
43
|
+
def submit domain, type, email_address = nil
|
|
44
|
+
if type.to_s == 'email'
|
|
45
|
+
raise ArgumentError, 'email_address must be specified' if email_address.nil?
|
|
46
|
+
|
|
47
|
+
post('dcv/v1/validation/submit/domain/email', domain: domain,
|
|
48
|
+
email: email_address)
|
|
49
|
+
else
|
|
50
|
+
post("dcv/v1/validation/submit/domain/#{type}", domain: domain)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def _format_status status
|
|
57
|
+
return status unless status['expirationDate']
|
|
58
|
+
|
|
59
|
+
status.merge('expiration_date_obj' =>
|
|
60
|
+
Date.strptime(status['expirationDate'], '%Y-%m-%d'))
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# A connection to the Domain API
|
|
4
|
+
class Varanus::Domain < Varanus::RestResource
|
|
5
|
+
# Create a new domain. The domain may need to be manually approved after this is
|
|
6
|
+
# called.
|
|
7
|
+
# +name+ is the domain
|
|
8
|
+
# +delegations+ is an Array of Hashes. Each Hash should have an 'orgId' and
|
|
9
|
+
# 'certTypes' key
|
|
10
|
+
# opts may include the following keys:
|
|
11
|
+
# - :description - optional - String
|
|
12
|
+
# - :active - optional - Boolean (defaults to +true+)
|
|
13
|
+
# - :allow_subdomains - optional - set to +false+ if you don't want to allow sub
|
|
14
|
+
# domains for this entry
|
|
15
|
+
#
|
|
16
|
+
# @returns [String] - URL for newly created domain
|
|
17
|
+
def create domain, delegations, opts = {}
|
|
18
|
+
opts = opts.dup
|
|
19
|
+
allow_subdomains = opts.delete(:allow_subdomains)
|
|
20
|
+
domain = "*.#{domain}" if allow_subdomains != false && !domain.start_with?('*.')
|
|
21
|
+
|
|
22
|
+
result = @varanus.connection.post('domain/v1',
|
|
23
|
+
opts.merge(name: domain, delegations: delegations))
|
|
24
|
+
check_result result
|
|
25
|
+
result.headers['Location']
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Return info on domain. +id+ must be the id returned by #list
|
|
29
|
+
def info id
|
|
30
|
+
get("domain/v1/#{id}")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def list opts = {}
|
|
34
|
+
get_with_size_and_position('domain/v1', opts)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def list_with_info opts = {}
|
|
38
|
+
domains = list(opts)
|
|
39
|
+
domains.map! { |domain| info(domain['id']) }
|
|
40
|
+
domains
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# A connection to the Organization API
|
|
4
|
+
class Varanus::Organization < Varanus::RestResource
|
|
5
|
+
# Return info on organization.
|
|
6
|
+
def info id
|
|
7
|
+
get("organization/v1/#{id}")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def list
|
|
11
|
+
get('organization/v1')
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# An abstract class for rest resources
|
|
4
|
+
# Rest resources should not be initialized directly. They should be created by methods
|
|
5
|
+
# on Varanus
|
|
6
|
+
class Varanus::RestResource
|
|
7
|
+
# :nodoc:
|
|
8
|
+
def initialize varanus
|
|
9
|
+
@varanus = varanus
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def check_result result
|
|
15
|
+
body = result.body
|
|
16
|
+
return unless body.is_a?(Hash)
|
|
17
|
+
return if body['code'].nil?
|
|
18
|
+
|
|
19
|
+
klass = Varanus::Error
|
|
20
|
+
if body['code'] == 0 && body['description'] =~ /process/
|
|
21
|
+
klass = Varanus::Error::StillProcessing
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
raise klass.new(body['code'], body['description'])
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def get path, *args
|
|
28
|
+
result = @varanus.connection.get(path, *args)
|
|
29
|
+
check_result result
|
|
30
|
+
result.body
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Performs multiple GETs with varying positions to ensure all results are returned.
|
|
34
|
+
def get_with_size_and_position path, opts = {}
|
|
35
|
+
size = opts[:size] || 200
|
|
36
|
+
position = opts[:position] || 0
|
|
37
|
+
|
|
38
|
+
results = []
|
|
39
|
+
loop do
|
|
40
|
+
params = { size: size, position: position }.merge(opts)
|
|
41
|
+
new_results = get(path, params)
|
|
42
|
+
results += new_results
|
|
43
|
+
break if new_results.length < size
|
|
44
|
+
|
|
45
|
+
position += size
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
results
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def post path, *args
|
|
52
|
+
result = @varanus.connection.post(path, *args)
|
|
53
|
+
check_result result
|
|
54
|
+
result.body
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/varanus/ssl.rb
CHANGED
|
@@ -2,35 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
# An connection to the SSL/TSL API. This should not be initialized directly. Instead,
|
|
4
4
|
# use Varanus#ssl
|
|
5
|
-
class Varanus::SSL
|
|
6
|
-
# @note Do not call this directly. Use {Varanus#ssl} to initialize
|
|
7
|
-
def initialize varanus
|
|
8
|
-
@varanus = varanus
|
|
9
|
-
end
|
|
10
|
-
|
|
5
|
+
class Varanus::SSL < Varanus::RestResource
|
|
11
6
|
# Returns the option from #certificate_types that best matches the csr.
|
|
12
7
|
# @param csr [Varanus::SSL::CSR]
|
|
13
8
|
# @return [Hash] The option from {#certificate_types} that best matches the csr
|
|
14
|
-
def certificate_type_from_csr csr
|
|
15
|
-
|
|
16
|
-
types
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
types.find do |ct|
|
|
25
|
-
ct['name'] =~ /\bSSL\b/ && ct['name'] !~ /(?:Multi.?Domain|Wildcard)/i
|
|
26
|
-
end
|
|
9
|
+
def certificate_type_from_csr csr, days = nil
|
|
10
|
+
types = certificate_types_standard(days)
|
|
11
|
+
return types.first if types.length <= 1
|
|
12
|
+
|
|
13
|
+
regexp = cert_type_regexp(csr)
|
|
14
|
+
typ = types.find { |ct| ct['name'] =~ regexp } if regexp
|
|
15
|
+
return typ unless typ.nil?
|
|
16
|
+
|
|
17
|
+
types.find do |ct|
|
|
18
|
+
ct['name'] =~ /\bSSL\b/ && ct['name'] !~ /(?:Multi.?Domain|Wildcard)/i
|
|
27
19
|
end
|
|
28
20
|
end
|
|
29
21
|
|
|
30
22
|
# Certificate types that can be used to sign a cert
|
|
31
23
|
# @return [Array<Hash>]
|
|
32
24
|
def certificate_types
|
|
33
|
-
@certificate_types ||= get('types')
|
|
25
|
+
@certificate_types ||= get('ssl/v1/types')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Return Array of certificate types based on standard sorting.
|
|
29
|
+
# @param days [Integer] if present, only include types that support the given day count
|
|
30
|
+
# @return [Array<Hash>]
|
|
31
|
+
def certificate_types_standard days = nil
|
|
32
|
+
types = certificate_types.reject do |ct|
|
|
33
|
+
ct['name'] =~ /\b(?:EV|ECC|AMT|Elite)\b/
|
|
34
|
+
end
|
|
35
|
+
types = types.select! { |t| t['terms'].include? days } unless days.nil?
|
|
36
|
+
|
|
37
|
+
types
|
|
34
38
|
end
|
|
35
39
|
|
|
36
40
|
# Retrieves the cert.
|
|
@@ -48,7 +52,16 @@ class Varanus::SSL
|
|
|
48
52
|
# @raise [Varanus::Error::StillProcessing] Cert is still being signed
|
|
49
53
|
# @return [String] Certificate
|
|
50
54
|
def collect id, type = 'x509'
|
|
51
|
-
get("collect/#{id}/#{type}")
|
|
55
|
+
get("ssl/v1/collect/#{id}/#{type}")
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Returns info on the SSL certificate of the given name
|
|
59
|
+
def info id
|
|
60
|
+
get("ssl/v1/#{id}")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def list opts = {}
|
|
64
|
+
get_with_size_and_position('ssl/v1', opts)
|
|
52
65
|
end
|
|
53
66
|
|
|
54
67
|
# Revoke an ssl cert
|
|
@@ -56,7 +69,7 @@ class Varanus::SSL
|
|
|
56
69
|
# @param reason [String] Reason for revoking. Sectigo's API will return an error if it
|
|
57
70
|
# is blank.
|
|
58
71
|
def revoke id, reason
|
|
59
|
-
post("revoke/#{id}", reason: reason)
|
|
72
|
+
post("ssl/v1/revoke/#{id}", reason: reason)
|
|
60
73
|
nil
|
|
61
74
|
end
|
|
62
75
|
|
|
@@ -75,6 +88,7 @@ class Varanus::SSL
|
|
|
75
88
|
# specified, lowest allowed for the cert type will be used)
|
|
76
89
|
# @return [Integer] Id of SSL cert.
|
|
77
90
|
def sign csr, org_id, opts = {}
|
|
91
|
+
opts[:days] ||= opts[:years] * 365 unless opts[:years].nil?
|
|
78
92
|
csr = Varanus::SSL::CSR.new(csr) unless csr.is_a?(Varanus::SSL::CSR)
|
|
79
93
|
cert_type_id = opts_to_cert_type_id opts, csr
|
|
80
94
|
args = {
|
|
@@ -87,42 +101,17 @@ class Varanus::SSL
|
|
|
87
101
|
comments: opts[:comments].to_s[0, 1024],
|
|
88
102
|
externalRequester: opts[:external_requester].to_s[0, 512]
|
|
89
103
|
}
|
|
90
|
-
post('enroll', args)['sslId']
|
|
104
|
+
post('ssl/v1/enroll', args)['sslId']
|
|
91
105
|
end
|
|
92
106
|
|
|
93
107
|
private
|
|
94
108
|
|
|
95
|
-
def
|
|
96
|
-
|
|
97
|
-
return unless body.is_a?(Hash)
|
|
98
|
-
return if body['code'].nil?
|
|
99
|
-
|
|
100
|
-
klass = Varanus::Error
|
|
101
|
-
if body['code'] == 0 && body['description'] =~ /process/
|
|
102
|
-
klass = Varanus::Error::StillProcessing
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
raise klass.new(body['code'], body['description'])
|
|
106
|
-
end
|
|
109
|
+
def cert_type_regexp csr
|
|
110
|
+
return /Wildcard.+SSL/i if csr.all_names.any? { |n| n.start_with?('*.') }
|
|
107
111
|
|
|
108
|
-
|
|
109
|
-
@connection ||= Faraday.new(url: 'https://cert-manager.com/api/ssl/v1',
|
|
110
|
-
request: { timeout: 300 }) do |conn|
|
|
111
|
-
conn.request :json
|
|
112
|
-
conn.response :json, content_type: /\bjson$/
|
|
112
|
+
return /Multi.?Domain.+SSL/i if csr.subject_alt_names.any?
|
|
113
113
|
|
|
114
|
-
|
|
115
|
-
conn.headers['password'] = @varanus.password
|
|
116
|
-
conn.headers['customerUri'] = @varanus.customer_uri
|
|
117
|
-
|
|
118
|
-
conn.adapter Faraday.default_adapter
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def get path
|
|
123
|
-
result = connection.get(path)
|
|
124
|
-
check_result result
|
|
125
|
-
result.body
|
|
114
|
+
nil
|
|
126
115
|
end
|
|
127
116
|
|
|
128
117
|
def opts_to_cert_type_id opts, csr
|
|
@@ -132,19 +121,12 @@ class Varanus::SSL
|
|
|
132
121
|
when String
|
|
133
122
|
certificate_types.find { |ct| ct['name'] == opts[:cert_type] }['id']
|
|
134
123
|
else
|
|
135
|
-
certificate_type_from_csr(csr)['id']
|
|
124
|
+
certificate_type_from_csr(csr, opts[:days])['id']
|
|
136
125
|
end
|
|
137
126
|
end
|
|
138
127
|
|
|
139
|
-
def post path, *args
|
|
140
|
-
result = connection.post(path, *args)
|
|
141
|
-
check_result result
|
|
142
|
-
result.body
|
|
143
|
-
end
|
|
144
|
-
|
|
145
128
|
def opts_to_term opts, cert_type_id
|
|
146
129
|
term = opts[:days]
|
|
147
|
-
term ||= opts[:years] * 365 unless opts[:years].nil?
|
|
148
130
|
term ||= certificate_types.find { |ct| ct['id'] == cert_type_id }['terms'].min
|
|
149
131
|
term
|
|
150
132
|
end
|
data/lib/varanus/ssl/csr.rb
CHANGED
|
@@ -25,18 +25,23 @@ class Varanus::SSL::CSR
|
|
|
25
25
|
request = OpenSSL::X509::Request.new
|
|
26
26
|
request.version = 0
|
|
27
27
|
request.subject = OpenSSL::X509::Name.parse subject.map { |k, v| "/#{k}=#{v}" }.join
|
|
28
|
+
request.add_attribute names_to_san_attribute(names)
|
|
29
|
+
request.public_key = key.public_key
|
|
30
|
+
|
|
31
|
+
request.sign(key, OpenSSL::Digest::SHA256.new)
|
|
32
|
+
|
|
33
|
+
[key, Varanus::SSL::CSR.new(request)]
|
|
34
|
+
end
|
|
28
35
|
|
|
29
|
-
|
|
36
|
+
# :nodoc:
|
|
37
|
+
# Create a Subject Alternate Names attribute from an Array of dns names
|
|
38
|
+
def self.names_to_san_attribute names
|
|
30
39
|
ef = OpenSSL::X509::ExtensionFactory.new
|
|
31
40
|
name_str = names.map { |n| "DNS:#{n}" }.join(', ')
|
|
32
41
|
ext = ef.create_extension('subjectAltName', name_str, false)
|
|
33
42
|
seq = OpenSSL::ASN1::Sequence([ext])
|
|
34
43
|
ext_req = OpenSSL::ASN1::Set([seq])
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
request.public_key = key.public_key
|
|
38
|
-
request.sign(key, OpenSSL::Digest::SHA256.new)
|
|
39
|
-
[key, Varanus::SSL::CSR.new(request)]
|
|
44
|
+
OpenSSL::X509::Attribute.new('extReq', ext_req)
|
|
40
45
|
end
|
|
41
46
|
|
|
42
47
|
# Common Name (CN) for cert.
|
|
@@ -82,6 +87,8 @@ class Varanus::SSL::CSR
|
|
|
82
87
|
@request.public_key.n.num_bytes * 8
|
|
83
88
|
when OpenSSL::PKey::DSA
|
|
84
89
|
@request.public_key.p.num_bytes * 8
|
|
90
|
+
when OpenSSL::PKey::EC
|
|
91
|
+
@request.public_key.group.degree
|
|
85
92
|
else
|
|
86
93
|
raise "Unknown public key type: #{@request.public_key.class}"
|
|
87
94
|
end
|
data/lib/varanus/version.rb
CHANGED
data/varanus.gemspec
CHANGED
|
@@ -4,7 +4,6 @@ lib = File.expand_path('lib', __dir__)
|
|
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
require 'varanus/version'
|
|
6
6
|
|
|
7
|
-
# rubocop:disable Metrics/BlockLength
|
|
8
7
|
Gem::Specification.new do |spec|
|
|
9
8
|
spec.name = 'varanus'
|
|
10
9
|
spec.version = Varanus::VERSION
|
|
@@ -28,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
|
28
27
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
29
28
|
end
|
|
30
29
|
spec.require_paths = ['lib']
|
|
31
|
-
spec.required_ruby_version = '>= 2.
|
|
30
|
+
spec.required_ruby_version = '>= 2.5.0'
|
|
32
31
|
|
|
33
32
|
spec.add_development_dependency 'bundler', '~> 1.16'
|
|
34
33
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
|
@@ -44,4 +43,3 @@ Gem::Specification.new do |spec|
|
|
|
44
43
|
spec.add_runtime_dependency 'faraday_middleware'
|
|
45
44
|
spec.add_runtime_dependency 'savon', '~> 2.0'
|
|
46
45
|
end
|
|
47
|
-
# rubocop:enable Metrics/BlockLength
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: varanus
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sean Dilda
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-01-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -204,8 +204,12 @@ files:
|
|
|
204
204
|
- bin/setup
|
|
205
205
|
- docker-compose.yml
|
|
206
206
|
- lib/varanus.rb
|
|
207
|
+
- lib/varanus/dcv.rb
|
|
208
|
+
- lib/varanus/domain.rb
|
|
207
209
|
- lib/varanus/error.rb
|
|
210
|
+
- lib/varanus/organization.rb
|
|
208
211
|
- lib/varanus/reports.rb
|
|
212
|
+
- lib/varanus/rest_resource.rb
|
|
209
213
|
- lib/varanus/ssl.rb
|
|
210
214
|
- lib/varanus/ssl/csr.rb
|
|
211
215
|
- lib/varanus/version.rb
|
|
@@ -222,15 +226,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
222
226
|
requirements:
|
|
223
227
|
- - ">="
|
|
224
228
|
- !ruby/object:Gem::Version
|
|
225
|
-
version: 2.
|
|
229
|
+
version: 2.5.0
|
|
226
230
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
227
231
|
requirements:
|
|
228
232
|
- - ">="
|
|
229
233
|
- !ruby/object:Gem::Version
|
|
230
234
|
version: '0'
|
|
231
235
|
requirements: []
|
|
232
|
-
|
|
233
|
-
rubygems_version: 2.7.8
|
|
236
|
+
rubygems_version: 3.0.3
|
|
234
237
|
signing_key:
|
|
235
238
|
specification_version: 4
|
|
236
239
|
summary: Interface for Sectigo's (formerly Comodo CA) API.
|