varanus 0.7.1 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 271baf219a1247e588a20aba506a76e26668bad6c6ab55546f75fa697d04e3ff
4
- data.tar.gz: 00c5bc35eeb4b56fdc94b18d969c7ac498ffc87a948db20fdc989fc4e90cf8d6
3
+ metadata.gz: 9c5717bc294e05caa49007dbf36c638ecf3a1d3e192aee421e51a73fec58246c
4
+ data.tar.gz: 54f6feea0b5b692d415dd2f9d5eff9d0d088f29e26d54a700467494f11904048
5
5
  SHA512:
6
- metadata.gz: 70898c1f830700b0a2865656143c452dfeae4b9846e9c1b4730c5cd359d2c4f786e167758581d2028fc2c60588480382066cecc932d03b7355accb84ff21a0c3
7
- data.tar.gz: de4d6791505e36cbaa157a0004e2405b90f1067c0953a892a0efb6fc622b671744779603620b3c142413043e4063cbd411cf2629acb3256a7fccc308e8be93ee
6
+ metadata.gz: 246eeabfd08d59b01f5b8e6cca4d5ec8b4c7a73223ee34d8ac86a1d459d286fdf965ed410a381b2312ab72e97f3c0b65dc0da77c8b31776e53253f10b9003a05
7
+ data.tar.gz: cdf0e60e8894b50e55f81901f0d441a7a3edf376856de12ea4a0bfc845267c3026926dcafabec14e7aebaf1292a25e6c8c0e76cbdfd9f346a9b18a3828021543
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.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Dilda
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-31 00:00:00.000000000 Z
11
+ date: 2024-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.16'
19
+ version: '2.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.16'
26
+ version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -189,36 +189,12 @@ email:
189
189
  executables: []
190
190
  extensions: []
191
191
  extra_rdoc_files: []
192
- files:
193
- - ".codeclimate.yml"
194
- - ".gitignore"
195
- - ".rubocop.yml"
196
- - ".travis.yml"
197
- - CHANGELOG.md
198
- - Gemfile
199
- - Gemfile.lock
200
- - LICENSE.txt
201
- - README.md
202
- - Rakefile
203
- - bin/console
204
- - bin/setup
205
- - docker-compose.yml
206
- - lib/varanus.rb
207
- - lib/varanus/dcv.rb
208
- - lib/varanus/domain.rb
209
- - lib/varanus/error.rb
210
- - lib/varanus/organization.rb
211
- - lib/varanus/reports.rb
212
- - lib/varanus/rest_resource.rb
213
- - lib/varanus/ssl.rb
214
- - lib/varanus/ssl/csr.rb
215
- - lib/varanus/version.rb
216
- - varanus.gemspec
192
+ files: []
217
193
  homepage: https://github.com/duke-automation/varanus
218
194
  licenses:
219
195
  - MIT
220
196
  metadata: {}
221
- post_install_message:
197
+ post_install_message:
222
198
  rdoc_options: []
223
199
  require_paths:
224
200
  - lib
@@ -233,8 +209,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
233
209
  - !ruby/object:Gem::Version
234
210
  version: '0'
235
211
  requirements: []
236
- rubygems_version: 3.0.3
237
- signing_key:
212
+ rubygems_version: 3.3.27
213
+ signing_key:
238
214
  specification_version: 4
239
215
  summary: Interface for Sectigo's (formerly Comodo CA) API.
240
216
  test_files: []
data/.codeclimate.yml DELETED
@@ -1,4 +0,0 @@
1
- plugins:
2
- rubocop:
3
- enabled: true
4
- channel: rubocop-0-59
data/.gitignore DELETED
@@ -1,9 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /_yardoc/
4
- /coverage/
5
- /doc/
6
- /pkg/
7
- /spec/reports/
8
- /tmp/
9
- /test.rb
data/.rubocop.yml DELETED
@@ -1,51 +0,0 @@
1
- AllCops:
2
- NewCops: disable
3
- TargetRubyVersion: 2.5
4
-
5
- Bundler/OrderedGems:
6
- AutoCorrect: false
7
-
8
- Layout/LineLength:
9
- Max: 90
10
- Exclude:
11
- - 'test/**/*'
12
-
13
- Metrics/AbcSize:
14
- Max: 25
15
- Exclude:
16
- - 'test/**/*'
17
-
18
- Metrics/ClassLength:
19
- Max: 125
20
- Exclude:
21
- - 'test/**/*'
22
-
23
- Metrics/MethodLength:
24
- Max: 20
25
- Exclude:
26
- - 'test/**/*'
27
-
28
- Naming/FileName:
29
- Exclude:
30
- - Gemfile
31
-
32
- Style/ClassAndModuleChildren:
33
- EnforcedStyle: compact
34
-
35
- Style/ConditionalAssignment:
36
- Enabled: false
37
-
38
- Style/MethodDefParentheses:
39
- EnforcedStyle: require_no_parentheses_except_multiline
40
-
41
- Style/NumericPredicate:
42
- EnforcedStyle: comparison
43
-
44
- Style/RescueModifier:
45
- AutoCorrect: false
46
-
47
- Style/SymbolArray:
48
- EnforcedStyle: brackets
49
-
50
- Style/WordArray:
51
- EnforcedStyle: brackets
data/.travis.yml DELETED
@@ -1,18 +0,0 @@
1
- ---
2
- env:
3
- global:
4
- - CC_TEST_REPORTER_ID=11ec0aee76479858801566bb43fd7d76eced4cbb2432bcead71db59dae21eaae
5
- sudo: false
6
- language: ruby
7
- cache: bundler
8
- rvm:
9
- - 2.5
10
- - 2.6
11
- - 2.7
12
- before_install: gem install bundler -v 1.16.5
13
- before_script:
14
- - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
15
- - chmod +x ./cc-test-reporter
16
- - ./cc-test-reporter before-build
17
- after_script:
18
- - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
data/CHANGELOG.md DELETED
@@ -1,38 +0,0 @@
1
- ### Version 0.7.1 (2022-01-31)
2
- * Varanus::SSL#certificate_types_standard - also exclude 'Extended Validation'
3
-
4
- ### Version 0.7.0 (2020-02-03)
5
- * Add Varanus::Domain#report
6
-
7
- ### Version 0.6.0 (2020-02-01)
8
- * Add Varanus::SSL#report
9
- * Varanus::Reports (Varanus#reports) is now deprecated.
10
-
11
- ### Version 0.5.1 (2021-01-28)
12
- * Varanus::SSL::CSR - support EC certs
13
-
14
- ### Version 0.5.0 (2021-01-26)
15
- * Add Varanus::Domain
16
- * Add Varanus::SSL#list and Varanus::SSL#info
17
- * Add Varanus::Organization
18
-
19
- ### 0.4.0 (2021-01-06)
20
- * Add Varanus::DCV
21
-
22
- ### 0.3.1 (2020-10-14)
23
- * Fix issue when Sectigo reports two identical 'Short Life' certs
24
-
25
- ### 0.3.0 (2020-08-24)
26
- * Add support for new 'Short Life' certs
27
-
28
- ### 0.2.1 (2018-11-13)
29
- * Increase timeout value for SSL requests
30
-
31
- ### 0.2.0 (2018-11-09)
32
- * Added Varanus::SSL::CSR.generate
33
- * Added Reports
34
- * Varanus::Reports#ssl - list of SSL/TLS certs
35
- * Varanus::Reports#domains - list of domains validated with DCV
36
-
37
- ### 0.1.0 (2018-11-07)
38
- * Initial release
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source 'https://rubygems.org'
4
-
5
- git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
-
7
- # Specify your gem's dependencies in varanus.gemspec
8
- gemspec
data/Gemfile.lock DELETED
@@ -1,108 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- varanus (0.7.1)
5
- faraday
6
- faraday_middleware
7
- savon (~> 2.0)
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
- addressable (2.7.0)
13
- public_suffix (>= 2.0.2, < 5.0)
14
- akami (1.3.1)
15
- gyoku (>= 0.4.0)
16
- nokogiri
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)
24
- multipart-post (>= 1.2, < 3)
25
- ruby2_keywords
26
- faraday-net_http (1.0.0)
27
- faraday_middleware (1.0.0)
28
- faraday (~> 1.0)
29
- gyoku (1.3.1)
30
- builder (>= 2.1.2)
31
- hashdiff (1.0.1)
32
- httpi (2.4.5)
33
- rack
34
- socksify
35
- minitest (5.14.3)
36
- minitest-rg (5.2.0)
37
- minitest (~> 5.0)
38
- mocha (1.12.0)
39
- multipart-post (2.1.1)
40
- nokogiri (1.11.1-x86_64-linux)
41
- racc (~> 1.4)
42
- nori (2.6.0)
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)
49
- rainbow (3.0.0)
50
- rake (10.5.0)
51
- regexp_parser (2.0.3)
52
- rexml (3.2.4)
53
- rubocop (1.7.0)
54
- parallel (~> 1.10)
55
- parser (>= 2.7.1.5)
56
- rainbow (>= 2.2.2, < 4.0)
57
- regexp_parser (>= 1.8, < 3.0)
58
- rexml
59
- rubocop-ast (>= 1.2.0, < 2.0)
60
- ruby-progressbar (~> 1.7)
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)
67
- akami (~> 1.2)
68
- builder (>= 2.1.2)
69
- gyoku (~> 1.2)
70
- httpi (~> 2.3)
71
- nokogiri (>= 1.8.1)
72
- nori (~> 2.4)
73
- wasabi (~> 3.4)
74
- simplecov (0.21.1)
75
- docile (~> 1.1)
76
- simplecov-html (~> 0.11)
77
- simplecov_json_formatter (~> 0.1)
78
- simplecov-html (0.12.3)
79
- simplecov_json_formatter (0.1.2)
80
- socksify (1.7.1)
81
- unicode-display_width (1.7.0)
82
- wasabi (3.6.1)
83
- addressable
84
- httpi (~> 2.0)
85
- nokogiri (>= 1.4.2)
86
- webmock (3.11.0)
87
- addressable (>= 2.3.6)
88
- crack (>= 0.3.2)
89
- hashdiff (>= 0.4.0, < 2.0.0)
90
- yard (0.9.26)
91
-
92
- PLATFORMS
93
- ruby
94
-
95
- DEPENDENCIES
96
- bundler (~> 1.16)
97
- minitest (~> 5.0)
98
- minitest-rg
99
- mocha
100
- rake (~> 10.0)
101
- rubocop
102
- simplecov
103
- varanus!
104
- webmock
105
- yard
106
-
107
- BUNDLED WITH
108
- 1.17.3
data/LICENSE.txt DELETED
@@ -1,21 +0,0 @@
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 DELETED
@@ -1,104 +0,0 @@
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
- [![Build Status](https://travis-ci.org/duke-automation/varanus.svg?branch=master)](https://travis-ci.org/duke-automation/varanus)
11
- [![Gem Version](https://badge.fury.io/rb/varanus.svg)](http://badge.fury.io/rb/varanus)
12
- [![Maintainability](https://api.codeclimate.com/v1/badges/593ef1aa2ba757b5374f/maintainability)](https://codeclimate.com/github/duke-automation/varanus/maintainability)
13
- [![Test Coverage](https://api.codeclimate.com/v1/badges/593ef1aa2ba757b5374f/test_coverage)](https://codeclimate.com/github/duke-automation/varanus/test_coverage)
14
-
15
- ## Usage
16
-
17
- #### Generate and sign SSL cert
18
-
19
- ```ruby
20
- key, csr = Varanus::SSL::CSR.generate(['example.com'])
21
- varanus = Varanus.new(customer_uri, username, password)
22
- id = varanus.ssl.sign csr, org_id
23
- begin
24
- cert = varanus.ssl.collect id
25
- rescue Varanus::Error::StillProcessing
26
- sleep 1
27
- retry
28
- end
29
- puts key
30
- puts cert
31
- ```
32
-
33
- #### Sign SSL cert from CSR
34
-
35
- ```ruby
36
- csr = File.read('/path/to/file.csr')
37
- varanus = Varanus.new(customer_uri, username, password)
38
- id = varanus.ssl.sign csr, org_id
39
- begin
40
- cert = varanus.ssl.collect id
41
- rescue Varanus::Error::StillProcessing
42
- sleep 1
43
- retry
44
- end
45
- puts cert
46
- ```
47
-
48
- #### Revoke SSL cert
49
-
50
- ```ruby
51
- Varanus.new(customer_uri, username, password).ssl.revoke(id)
52
- ```
53
-
54
- #### Reports
55
-
56
- Report on all SSL certs
57
- ```ruby
58
- pp Varanus.new(customer_uri, usernams, password).reports.ssl
59
- ```
60
-
61
- Report on all domains (DCV status)
62
- ```ruby
63
- pp Varanus.new(customer_uri, usernams, password).reports.domains
64
- ```
65
-
66
- #### Authentication
67
-
68
- 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'```
69
-
70
- #### Finding Organization Id (org_id)
71
-
72
- Signing a cert requires specifying an ```org_id```. Each department in cert-manager.com has an associated ```org_id```.
73
-
74
- 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.
75
-
76
- ## Installation
77
-
78
- Add this line to your application's Gemfile:
79
-
80
- ```ruby
81
- gem 'varanus'
82
- ```
83
-
84
- And then execute:
85
-
86
- $ bundle
87
-
88
- Or install it yourself as:
89
-
90
- $ gem install varanus
91
-
92
- ## Development
93
-
94
- 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.
95
-
96
- 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).
97
-
98
- ## Contributing
99
-
100
- Bug reports and pull requests are welcome on GitHub at https://github.com/duke-automation/varanus.
101
-
102
- ## License
103
-
104
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile DELETED
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/gem_tasks'
4
- require 'rake/testtask'
5
-
6
- Rake::TestTask.new(:test) do |t|
7
- t.libs << 'test'
8
- t.libs << 'lib'
9
- t.test_files = FileList['test/**/*_test.rb']
10
- end
11
-
12
- task default: :test
data/bin/console DELETED
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require 'bundler/setup'
5
- require 'varanus'
6
-
7
- # You can add fixtures and/or initialization code here to make experimenting
8
- # with your gem easier. You can also use a different console, if you like.
9
-
10
- # (If you use this, don't forget to add pry to your Gemfile!)
11
- # require "pry"
12
- # Pry.start
13
-
14
- require 'irb'
15
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
data/docker-compose.yml DELETED
@@ -1,11 +0,0 @@
1
- version: '3'
2
- services:
3
- console:
4
- image: ruby:2.5
5
- volumes:
6
- - .:/app:z
7
- hostname: varanus-dev
8
- working_dir: /app
9
- stdin_open: true
10
- tty: true
11
- command: bash -c './bin/setup && ./bin/console'
data/lib/varanus/dcv.rb DELETED
@@ -1,62 +0,0 @@
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
@@ -1,46 +0,0 @@
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
-
43
- def report
44
- post('report/v1/domains', {})['reports']
45
- end
46
- end
data/lib/varanus/error.rb DELETED
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Error returned from the Sectigo API
4
- class Varanus::Error < StandardError
5
- # @return [Integer] Code associated with error
6
- attr_reader :code
7
-
8
- def initialize code, msg
9
- @code = code
10
- super(msg)
11
- end
12
- end
13
-
14
- # Certificate is still being signed.
15
- class Varanus::Error::StillProcessing < Varanus::Error; end
@@ -1,13 +0,0 @@
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
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # An connection to the Reports API. This should not be initialized directly. Instead,
4
- # use Varanus#reports
5
- class Varanus::Reports
6
- SSL_CERT_STATUSES = {
7
- any: 0,
8
- requested: 1,
9
- downloaded: 2,
10
- revoked: 3,
11
- expired: 4,
12
- pending_download: 5,
13
- not_enrolled: 6
14
- }.freeze
15
-
16
- # @note Do not call this directly. Use {Varanus#reports} to initialize
17
- def initialize varanus
18
- @varanus = varanus
19
- end
20
-
21
- # DEPRECATED: Please use Varanus::Domain#list_with_info instead.
22
- def domains
23
- warn 'DEPRECATION WARNING: Varanus::Reports#domains is deprecated. ' \
24
- 'Use Varanus::Domain#report instead'
25
- r = soap_call :get_domain_report, {}
26
- format_results r[:report_row_domains]
27
- end
28
-
29
- # DEPRECATED: Please use Varanus::SSL#report instead.
30
- def ssl opts = {}
31
- warn 'DEPRECATION WARNING: Varanus::Reports#ssl is deprecated. ' \
32
- 'Use Varanus::SSL#report instead'
33
-
34
- msg = { organizationNames: nil, certificateStatus: 0 }
35
-
36
- msg[:organizationNames] = Array(opts[:orgs]).join(',') if opts.include? :orgs
37
- if opts.include? :status
38
- msg[:certificateStatus] = SSL_CERT_STATUSES[opts[:status]]
39
- raise ArgumentError, 'Invalid status' if msg[:certificateStatus].nil?
40
- end
41
-
42
- r = soap_call :get_SSL_report, msg
43
- format_results r[:reports]
44
- end
45
-
46
- private
47
-
48
- def format_results results
49
- if results.is_a? Hash
50
- [results]
51
- else
52
- results.to_a
53
- end
54
- end
55
-
56
- def savon
57
- @savon ||= Savon.client(
58
- namespace: 'http://report.ws.epki.comodo.com/',
59
- endpoint: 'https://cert-manager.com:443/ws/ReportService',
60
- log: false
61
- )
62
- end
63
-
64
- def soap_call func, opts = {}
65
- msg = opts.dup
66
- msg[:authData] = { customerLoginUri: @varanus.customer_uri, login: @varanus.username,
67
- password: @varanus.password }
68
-
69
- result = savon.call func, message: msg
70
- result.body[(func.to_s.downcase + '_response').to_sym][:return]
71
- end
72
- end
@@ -1,56 +0,0 @@
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
@@ -1,131 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Wrapper class around a OpenSSL::X509::Request
4
- # Provides helper functions to make reading information from the CSR easier
5
- class Varanus::SSL::CSR
6
- # Key size used when calling {.generate}
7
- DEFAULT_KEY_SIZE = 4096
8
-
9
- # Generate a CSR
10
- # @param names [Array<String>] List of DNS names. The first one will be the CN
11
- # @param key [OpenSSL::PKey::RSA, OpenSSL::PKey::DSA, nil] Secret key for the cert.
12
- # A DSA key will be generated if +nil+ is passed in.
13
- # @param subject [Hash] Options for the subject of the cert. By default only CN will
14
- # be set
15
- # @return [Array(OpenSSL::PKey::PKey, Varanus::SSL::CSR)] The private key for the cert
16
- # and CSR
17
- def self.generate names, key = nil, subject = {}
18
- raise ArgumentError, 'names cannot be empty' if names.empty?
19
-
20
- subject = subject.dup
21
- subject['CN'] = names.first
22
-
23
- key ||= OpenSSL::PKey::DSA.new(DEFAULT_KEY_SIZE)
24
-
25
- request = OpenSSL::X509::Request.new
26
- request.version = 0
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.new('SHA256'))
32
-
33
- [key, Varanus::SSL::CSR.new(request)]
34
- end
35
-
36
- # :nodoc:
37
- # Create a Subject Alternate Names attribute from an Array of dns names
38
- def self.names_to_san_attribute names
39
- ef = OpenSSL::X509::ExtensionFactory.new
40
- name_str = names.map { |n| "DNS:#{n}" }.join(', ')
41
- ext = ef.create_extension('subjectAltName', name_str, false)
42
- seq = OpenSSL::ASN1::Sequence([ext])
43
- ext_req = OpenSSL::ASN1::Set([seq])
44
- OpenSSL::X509::Attribute.new('extReq', ext_req)
45
- end
46
-
47
- # Common Name (CN) for cert.
48
- # @return [String]
49
- attr_reader :cn
50
-
51
- # OpenSSL::X509::Request representation of CSR
52
- # @return [OpenSSL::X509::Request]
53
- attr_reader :request
54
-
55
- # @param csr [String, OpenSSL::X509::Request]
56
- def initialize csr
57
- if csr.is_a? OpenSSL::X509::Request
58
- @request = csr
59
- @text = csr.to_s
60
- else
61
- @text = csr.to_s
62
- @request = OpenSSL::X509::Request.new @text
63
- end
64
-
65
- raise 'Improperly signed CSR' unless @request.verify @request.public_key
66
-
67
- cn_ref = @request.subject.to_a.find { |a| a[0] == 'CN' }
68
- @cn = cn_ref && cn_ref[1].downcase
69
-
70
- _parse_sans
71
-
72
- # If we have no CN or SAN, raise an error
73
- raise 'CSR must have a CN and/or subjectAltName' if @cn.nil? && @sans.empty?
74
- end
75
-
76
- # Unique list of all DNS names for cert (CN and subject alt names)
77
- # @return [Array<String>]
78
- def all_names
79
- ([@cn] + @sans).compact.uniq
80
- end
81
-
82
- # Key size for the cert
83
- # @return [Integer]
84
- def key_size
85
- case @request.public_key
86
- when OpenSSL::PKey::RSA
87
- @request.public_key.n.num_bytes * 8
88
- when OpenSSL::PKey::DSA
89
- @request.public_key.p.num_bytes * 8
90
- when OpenSSL::PKey::EC
91
- @request.public_key.group.degree
92
- else
93
- raise "Unknown public key type: #{@request.public_key.class}"
94
- end
95
- end
96
-
97
- # PEM format for cert
98
- def to_s
99
- @text
100
- end
101
-
102
- # DNS subject alt names
103
- # @return [Array<String>]
104
- def subject_alt_names
105
- @sans
106
- end
107
-
108
- private
109
-
110
- def _parse_sans
111
- extensions = @request.attributes.select { |at| at.oid == 'extReq' }
112
- sans_extensions = extensions.flat_map do |extension|
113
- extension.value.value[0].value
114
- .select { |ext| ext.first.value == 'subjectAltName' }
115
- .map { |ext| ext.value.last }
116
- end
117
- @sans = sans_extensions.compact.flat_map do |san|
118
- _parse_sans_extension san
119
- end
120
- end
121
-
122
- def _parse_sans_extension ext
123
- OpenSSL::ASN1.decode(ext.value).map do |s_entry|
124
- unless s_entry.tag == 2 && s_entry.tag_class == :CONTEXT_SPECIFIC
125
- raise "unknown tag #{s_entry.tag}"
126
- end
127
-
128
- s_entry.value.downcase
129
- end
130
- end
131
- end
data/lib/varanus/ssl.rb DELETED
@@ -1,191 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # An connection to the SSL/TSL API. This should not be initialized directly. Instead,
4
- # use Varanus#ssl
5
- class Varanus::SSL < Varanus::RestResource
6
- # rubocop:disable Style/MutableConstant
7
- # These constants are frozen, rubocop is failing to detect the freeze.
8
- # See https://github.com/rubocop-hq/rubocop/issues/4406
9
- REPORT_CERT_STATUS = { any: 0, requested: 1, issued: 2, revoked: 3, expired: 4 }
10
- REPORT_CERT_STATUS.default_proc = proc { |_h, k|
11
- raise ArgumentError, "Unknown certificateStatus: #{k.inspect}"
12
- }
13
- REPORT_CERT_STATUS.freeze
14
-
15
- REPORT_CERT_DATE_ATTR = { revocation_date: 2, expiration_date: 3, request_date: 4,
16
- issue_date: 5 }
17
- REPORT_CERT_DATE_ATTR.default_proc = proc { |_h, k|
18
- raise ArgumentError, "Unknown certificateDateAttribute: #{k.inspect}"
19
- }
20
- REPORT_CERT_DATE_ATTR.freeze
21
- # rubocop:enable Style/MutableConstant
22
-
23
- # Returns the option from #certificate_types that best matches the csr.
24
- # @param csr [Varanus::SSL::CSR]
25
- # @return [Hash] The option from {#certificate_types} that best matches the csr
26
- def certificate_type_from_csr csr, days = nil
27
- types = certificate_types_standard(days)
28
- return types.first if types.length <= 1
29
-
30
- regexp = cert_type_regexp(csr)
31
- typ = types.find { |ct| ct['name'] =~ regexp } if regexp
32
- return typ unless typ.nil?
33
-
34
- types.find do |ct|
35
- ct['name'] =~ /\bSSL\b/ && ct['name'] !~ /(?:Multi.?Domain|Wildcard)/i
36
- end
37
- end
38
-
39
- # Certificate types that can be used to sign a cert
40
- # @return [Array<Hash>]
41
- def certificate_types
42
- @certificate_types ||= get('ssl/v1/types')
43
- end
44
-
45
- # Return Array of certificate types based on standard sorting.
46
- # @param days [Integer] if present, only include types that support the given day count
47
- # @return [Array<Hash>]
48
- def certificate_types_standard days = nil
49
- types = certificate_types.reject do |ct|
50
- ct['name'] =~ /\b(?:EV|Extended Validation|ECC|AMT|Elite)\b/
51
- end
52
- types = types.select! { |t| t['terms'].include? days } unless days.nil?
53
-
54
- types
55
- end
56
-
57
- # Retrieves the cert.
58
- # @param id [Integer] As returned by {#sign}
59
- # @param type [String]
60
- #
61
- # +type+ can be one of:
62
- # 'x509' - X509 format - cert and chain (default)
63
- # 'x509CO' - X509 format - cert only
64
- # 'x509IO' - X509 format - intermediates/root only
65
- # 'x590IOR' - X509 format - intermediates/root only reversed
66
- # 'base64' - PKCS#7 base64 encoded
67
- # 'bin' - PKCS#7 bin encoded
68
- #
69
- # @raise [Varanus::Error::StillProcessing] Cert is still being signed
70
- # @return [String] Certificate
71
- def collect id, type = 'x509'
72
- get("ssl/v1/collect/#{id}/#{type}")
73
- end
74
-
75
- # Returns info on the SSL certificate of the given name
76
- def info id
77
- get("ssl/v1/#{id}")
78
- end
79
-
80
- # List certs ids and serial numbers
81
- def list opts = {}
82
- get_with_size_and_position('ssl/v1', opts)
83
- end
84
-
85
- # Return a report (list) of SSL certs based on the options.
86
- # The report includes a full set of details about the certs, not just the id/cn/serial
87
- # +opts+ can include:
88
- # (all are optional)
89
- # - :organizationIds - Array - ids of organization/departments to include certs for
90
- # - :certificateStatus - :any, :requested, :issued, :revoked, or :expired
91
- # - :certificateDateAttribute - Specifies what fields :from and/or :to refer to.
92
- # Can be: :revocation_date, :expiration_date,
93
- # :request_date, or :issue_date
94
- # - :from - Date - based on :certificateDateAttribute
95
- # - :to - Date - based on :certificateDateAttribute
96
- def report opts = { certificateStatus: :any }
97
- # Default is to request any certificate status since the API call will fail if no
98
- # options are passed
99
- opts = { certificateStatus: :any } if opts.empty?
100
- opts = _parse_report_opts(opts)
101
-
102
- post('report/v1/ssl-certificates', opts)['reports']
103
- end
104
-
105
- # Revoke an ssl cert
106
- # @param id [Integer] As returned by {#sign}
107
- # @param reason [String] Reason for revoking. Sectigo's API will return an error if it
108
- # is blank.
109
- def revoke id, reason
110
- post("ssl/v1/revoke/#{id}", reason: reason)
111
- nil
112
- end
113
-
114
- # Sign an SSL cert. Returns the id of the SSL cert
115
- # @param csr [Varanus::SSL::CSR, OpenSSL::X509::Request, String] CSR to sign
116
- # @param org_id [Integer] your organization id on cert-manager.com
117
- # @param opts [Hash]
118
- # @option opts [String] :comments ('') Limited to 1,024 characters
119
- # @option opts [String] :external_requester ('') email address associated with cert on
120
- # cert-manager.com - limited to 512 characters
121
- # @option opts [String, Integer] :cert_type name(String) or id(Integer) of the cert
122
- # type to use. If none is specified, Varanus will attempt to find one
123
- # @option opts [Integer] :years number of years cert should be valid for (this number
124
- # is multiplied by 365 and used as days)
125
- # @option opts [Integer] :days number of days cert should be valid for (if none is
126
- # specified, lowest allowed for the cert type will be used)
127
- # @return [Integer] Id of SSL cert.
128
- def sign csr, org_id, opts = {}
129
- opts[:days] ||= opts[:years] * 365 unless opts[:years].nil?
130
- csr = Varanus::SSL::CSR.new(csr) unless csr.is_a?(Varanus::SSL::CSR)
131
- cert_type_id = opts_to_cert_type_id opts, csr
132
- args = {
133
- orgId: org_id,
134
- csr: csr.to_s,
135
- subjAltNames: csr.subject_alt_names.join(','),
136
- certType: cert_type_id,
137
- term: opts_to_term(opts, cert_type_id),
138
- serverType: -1,
139
- comments: opts[:comments].to_s[0, 1024],
140
- externalRequester: opts[:external_requester].to_s[0, 512]
141
- }
142
- post('ssl/v1/enroll', args)['sslId']
143
- end
144
-
145
- private
146
-
147
- def cert_type_regexp csr
148
- return /Wildcard.+SSL/i if csr.all_names.any? { |n| n.start_with?('*.') }
149
-
150
- return /Multi.?Domain.+SSL/i if csr.subject_alt_names.any?
151
-
152
- nil
153
- end
154
-
155
- def opts_to_cert_type_id opts, csr
156
- case opts[:cert_type]
157
- when Integer
158
- opts[:cert_type]
159
- when String
160
- certificate_types.find { |ct| ct['name'] == opts[:cert_type] }['id']
161
- else
162
- certificate_type_from_csr(csr, opts[:days])['id']
163
- end
164
- end
165
-
166
- def opts_to_term opts, cert_type_id
167
- term = opts[:days]
168
- term ||= certificate_types.find { |ct| ct['id'] == cert_type_id }['terms'].min
169
- term
170
- end
171
-
172
- def _parse_report_opts user_opts
173
- api_opts = {}
174
- user_opts.each do |key, val|
175
- case key
176
- when :organizationIds, :certificateRequestSource, :serialNumberFormat
177
- api_opts[key] = val
178
- when :from, :to
179
- api_opts[key] = val.strftime('%Y-%m-%d')
180
- when :certificateStatus
181
- api_opts[key] = REPORT_CERT_STATUS[val]
182
- when :certificateDateAttribute
183
- api_opts[key] = REPORT_CERT_DATE_ATTR[val]
184
- else
185
- raise ArgumentError, "Unknown key: #{key.inspect}"
186
- end
187
- end
188
-
189
- api_opts
190
- end
191
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Varanus
4
- VERSION = '0.7.1'
5
- end
data/lib/varanus.rb DELETED
@@ -1,77 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Interface for Sectigo's (formerly Comodo CA) API.
4
- class Varanus
5
- attr_reader :customer_uri, :username, :password
6
-
7
- # @param customer_uri [String]
8
- # (see {file:README.md#label-Finding+Organization+Id+-28org_id-29})
9
- # @param username [String]
10
- # @param password [String]
11
- def initialize customer_uri, username, password
12
- @customer_uri = customer_uri
13
- @username = username
14
- @password = password
15
- end
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
-
50
- # DEPRECATED
51
- def reports
52
- @reports ||= Reports.new(self)
53
- end
54
-
55
- # Retrive SSL instance
56
- # @return [Varanus::SSL]
57
- def ssl
58
- @ssl ||= SSL.new(self)
59
- end
60
- end
61
-
62
- # stdlib/gem requires
63
- require 'faraday'
64
- require 'faraday_middleware'
65
- require 'openssl'
66
- require 'savon'
67
-
68
- # Require other files in this gem
69
- require 'varanus/error'
70
- require 'varanus/rest_resource'
71
- require 'varanus/dcv'
72
- require 'varanus/domain'
73
- require 'varanus/organization'
74
- require 'varanus/reports'
75
- require 'varanus/ssl'
76
- require 'varanus/ssl/csr'
77
- require 'varanus/version'
data/varanus.gemspec DELETED
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- lib = File.expand_path('lib', __dir__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'varanus/version'
6
-
7
- Gem::Specification.new do |spec|
8
- spec.name = 'varanus'
9
- spec.version = Varanus::VERSION
10
- spec.authors = ['Sean Dilda']
11
- spec.email = ['sean@duke.edu']
12
-
13
- spec.summary = "Interface for Sectigo's (formerly Comodo CA) API."
14
- spec.description = <<~DESCRIPTION
15
- This gem provides an interface to Sectigo's (formerly Comodo CA) APIs for working
16
- with SSL/TLS certificates as well as its reporting API.
17
-
18
- Support for Sectigo's other APIs (S/MIME, code signing, device certificates, etc) may
19
- be added at a later date.
20
- DESCRIPTION
21
- spec.homepage = 'https://github.com/duke-automation/varanus'
22
- spec.license = 'MIT'
23
-
24
- # Specify which files should be added to the gem when it is released.
25
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
26
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
27
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
28
- end
29
- spec.require_paths = ['lib']
30
- spec.required_ruby_version = '>= 2.5.0'
31
-
32
- spec.add_development_dependency 'bundler', '~> 1.16'
33
- spec.add_development_dependency 'minitest', '~> 5.0'
34
- spec.add_development_dependency 'minitest-rg'
35
- spec.add_development_dependency 'mocha'
36
- spec.add_development_dependency 'rake', '~> 10.0'
37
- spec.add_development_dependency 'rubocop'
38
- spec.add_development_dependency 'simplecov'
39
- spec.add_development_dependency 'webmock'
40
- spec.add_development_dependency 'yard'
41
-
42
- spec.add_runtime_dependency 'faraday'
43
- spec.add_runtime_dependency 'faraday_middleware'
44
- spec.add_runtime_dependency 'savon', '~> 2.0'
45
- end