varanus 0.1.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.
- checksums.yaml +7 -0
- data/.codeclimate.yml +4 -0
- data/.gitignore +8 -0
- data/.rubocop.yml +70 -0
- data/.travis.yml +19 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +76 -0
- data/LICENSE.txt +21 -0
- data/README.md +71 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/docker-compose.yml +11 -0
- data/lib/varanus/error.rb +13 -0
- data/lib/varanus/ssl/csr.rb +82 -0
- data/lib/varanus/ssl.rb +148 -0
- data/lib/varanus/version.rb +3 -0
- data/lib/varanus.rb +31 -0
- data/varanus.gemspec +44 -0
- metadata +221 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: c3f1e3b8a3c5d8b1999ab00642afaef76bfa69be3872b9af2ab91af9aa4731bc
|
|
4
|
+
data.tar.gz: bf2cd9f9449d290133f6a8f21a5c64fb5541d42c6349b0179eaa85af153bf3e9
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6890038fac5dfa28e212cdb119d16ff35bfa5344359df100076ddd533f5226b3b4c00f8302442d24c27ecdd233d9e23991d37ac3ca6400066ff050f168937d2a
|
|
7
|
+
data.tar.gz: df2e85079624160c161e8d8849c97c0e7287f5e89585dd3a1f9fa2c6fddd100876b72b6fff6e0dc3c028090c7830835c047d8bd22ffbb477c6935ed19d857496
|
data/.codeclimate.yml
ADDED
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 2.3
|
|
3
|
+
|
|
4
|
+
Bundler/OrderedGems:
|
|
5
|
+
AutoCorrect: false
|
|
6
|
+
|
|
7
|
+
Metrics/AbcSize:
|
|
8
|
+
Max: 25
|
|
9
|
+
Exclude:
|
|
10
|
+
- 'test/**/*'
|
|
11
|
+
|
|
12
|
+
Metrics/ClassLength:
|
|
13
|
+
Max: 125
|
|
14
|
+
Exclude:
|
|
15
|
+
- 'test/**/*'
|
|
16
|
+
|
|
17
|
+
Metrics/LineLength:
|
|
18
|
+
Max: 90
|
|
19
|
+
Exclude:
|
|
20
|
+
- 'test/**/*'
|
|
21
|
+
|
|
22
|
+
Metrics/MethodLength:
|
|
23
|
+
Max: 20
|
|
24
|
+
Exclude:
|
|
25
|
+
- 'test/**/*'
|
|
26
|
+
|
|
27
|
+
Naming/FileName:
|
|
28
|
+
Exclude:
|
|
29
|
+
- Gemfile
|
|
30
|
+
|
|
31
|
+
Naming/UncommunicativeMethodParamName:
|
|
32
|
+
AllowedNames:
|
|
33
|
+
- gb
|
|
34
|
+
- id
|
|
35
|
+
- ip
|
|
36
|
+
- os
|
|
37
|
+
- vm
|
|
38
|
+
|
|
39
|
+
Style/ClassAndModuleChildren:
|
|
40
|
+
Enabled: false
|
|
41
|
+
|
|
42
|
+
Style/ConditionalAssignment:
|
|
43
|
+
Enabled: false
|
|
44
|
+
|
|
45
|
+
Style/FrozenStringLiteralComment:
|
|
46
|
+
Enabled: false
|
|
47
|
+
|
|
48
|
+
Style/MethodDefParentheses:
|
|
49
|
+
EnforcedStyle: require_no_parentheses_except_multiline
|
|
50
|
+
|
|
51
|
+
Style/NumericPredicate:
|
|
52
|
+
EnforcedStyle: comparison
|
|
53
|
+
|
|
54
|
+
Style/RescueModifier:
|
|
55
|
+
AutoCorrect: false
|
|
56
|
+
|
|
57
|
+
Style/SymbolArray:
|
|
58
|
+
EnforcedStyle: brackets
|
|
59
|
+
|
|
60
|
+
Style/TrailingCommaInArguments:
|
|
61
|
+
EnforcedStyleForMultiline: no_comma
|
|
62
|
+
|
|
63
|
+
Style/TrailingCommaInArrayLiteral:
|
|
64
|
+
EnforcedStyleForMultiline: no_comma
|
|
65
|
+
|
|
66
|
+
Style/TrailingCommaInHashLiteral:
|
|
67
|
+
EnforcedStyleForMultiline: no_comma
|
|
68
|
+
|
|
69
|
+
Style/WordArray:
|
|
70
|
+
EnforcedStyle: brackets
|
data/.travis.yml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
env:
|
|
3
|
+
global:
|
|
4
|
+
- CC_TEST_REPORTER_ID=11ec0aee76479858801566bb43fd7d76eced4cbb2432bcead71db59dae21eaae
|
|
5
|
+
sudo: false
|
|
6
|
+
language: ruby
|
|
7
|
+
cache: bundler
|
|
8
|
+
rvm:
|
|
9
|
+
- 2.3
|
|
10
|
+
- 2.4
|
|
11
|
+
- 2.5
|
|
12
|
+
- 2.6
|
|
13
|
+
before_install: gem install bundler -v 1.16.5
|
|
14
|
+
before_script:
|
|
15
|
+
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
|
|
16
|
+
- chmod +x ./cc-test-reporter
|
|
17
|
+
- ./cc-test-reporter before-build
|
|
18
|
+
after_script:
|
|
19
|
+
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
varanus (0.1.0)
|
|
5
|
+
faraday
|
|
6
|
+
faraday_middleware
|
|
7
|
+
|
|
8
|
+
GEM
|
|
9
|
+
remote: https://rubygems.org/
|
|
10
|
+
specs:
|
|
11
|
+
addressable (2.5.2)
|
|
12
|
+
public_suffix (>= 2.0.2, < 4.0)
|
|
13
|
+
ast (2.4.0)
|
|
14
|
+
crack (0.4.3)
|
|
15
|
+
safe_yaml (~> 1.0.0)
|
|
16
|
+
docile (1.3.1)
|
|
17
|
+
faraday (0.15.3)
|
|
18
|
+
multipart-post (>= 1.2, < 3)
|
|
19
|
+
faraday_middleware (0.12.2)
|
|
20
|
+
faraday (>= 0.7.4, < 1.0)
|
|
21
|
+
hashdiff (0.3.7)
|
|
22
|
+
jaro_winkler (1.5.1)
|
|
23
|
+
json (2.1.0)
|
|
24
|
+
metaclass (0.0.4)
|
|
25
|
+
minitest (5.11.3)
|
|
26
|
+
minitest-rg (5.2.0)
|
|
27
|
+
minitest (~> 5.0)
|
|
28
|
+
mocha (1.7.0)
|
|
29
|
+
metaclass (~> 0.0.1)
|
|
30
|
+
multipart-post (2.0.0)
|
|
31
|
+
parallel (1.12.1)
|
|
32
|
+
parser (2.5.3.0)
|
|
33
|
+
ast (~> 2.4.0)
|
|
34
|
+
powerpack (0.1.2)
|
|
35
|
+
public_suffix (3.0.3)
|
|
36
|
+
rainbow (3.0.0)
|
|
37
|
+
rake (10.5.0)
|
|
38
|
+
rubocop (0.60.0)
|
|
39
|
+
jaro_winkler (~> 1.5.1)
|
|
40
|
+
parallel (~> 1.10)
|
|
41
|
+
parser (>= 2.5, != 2.5.1.1)
|
|
42
|
+
powerpack (~> 0.1)
|
|
43
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
44
|
+
ruby-progressbar (~> 1.7)
|
|
45
|
+
unicode-display_width (~> 1.4.0)
|
|
46
|
+
ruby-progressbar (1.10.0)
|
|
47
|
+
safe_yaml (1.0.4)
|
|
48
|
+
simplecov (0.16.1)
|
|
49
|
+
docile (~> 1.1)
|
|
50
|
+
json (>= 1.8, < 3)
|
|
51
|
+
simplecov-html (~> 0.10.0)
|
|
52
|
+
simplecov-html (0.10.2)
|
|
53
|
+
unicode-display_width (1.4.0)
|
|
54
|
+
webmock (3.4.2)
|
|
55
|
+
addressable (>= 2.3.6)
|
|
56
|
+
crack (>= 0.3.2)
|
|
57
|
+
hashdiff
|
|
58
|
+
yard (0.9.16)
|
|
59
|
+
|
|
60
|
+
PLATFORMS
|
|
61
|
+
ruby
|
|
62
|
+
|
|
63
|
+
DEPENDENCIES
|
|
64
|
+
bundler (~> 1.16)
|
|
65
|
+
minitest (~> 5.0)
|
|
66
|
+
minitest-rg
|
|
67
|
+
mocha
|
|
68
|
+
rake (~> 10.0)
|
|
69
|
+
rubocop
|
|
70
|
+
simplecov
|
|
71
|
+
varanus!
|
|
72
|
+
webmock
|
|
73
|
+
yard
|
|
74
|
+
|
|
75
|
+
BUNDLED WITH
|
|
76
|
+
1.17.1
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 Duke University
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Varanus
|
|
2
|
+
|
|
3
|
+
This gem provides an interface to Sectigo's (formerly Comodo CA) APIs for working
|
|
4
|
+
with SSL/TLS certificates as well as its reporting API.
|
|
5
|
+
|
|
6
|
+
Support for Sectigo's other APIs (S/MIME, code signing, device certificates, etc) may
|
|
7
|
+
be added at a later date. Merge requests to add some of this functionality would be
|
|
8
|
+
greatly appreciated.
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
Add this line to your application's Gemfile:
|
|
13
|
+
|
|
14
|
+
```ruby
|
|
15
|
+
gem 'varanus'
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
And then execute:
|
|
19
|
+
|
|
20
|
+
$ bundle
|
|
21
|
+
|
|
22
|
+
Or install it yourself as:
|
|
23
|
+
|
|
24
|
+
$ gem install varanus
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
#### Sign SSL cert from CSR
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
csr = File.read('/path/to/file.csr')
|
|
32
|
+
varanus = Varanus.new(customer_uri, username, password)
|
|
33
|
+
id = varanus.ssl.sign csr, org_id
|
|
34
|
+
begin
|
|
35
|
+
cert = varanus.ssl.collect id
|
|
36
|
+
rescue Varanus::Error::StillProcessing
|
|
37
|
+
sleep 1
|
|
38
|
+
retry
|
|
39
|
+
end
|
|
40
|
+
puts cert
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
#### Revoke SSL cert
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
Varanus.new(customer_uri, username, password).ssl.revoke(id)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
#### Authentication
|
|
50
|
+
|
|
51
|
+
Authentication requires the same credentials you use to login to cert-manager.com as well as the ```customer_uri```. If your URL to log into cert-manager.com is https://cert-manager.com/customer/MyCompany then your ```customer_uri``` will be ```'MyCompany'```
|
|
52
|
+
|
|
53
|
+
#### Finding Organization Id (org_id)
|
|
54
|
+
|
|
55
|
+
Signing a cert requires specifying an ```org_id```. Each department in cert-manager.com has an associated ```org_id```.
|
|
56
|
+
|
|
57
|
+
To find the ```org_id```, log into cert-manager.com, go to **Settings** -> **Departments**, then click to edit the department you are interested in. The value you want is in the **OrgID** field.
|
|
58
|
+
|
|
59
|
+
## Development
|
|
60
|
+
|
|
61
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
62
|
+
|
|
63
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
64
|
+
|
|
65
|
+
## Contributing
|
|
66
|
+
|
|
67
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/duke-automation/varanus.
|
|
68
|
+
|
|
69
|
+
## License
|
|
70
|
+
|
|
71
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'varanus'
|
|
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/bin/setup
ADDED
data/docker-compose.yml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Error returned from the Sectigo API
|
|
2
|
+
class Varanus::Error < StandardError
|
|
3
|
+
# @return [Integer] Code associated with error
|
|
4
|
+
attr_reader :code
|
|
5
|
+
|
|
6
|
+
def initialize code, msg
|
|
7
|
+
@code = code
|
|
8
|
+
super(msg)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Certificate is still being signed.
|
|
13
|
+
class Varanus::Error::StillProcessing < Varanus::Error; end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Wrapper class around a OpenSSL::X509::Request
|
|
2
|
+
# Provides helper functions to make reading information from the CSR easier
|
|
3
|
+
class Varanus::SSL::CSR
|
|
4
|
+
# Common Name (CN) for cert.
|
|
5
|
+
# @return [String]
|
|
6
|
+
attr_reader :cn
|
|
7
|
+
|
|
8
|
+
# @param csr [String, OpenSSL::X509::Request]
|
|
9
|
+
def initialize csr
|
|
10
|
+
if csr.is_a? OpenSSL::X509::Request
|
|
11
|
+
@req = csr
|
|
12
|
+
@text = csr.to_s
|
|
13
|
+
else
|
|
14
|
+
@text = csr.to_s
|
|
15
|
+
@req = OpenSSL::X509::Request.new @text
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
raise 'Improperly signed CSR' unless @req.verify @req.public_key
|
|
19
|
+
|
|
20
|
+
cn_ref = @req.subject.to_a.find { |a| a[0] == 'CN' }
|
|
21
|
+
@cn = cn_ref && cn_ref[1].downcase
|
|
22
|
+
|
|
23
|
+
_parse_sans
|
|
24
|
+
|
|
25
|
+
# If we have no CN or SAN, raise an error
|
|
26
|
+
raise 'CSR must have a CN and/or subjectAltName' if @cn.nil? && @sans.empty?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Unique list of all DNS names for cert (CN and subject alt names)
|
|
30
|
+
# @return [Array<String>]
|
|
31
|
+
def all_names
|
|
32
|
+
([@cn] + @sans).compact.uniq
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Key size for the cert
|
|
36
|
+
# @return [Integer]
|
|
37
|
+
def key_size
|
|
38
|
+
case @req.public_key
|
|
39
|
+
when OpenSSL::PKey::RSA
|
|
40
|
+
@req.public_key.n.num_bytes * 8
|
|
41
|
+
when OpenSSL::PKey::DSA
|
|
42
|
+
@req.public_key.p.num_bytes * 8
|
|
43
|
+
else
|
|
44
|
+
raise "Unknown public key type: #{@req.public_key.class}"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# PEM format for cert
|
|
49
|
+
def to_s
|
|
50
|
+
@text
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# DNS subject alt names
|
|
54
|
+
# @return [Array<String>]
|
|
55
|
+
def subject_alt_names
|
|
56
|
+
@sans
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def _parse_sans
|
|
62
|
+
extensions = @req.attributes.select { |at| at.oid == 'extReq' }
|
|
63
|
+
sans_extensions = extensions.flat_map do |extension|
|
|
64
|
+
extension.value.value[0].value
|
|
65
|
+
.select { |ext| ext.first.value == 'subjectAltName' }
|
|
66
|
+
.map { |ext| ext.value.last }
|
|
67
|
+
end
|
|
68
|
+
@sans = sans_extensions.compact.flat_map do |san|
|
|
69
|
+
_parse_sans_extension san
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def _parse_sans_extension ext
|
|
74
|
+
OpenSSL::ASN1.decode(ext.value).map do |s_entry|
|
|
75
|
+
unless s_entry.tag == 2 && s_entry.tag_class == :CONTEXT_SPECIFIC
|
|
76
|
+
raise "unknown tag #{s_entry.tag}"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
s_entry.value.downcase
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
data/lib/varanus/ssl.rb
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# An connection to the SSL/TSL API. This should not be initialized directly. Instead,
|
|
2
|
+
# use Varanus#ssl
|
|
3
|
+
class Varanus::SSL
|
|
4
|
+
# @note Do not call this directly. Use {Varanus#ssl} to initialize
|
|
5
|
+
def initialize varanus
|
|
6
|
+
@varanus = varanus
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Returns the option from #certificate_types that best matches the csr.
|
|
10
|
+
# @param csr [Varanus::SSL::CSR]
|
|
11
|
+
# @return [Hash] The option from {#certificate_types} that best matches the csr
|
|
12
|
+
def certificate_type_from_csr csr
|
|
13
|
+
# first exclude certificate types we don't want
|
|
14
|
+
types = certificate_types.reject do |ct|
|
|
15
|
+
ct['name'] =~ /\b(?:EV|ECC|AMT|Elite)\b/
|
|
16
|
+
end
|
|
17
|
+
if csr.all_names.any? { |n| n.start_with?('*.') }
|
|
18
|
+
types.find { |ct| ct['name'] =~ /Wildcard.+SSL/i }
|
|
19
|
+
elsif csr.subject_alt_names.any?
|
|
20
|
+
types.find { |ct| ct['name'] =~ /Multi.?Domain.+SSL/i }
|
|
21
|
+
else
|
|
22
|
+
types.find do |ct|
|
|
23
|
+
ct['name'] =~ /\bSSL\b/ && ct['name'] !~ /(?:Multi.?Domain|Wildcard)/i
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Certificate types that can be used to sign a cert
|
|
29
|
+
# @return [Array<Hash>]
|
|
30
|
+
def certificate_types
|
|
31
|
+
@certificate_types ||= get('types')
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Retrieves the cert.
|
|
35
|
+
# @param id [Integer] As returned by {#sign}
|
|
36
|
+
# @param type [String]
|
|
37
|
+
#
|
|
38
|
+
# +type+ can be one of:
|
|
39
|
+
# 'x509' - X509 format - cert and chain (default)
|
|
40
|
+
# 'x509CO' - X509 format - cert only
|
|
41
|
+
# 'x509IO' - X509 format - intermediates/root only
|
|
42
|
+
# 'x590IOR' - X509 format - intermediates/root only reversed
|
|
43
|
+
# 'base64' - PKCS#7 base64 encoded
|
|
44
|
+
# 'bin' - PKCS#7 bin encoded
|
|
45
|
+
#
|
|
46
|
+
# @raise [Varanus::Error::StillProcessing] Cert is still being signed
|
|
47
|
+
# @return [String] Certificate
|
|
48
|
+
def collect id, type = 'x509'
|
|
49
|
+
get("collect/#{id}/#{type}")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Revoke an ssl cert
|
|
53
|
+
# @param id [Integer] As returned by {#sign}
|
|
54
|
+
# @param reason [String] Reason for revoking. Sectigo's API will return an error if it
|
|
55
|
+
# is blank.
|
|
56
|
+
def revoke id, reason
|
|
57
|
+
post("revoke/#{id}", reason: reason)
|
|
58
|
+
nil
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Sign an SSL cert. Returns the id of the SSL cert
|
|
62
|
+
# @param csr [Varanus::SSL::CSR, OpenSSL::X509::Request, String] CSR to sign
|
|
63
|
+
# @param org_id [Integer] your organization id on cert-manager.com
|
|
64
|
+
# @param opts [Hash]
|
|
65
|
+
# @option opts [String] :comments ('') Limited to 1,024 characters
|
|
66
|
+
# @option opts [String] :external_requester ('') email address associated with cert on
|
|
67
|
+
# cert-manager.com - limited to 512 characters
|
|
68
|
+
# @option opts [String, Integer] :cert_type name(String) or id(Integer) of the cert
|
|
69
|
+
# type to use. If none is specified, Varanus will attempt to find one
|
|
70
|
+
# @option opts [Integer] :years number of years cert should be valid for (this number
|
|
71
|
+
# is multiplied by 365 and used as days)
|
|
72
|
+
# @option opts [Integer] :days number of days cert should be valid for (if none is
|
|
73
|
+
# specified, lowest allowed for the cert type will be used)
|
|
74
|
+
# @return [Integer] Id of SSL cert.
|
|
75
|
+
def sign csr, org_id, opts = {}
|
|
76
|
+
csr = Varanus::SSL::CSR.new(csr) unless csr.is_a?(Varanus::SSL::CSR)
|
|
77
|
+
cert_type_id = opts_to_cert_type_id opts, csr
|
|
78
|
+
args = {
|
|
79
|
+
orgId: org_id,
|
|
80
|
+
csr: csr.to_s,
|
|
81
|
+
subjAltNames: csr.subject_alt_names.join(','),
|
|
82
|
+
certType: cert_type_id,
|
|
83
|
+
term: opts_to_term(opts, cert_type_id),
|
|
84
|
+
serverType: -1,
|
|
85
|
+
comments: opts[:comments].to_s[0, 1024],
|
|
86
|
+
externalRequester: opts[:external_requester].to_s[0, 512]
|
|
87
|
+
}
|
|
88
|
+
post('enroll', args)['sslId']
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
private
|
|
92
|
+
|
|
93
|
+
def check_result result
|
|
94
|
+
body = result.body
|
|
95
|
+
return unless body.is_a?(Hash)
|
|
96
|
+
return if body['code'].nil?
|
|
97
|
+
|
|
98
|
+
klass = Varanus::Error
|
|
99
|
+
if body['code'] == 0 && body['description'] =~ /process/
|
|
100
|
+
klass = Varanus::Error::StillProcessing
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
raise klass.new(body['code'], body['description'])
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def connection
|
|
107
|
+
@connection ||= Faraday.new(url: 'https://cert-manager.com/api/ssl/v1') do |conn|
|
|
108
|
+
conn.request :json
|
|
109
|
+
conn.response :json, content_type: /\bjson$/
|
|
110
|
+
|
|
111
|
+
conn.headers['login'] = @varanus.username
|
|
112
|
+
conn.headers['password'] = @varanus.password
|
|
113
|
+
conn.headers['customerUri'] = @varanus.customer_uri
|
|
114
|
+
|
|
115
|
+
conn.adapter Faraday.default_adapter
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def get path
|
|
120
|
+
result = connection.get(path)
|
|
121
|
+
check_result result
|
|
122
|
+
result.body
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def opts_to_cert_type_id opts, csr
|
|
126
|
+
case opts[:cert_type]
|
|
127
|
+
when Integer
|
|
128
|
+
opts[:cert_type]
|
|
129
|
+
when String
|
|
130
|
+
certificate_types.find { |ct| ct['name'] == opts[:cert_type] }['id']
|
|
131
|
+
else
|
|
132
|
+
certificate_type_from_csr(csr)['id']
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def post path, *args
|
|
137
|
+
result = connection.post(path, *args)
|
|
138
|
+
check_result result
|
|
139
|
+
result.body
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def opts_to_term opts, cert_type_id
|
|
143
|
+
term = opts[:days]
|
|
144
|
+
term ||= opts[:years] * 365 unless opts[:years].nil?
|
|
145
|
+
term ||= certificate_types.find { |ct| ct['id'] == cert_type_id }['terms'].min
|
|
146
|
+
term
|
|
147
|
+
end
|
|
148
|
+
end
|
data/lib/varanus.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Interface for Sectigo's (formerly Comodo CA) API.
|
|
2
|
+
class Varanus
|
|
3
|
+
attr_reader :customer_uri, :username, :password
|
|
4
|
+
|
|
5
|
+
# @param customer_uri [String]
|
|
6
|
+
# (see {file:README.md#label-Finding+Organization+Id+-28org_id-29})
|
|
7
|
+
# @param username [String]
|
|
8
|
+
# @param password [String]
|
|
9
|
+
def initialize customer_uri, username, password
|
|
10
|
+
@customer_uri = customer_uri
|
|
11
|
+
@username = username
|
|
12
|
+
@password = password
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Retrive SSL instance
|
|
16
|
+
# @return [Varanus::SSL]
|
|
17
|
+
def ssl
|
|
18
|
+
@ssl ||= SSL.new(self)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# stdlib/gem requires
|
|
23
|
+
require 'faraday'
|
|
24
|
+
require 'faraday_middleware'
|
|
25
|
+
require 'openssl'
|
|
26
|
+
|
|
27
|
+
# Require other files in this gem
|
|
28
|
+
require 'varanus/error'
|
|
29
|
+
require 'varanus/ssl'
|
|
30
|
+
require 'varanus/ssl/csr'
|
|
31
|
+
require 'varanus/version'
|
data/varanus.gemspec
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
+
require 'varanus/version'
|
|
4
|
+
|
|
5
|
+
# rubocop:disable Metrics/BlockLength
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = 'varanus'
|
|
8
|
+
spec.version = Varanus::VERSION
|
|
9
|
+
spec.authors = ['Sean Dilda']
|
|
10
|
+
spec.email = ['sean@duke.edu']
|
|
11
|
+
|
|
12
|
+
spec.summary = "Interface for Sectigo's (formerly Comodo CA) API."
|
|
13
|
+
spec.description = <<~DESCRIPTION
|
|
14
|
+
This gem provides an interface to Sectigo's (formerly Comodo CA) APIs for working
|
|
15
|
+
with SSL/TLS certificates as well as its reporting API.
|
|
16
|
+
|
|
17
|
+
Support for Sectigo's other APIs (S/MIME, code signing, device certificates, etc) may
|
|
18
|
+
be added at a later date.
|
|
19
|
+
DESCRIPTION
|
|
20
|
+
spec.homepage = 'https://github.com/duke-automation/varanus'
|
|
21
|
+
spec.license = 'MIT'
|
|
22
|
+
|
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
25
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
26
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
27
|
+
end
|
|
28
|
+
spec.require_paths = ['lib']
|
|
29
|
+
spec.required_ruby_version = '>= 2.3.0'
|
|
30
|
+
|
|
31
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
|
32
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
|
33
|
+
spec.add_development_dependency 'minitest-rg'
|
|
34
|
+
spec.add_development_dependency 'mocha'
|
|
35
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
|
36
|
+
spec.add_development_dependency 'rubocop'
|
|
37
|
+
spec.add_development_dependency 'simplecov'
|
|
38
|
+
spec.add_development_dependency 'webmock'
|
|
39
|
+
spec.add_development_dependency 'yard'
|
|
40
|
+
|
|
41
|
+
spec.add_runtime_dependency 'faraday'
|
|
42
|
+
spec.add_runtime_dependency 'faraday_middleware'
|
|
43
|
+
end
|
|
44
|
+
# rubocop:enable Metrics/BlockLength
|
metadata
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: varanus
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Sean Dilda
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2018-11-07 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: bundler
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.16'
|
|
20
|
+
type: :development
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.16'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: minitest
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '5.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '5.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: minitest-rg
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: mocha
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rake
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '10.0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '10.0'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rubocop
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '0'
|
|
90
|
+
type: :development
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: simplecov
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: webmock
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - ">="
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: yard
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - ">="
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '0'
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - ">="
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '0'
|
|
139
|
+
- !ruby/object:Gem::Dependency
|
|
140
|
+
name: faraday
|
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - ">="
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '0'
|
|
146
|
+
type: :runtime
|
|
147
|
+
prerelease: false
|
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
+
requirements:
|
|
150
|
+
- - ">="
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: '0'
|
|
153
|
+
- !ruby/object:Gem::Dependency
|
|
154
|
+
name: faraday_middleware
|
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
|
156
|
+
requirements:
|
|
157
|
+
- - ">="
|
|
158
|
+
- !ruby/object:Gem::Version
|
|
159
|
+
version: '0'
|
|
160
|
+
type: :runtime
|
|
161
|
+
prerelease: false
|
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
163
|
+
requirements:
|
|
164
|
+
- - ">="
|
|
165
|
+
- !ruby/object:Gem::Version
|
|
166
|
+
version: '0'
|
|
167
|
+
description: |
|
|
168
|
+
This gem provides an interface to Sectigo's (formerly Comodo CA) APIs for working
|
|
169
|
+
with SSL/TLS certificates as well as its reporting API.
|
|
170
|
+
|
|
171
|
+
Support for Sectigo's other APIs (S/MIME, code signing, device certificates, etc) may
|
|
172
|
+
be added at a later date.
|
|
173
|
+
email:
|
|
174
|
+
- sean@duke.edu
|
|
175
|
+
executables: []
|
|
176
|
+
extensions: []
|
|
177
|
+
extra_rdoc_files: []
|
|
178
|
+
files:
|
|
179
|
+
- ".codeclimate.yml"
|
|
180
|
+
- ".gitignore"
|
|
181
|
+
- ".rubocop.yml"
|
|
182
|
+
- ".travis.yml"
|
|
183
|
+
- Gemfile
|
|
184
|
+
- Gemfile.lock
|
|
185
|
+
- LICENSE.txt
|
|
186
|
+
- README.md
|
|
187
|
+
- Rakefile
|
|
188
|
+
- bin/console
|
|
189
|
+
- bin/setup
|
|
190
|
+
- docker-compose.yml
|
|
191
|
+
- lib/varanus.rb
|
|
192
|
+
- lib/varanus/error.rb
|
|
193
|
+
- lib/varanus/ssl.rb
|
|
194
|
+
- lib/varanus/ssl/csr.rb
|
|
195
|
+
- lib/varanus/version.rb
|
|
196
|
+
- varanus.gemspec
|
|
197
|
+
homepage: https://github.com/duke-automation/varanus
|
|
198
|
+
licenses:
|
|
199
|
+
- MIT
|
|
200
|
+
metadata: {}
|
|
201
|
+
post_install_message:
|
|
202
|
+
rdoc_options: []
|
|
203
|
+
require_paths:
|
|
204
|
+
- lib
|
|
205
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
206
|
+
requirements:
|
|
207
|
+
- - ">="
|
|
208
|
+
- !ruby/object:Gem::Version
|
|
209
|
+
version: 2.3.0
|
|
210
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
211
|
+
requirements:
|
|
212
|
+
- - ">="
|
|
213
|
+
- !ruby/object:Gem::Version
|
|
214
|
+
version: '0'
|
|
215
|
+
requirements: []
|
|
216
|
+
rubyforge_project:
|
|
217
|
+
rubygems_version: 2.7.8
|
|
218
|
+
signing_key:
|
|
219
|
+
specification_version: 4
|
|
220
|
+
summary: Interface for Sectigo's (formerly Comodo CA) API.
|
|
221
|
+
test_files: []
|