saml-kit-cli 0.3.6 → 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59de9eccceb5455e9c5401acc901fff8bf7633510cf5516f92cbeecce0cd2677
4
- data.tar.gz: c76817df6dbbf92c25c4e7af6d0d15d20797a6286d3c718eec4db0f06654235a
3
+ metadata.gz: cdac1443e0096b2397693cdf4e7123a71966d68652ca19526ea4ff3f0a2ed124
4
+ data.tar.gz: eb10198f4f8a26aa64260f487a6c6c2c8acf7ad86d647a33fbb24175be9b16a6
5
5
  SHA512:
6
- metadata.gz: 63d5998c035e2a4a81e3b58f41f01801f83904c3984f81ef73e786010eac4191955e5164ff1ee927f97865933646d6737d4bfdaec5e054a6b9d72aac765b0898
7
- data.tar.gz: 430fc05192cfefaaa5ed58e8c5ce335dd14007b9049c77b595340a35bb9c5eb0885aac47a09639522cfb695d28b5c14b0ee2a477e5ac4ea2639b26bcf4f28293
6
+ metadata.gz: 6c929b7db445f1bc2958d87a927fb05835562a516d7d118c4616d7435ab926fc9dc726fba6056f32c92b6771409d52af1ff7164057e81810b8ddaaf4b35d3950
7
+ data.tar.gz: 460ea4637be3c0af9676b5ad97ef84ec4c0c57ff923671f5eef080fd1787e38743afdd88b9563bc5a33f6eabb1ae9f9e602ebb2ff4dd5e88046852b26f273c39
data/.gitlab-ci.yml ADDED
@@ -0,0 +1,15 @@
1
+ image: ruby:2.2
2
+
3
+ before_script:
4
+ - apt-get update && apt-get install -y locales
5
+ - echo "en_US.UTF-8 UTF-8" > /etc/locale.gen
6
+ - locale-gen
7
+ - export LC_ALL=en_US.UTF-8
8
+
9
+ rspec:
10
+ script:
11
+ - bin/cibuild
12
+
13
+ lint:
14
+ script:
15
+ - bin/lint
data/.rubocop.yml ADDED
@@ -0,0 +1,81 @@
1
+ require:
2
+ - rubocop/cop/internal_affairs
3
+ - rubocop-rspec
4
+
5
+ AllCops:
6
+ Exclude:
7
+ - 'coverage/**/*'
8
+ - 'pkg/**/*'
9
+ - 'spec/fixtures/**/*'
10
+ - 'tmp/**/*'
11
+ - 'vendor/**/*'
12
+ TargetRubyVersion: 2.2
13
+
14
+ Layout/ClassStructure:
15
+ Enabled: true
16
+ Categories:
17
+ module_inclusion:
18
+ - include
19
+ - prepend
20
+ - extend
21
+ ExpectedOrder:
22
+ - module_inclusion
23
+ - constants
24
+ - public_class_methods
25
+ - initializer
26
+ - instance_methods
27
+ - protected_methods
28
+ - private_methods
29
+
30
+ Layout/EndOfLine:
31
+ EnforcedStyle: lf
32
+
33
+ Layout/IndentArray:
34
+ EnforcedStyle: consistent
35
+
36
+ Layout/IndentHeredoc:
37
+ EnforcedStyle: active_support
38
+
39
+ Lint/AmbiguousBlockAssociation:
40
+ Exclude:
41
+ - 'spec/**/*.rb'
42
+
43
+ Lint/InterpolationCheck:
44
+ Exclude:
45
+ - 'spec/**/*.rb'
46
+
47
+ Metrics/BlockLength:
48
+ Exclude:
49
+ - '**/*.rake'
50
+ - '*.gemspec'
51
+ - 'Rakefile'
52
+ - 'spec/**/*.rb'
53
+
54
+ Metrics/ModuleLength:
55
+ Exclude:
56
+ - 'spec/**/*.rb'
57
+
58
+ Metrics/LineLength:
59
+ Exclude:
60
+ - 'spec/**/*.rb'
61
+
62
+ Style/Documentation:
63
+ Enabled: false
64
+
65
+ Style/EachWithObject:
66
+ Enabled: false
67
+
68
+ Style/StringLiterals:
69
+ EnforcedStyle: 'single_quotes'
70
+
71
+ Style/TrailingCommaInArrayLiteral:
72
+ Enabled: false
73
+
74
+ Style/TrailingCommaInHashLiteral:
75
+ Enabled: false
76
+
77
+ RSpec/MultipleExpectations:
78
+ Enabled: false
79
+
80
+ RSpec/NamedSubject:
81
+ Enabled: false
data/.travis.yml CHANGED
@@ -1,5 +1,11 @@
1
1
  sudo: false
2
2
  language: ruby
3
+ cache: bundler
3
4
  rvm:
5
+ - 2.2.9
6
+ - 2.3.6
7
+ - 2.4.3
4
8
  - 2.5.0
5
- before_install: gem install bundler -v 1.16.1
9
+ script:
10
+ - bin/cibuild
11
+ - bin/lint
data/Gemfile CHANGED
@@ -1,6 +1,8 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
6
 
5
7
  # Specify your gem's dependencies in saml-kit-cli.gemspec
6
8
  gemspec
data/README.md CHANGED
@@ -1,38 +1,35 @@
1
1
  # Saml::Kit::Cli
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/saml/kit/cli`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ [![Build Status](https://travis-ci.org/saml-kit/saml-kit-cli.svg?branch=master)](https://travis-ci.org/saml-kit/saml-kit-cli)
4
+ [![Maintainability](https://api.codeclimate.com/v1/badges/f303b0bfa878d7b81722/maintainability)](https://codeclimate.com/github/saml-kit/saml-kit-cli/maintainability)
5
+ [![Security](https://hakiri.io/github/saml-kit/saml-kit-cli/master.svg)](https://hakiri.io/github/saml-kit/saml-kit-cli/master)
6
6
 
7
7
  ## Installation
8
8
 
9
- Add this line to your application's Gemfile:
10
-
11
9
  ```ruby
12
- gem 'saml-kit-cli'
10
+ gem install 'saml-kit-cli'
13
11
  ```
14
12
 
15
- And then execute:
16
-
17
- $ bundle
18
-
19
- Or install it yourself as:
20
-
21
- $ gem install saml-kit-cli
22
-
23
13
  ## Usage
24
14
 
25
- TODO: Write usage instructions here
15
+ ```bash
16
+ も saml-kit
17
+ Commands:
18
+ saml-kit certificate SUBCOMMAND ...ARGS # Work with SAML Certificates.
19
+ saml-kit decode SUBCOMMAND ...ARGS # decode SAMLRequest/SAMLResponse.
20
+ saml-kit help [COMMAND] # Describe available commands or one specific command
21
+ saml-kit metadata SUBCOMMAND ...ARGS # Work with SAML Metadata.
22
+ saml-kit version # Display the current version
23
+ saml-kit xmldsig SUBCOMMAND ...ARGS # Check XML digital signatures.
24
+ ```
26
25
 
27
26
  ## Development
28
27
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
-
31
- 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).
28
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
32
29
 
33
30
  ## Contributing
34
31
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/saml-kit-cli.
32
+ Bug reports and pull requests are welcome on GitHub at https://github.com/saml-kit/saml-kit-cli.
36
33
 
37
34
  ## License
38
35
 
data/Rakefile CHANGED
@@ -1,6 +1,13 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+ require 'bundler/audit/task'
3
7
 
4
8
  RSpec::Core::RakeTask.new(:spec)
9
+ RuboCop::RakeTask.new(:rubocop)
10
+ Bundler::Audit::Task.new
5
11
 
6
- task :default => :spec
12
+ task lint: [:rubocop, 'bundle:audit']
13
+ task default: :spec
data/bin/cibuild ADDED
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+
3
+ # script/cibuild: Setup environment for CI to run tests. This is primarily
4
+ # designed to run on the continuous integration server.
5
+
6
+ set -e
7
+
8
+ cd "$(dirname "$0")/.."
9
+
10
+ echo [$(date "+%H:%M:%S")] "==> Started at…"
11
+
12
+ # GC customizations
13
+ export RUBY_GC_MALLOC_LIMIT=79000000
14
+ export RUBY_GC_HEAP_INIT_SLOTS=800000
15
+ export RUBY_HEAP_FREE_MIN=100000
16
+ export RUBY_HEAP_SLOTS_INCREMENT=400000
17
+ export RUBY_HEAP_SLOTS_GROWTH_FACTOR=1
18
+
19
+ ruby -v
20
+ gem install bundler --no-ri --no-rdoc --conservative
21
+ bin/test
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "saml/kit/cli"
4
+ require 'bundler/setup'
5
+ require 'saml/kit/cli'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "saml/kit/cli"
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- require "irb"
14
+ require 'irb'
14
15
  IRB.start(__FILE__)
data/bin/lint ADDED
@@ -0,0 +1,11 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ [ -z "$DEBUG" ] || set -x
6
+
7
+ echo [$(date "+%H:%M:%S")] "==> Running setup…"
8
+ bin/setup
9
+
10
+ echo [$(date "+%H:%M:%S")] "==> Running linters…"
11
+ bundle exec rake lint
data/bin/test ADDED
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+
3
+ # script/test: Run test suite for application. Optionally pass in a path to an
4
+ # individual test file to run a single test.
5
+
6
+
7
+ set -e
8
+
9
+ cd "$(dirname "$0")/.."
10
+
11
+ [ -z "$DEBUG" ] || set -x
12
+
13
+ echo [$(date "+%H:%M:%S")] "==> Running setup…"
14
+ bin/setup
15
+
16
+ echo [$(date "+%H:%M:%S")] "==> Running tests…"
17
+ bundle exec rake spec
data/exe/saml-kit CHANGED
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "saml/kit/cli"
4
+ require 'saml/kit/cli'
4
5
 
5
- samlkitrc = ENV.fetch("SAMLKITRC", File.join(Dir.home, ".samlkitrc"))
6
+ samlkitrc = ENV.fetch('SAMLKITRC', File.join(Dir.home, '.samlkitrc'))
6
7
  Saml::Kit.configure do |configuration|
7
- configuration.entity_id = ENV.fetch('ENTITY_ID', `hostname`.chomp)
8
+ configuration.entity_id = ENV.fetch('ENTITY_ID', Socket.gethostname.chomp)
8
9
  configuration.registry = Saml::Kit::Cli::YamlRegistry.new(samlkitrc)
9
10
  configuration.logger.level = Logger::FATAL
10
11
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Saml
4
+ module Kit
5
+ module Cli
6
+ class CertificateReport
7
+ HEADER = [
8
+ 'Subject', 'Issuer', 'Serial',
9
+ 'Not Before', 'Not After', 'Fingerprint'
10
+ ].freeze
11
+ attr_reader :certificate, :x509
12
+
13
+ def initialize(raw)
14
+ @certificate = ::Xml::Kit::Certificate.new(raw, use: :unknown)
15
+ @x509 = @certificate.x509
16
+ end
17
+
18
+ def print(shell)
19
+ shell.print_table([HEADER, body])
20
+ shell.say(x509.to_text, :green)
21
+ end
22
+
23
+ private
24
+
25
+ def fingerprint
26
+ certificate.fingerprint
27
+ end
28
+
29
+ def body
30
+ [
31
+ x509.subject, x509.issuer, x509.serial,
32
+ x509.not_before, x509.not_after, fingerprint
33
+ ]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Saml
4
+ module Kit
5
+ module Cli
6
+ module Commands
7
+ class Certificate < Thor
8
+ desc 'keypair', 'Create a key pair using a self signed certificate.'
9
+ method_option(
10
+ :format,
11
+ default: 'pem',
12
+ required: false,
13
+ enum: %w[pem env]
14
+ )
15
+ method_option :passphrase, default: nil, required: false
16
+ def keypair
17
+ GenerateKeyPair.new(
18
+ passphrase: options[:passphrase],
19
+ format: options[:format]
20
+ ).run(self)
21
+ end
22
+
23
+ desc 'dump', 'Dump the details of a X509 Certificate.'
24
+ def dump(raw)
25
+ CertificateReport.new(raw).print(self)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Saml
4
+ module Kit
5
+ module Cli
6
+ module Commands
7
+ class Decode < Thor
8
+ desc 'redirect uri', 'Decodes the uri using the HTTP Redirect binding'
9
+ method_option :export, default: nil, required: false
10
+ def redirect(uri)
11
+ print_report_for(redirect_binding.deserialize(uri))
12
+ rescue StandardError => error
13
+ say error.message, :red
14
+ end
15
+
16
+ desc(
17
+ 'post saml',
18
+ 'Decodes the SAMLRequest/SAMLResponse using the HTTP Post binding'
19
+ )
20
+ method_option :export, default: nil, required: false
21
+ def post(saml)
22
+ print_report_for(post_binding.deserialize('SAMLRequest' => saml))
23
+ rescue StandardError => error
24
+ say error.message, :red
25
+ end
26
+
27
+ desc 'raw <file>', 'Decode the contents of a decoded file'
28
+ def raw(file)
29
+ content = IO.read(File.expand_path(file))
30
+ print_report_for(Document.to_saml_document(content))
31
+ rescue StandardError => error
32
+ say error.message, :red
33
+ end
34
+
35
+ private
36
+
37
+ def print_report_for(document, export = options[:export])
38
+ IO.write(export, document.to_xml) if export
39
+ 2.times { say '' }
40
+ Report.new(document).print(self)
41
+ end
42
+
43
+ def post_binding(location = '')
44
+ Saml::Kit::Bindings::HttpPost.new(location: location)
45
+ end
46
+
47
+ def redirect_binding(location = '')
48
+ Saml::Kit::Bindings::HttpRedirect.new(location: location)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Saml
4
+ module Kit
5
+ module Cli
6
+ module Commands
7
+ class Metadata < Thor
8
+ desc 'register url', 'Registers the Metadata from the remote url.'
9
+ def register(url)
10
+ say registry.register_url(url).to_xml(pretty: true), :green
11
+ end
12
+
13
+ desc 'list', "List each of the registered entityId's"
14
+ def list
15
+ if registry.count.zero?
16
+ say('Register metadata using `saml-kit metadata register <url>`')
17
+ end
18
+ registry.each do |x|
19
+ say x.entity_id, :green
20
+ end
21
+ end
22
+
23
+ desc 'show entity_id', 'show the metadata associated with an entityId'
24
+ def show(entity_id)
25
+ metadata = registry.metadata_for(entity_id)
26
+ if metadata
27
+ Report.new(metadata).print(self)
28
+ else
29
+ say "`#{entity_id}` is not registered", :red
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def registry
36
+ Saml::Kit.registry
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Saml
4
+ module Kit
5
+ module Cli
6
+ module Commands
7
+ class XmlDigitalSignature < Thor
8
+ desc(
9
+ 'verify file',
10
+ 'Verify if the contents of a file has a valid signature.'
11
+ )
12
+ method_option(
13
+ :format,
14
+ default: 'short',
15
+ required: false,
16
+ enum: %w[short full]
17
+ )
18
+ def verify(file)
19
+ report = SignatureReport.new(file, format: options[:format])
20
+ report.print(self)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'saml/kit/cli/commands/certificate'
4
+ require 'saml/kit/cli/commands/decode'
5
+ require 'saml/kit/cli/commands/metadata'
6
+ require 'saml/kit/cli/commands/xml_digital_signature'
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Saml
4
+ module Kit
5
+ module Cli
6
+ class GenerateKeyPair
7
+ attr_reader :passphrase, :format
8
+
9
+ def initialize(passphrase:, format:)
10
+ @passphrase = passphrase
11
+ @format = format
12
+ end
13
+
14
+ def run(shell)
15
+ certificate, private_key = generate
16
+ if pem?
17
+ shell.say certificate
18
+ shell.say private_key
19
+ else
20
+ shell.say 'X509_CERTIFICATE=' + certificate.inspect
21
+ shell.say 'PRIVATE_KEY=' + private_key.inspect
22
+ end
23
+ shell.say 'Private Key Passphrase:', :green
24
+ shell.say passphrase.inspect
25
+ end
26
+
27
+ private
28
+
29
+ def generate
30
+ generator = ::Xml::Kit::SelfSignedCertificate.new
31
+ generator.create(passphrase: passphrase)
32
+ end
33
+
34
+ def pem?
35
+ format == 'pem'
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Saml
2
4
  module Kit
3
5
  module Cli
@@ -9,102 +11,30 @@ module Saml
9
11
  end
10
12
 
11
13
  def print(shell)
12
- shell.say_status :success, "Decoded #{document.send(:name)}"
13
- shell.print_table build_table_for(document)
14
- shell.say ""
15
- if document.signature.present? && document.signature.certificate.present?
16
- shell.say(document.signature.certificate.x509.to_text)
17
- end
18
- shell.say ""
19
- shell.say document.to_xml(pretty: true), :green
20
- shell.say ""
21
- document.errors.full_messages.each do |error|
22
- shell.say_status :error, error, :red
23
- end
14
+ shell.say_status status, "Decoded #{document.send(:name)}"
15
+ shell.print_table document.build_table
16
+ print_signature(document.signature, shell)
17
+ print_xml(shell)
18
+ print_errors(document.errors.full_messages, shell)
24
19
  end
25
20
 
26
21
  private
27
22
 
28
- def truncate(text, max: 50)
29
- if text.length >= max
30
- "#{text[0..max]}..."
31
- else
32
- text
33
- end
23
+ def status
24
+ document.is_a?(Saml::Kit::InvalidDocument) ? :error : :sucess
25
+ end
26
+
27
+ def print_errors(errors, shell)
28
+ errors.each { |x| shell.say_status :error, x, :red }
34
29
  end
35
30
 
36
- def build_table_for(document)
37
- table = [ ]
38
- case document
39
- when Saml::Kit::Document
40
- table.push(['ID', document.id])
41
- table.push(['Issuer', document.issuer])
42
- table.push(['Version', document.version])
43
- table.push(['Issue Instant', document.issue_instant.iso8601])
44
- table.push(['Type', document.send(:name)])
45
- table.push(['Valid', document.valid?])
46
- table.push(['Signed?', !!document.signed?])
47
- table.push(['Trusted?', !!document.trusted?])
48
- when Saml::Kit::Metadata
49
- table.push(['Entity Id', document.entity_id])
50
- table.push(['Type', document.send(:name)])
51
- table.push(['Valid', document.valid?])
52
- table.push(['Name Id Formats', document.name_id_formats.inspect])
53
- table.push(['Organization', document.organization_name])
54
- table.push(['Url', document.organization_url])
55
- table.push(['Contact', document.contact_person_company])
56
- [
57
- 'SingleSignOnService',
58
- 'SingleLogoutService',
59
- 'AssertionConsumerService'
60
- ].each do |type|
61
- document.services(type).each do |service|
62
- table.push([type, [service.location, service.binding]])
63
- end
64
- end
65
- document.certificates.each do |certificate|
66
- table.push(['', certificate.x509.to_text])
67
- end
68
- end
69
- if document.signature.present?
70
- signature = document.signature
71
- table.push(['Digest Value', signature.digest_value])
72
- table.push(['Expected Digest Value', signature.expected_digest_value])
73
- table.push(['Digest Method', signature.digest_method])
74
- table.push(['Signature Value', truncate(signature.signature_value)])
75
- table.push(['Signature Method', signature.signature_method])
76
- table.push(['Canonicalization Method', signature.canonicalization_method])
77
- table.push(['', signature.certificate.x509.to_text])
78
- end
79
- case document
80
- when Saml::Kit::AuthenticationRequest
81
- table.push(['ACS', document.assertion_consumer_service_url])
82
- table.push(['Name Id Format', document.name_id_format])
83
- when Saml::Kit::LogoutRequest
84
- table.push(['Name Id', document.name_id])
85
- when Saml::Kit::Response
86
- table.push(['Assertion Present?', document.assertion.present?])
87
- table.push(['Issuer', document.assertion.issuer])
88
- table.push(['Name Id', document.assertion.name_id])
89
- table.push(['Signed?', !!document.assertion.signed?])
90
- table.push(['Attributes', document.assertion.attributes.inspect])
91
- table.push(['Not Before', document.assertion.started_at])
92
- table.push(['Not After', document.assertion.expired_at])
93
- table.push(['Audiences', document.assertion.audiences.inspect])
94
- table.push(['Encrypted?', document.assertion.encrypted?])
95
- table.push(['Decryptable', document.assertion.decryptable?])
96
- if document.assertion.present?
97
- signature = document.assertion.signature
98
- table.push(['Digest Value', signature.digest_value])
99
- table.push(['Expected Digest Value', signature.expected_digest_value])
100
- table.push(['Digest Method', signature.digest_method])
101
- table.push(['Signature Value', truncate(signature.signature_value)])
102
- table.push(['Signature Method', signature.signature_method])
103
- table.push(['Canonicalization Method', signature.canonicalization_method])
104
- table.push(['', signature.certificate.x509.to_text])
105
- end
106
- end
107
- table
31
+ def print_signature(signature, shell)
32
+ return if !signature.present? || !signature.certificate.present?
33
+ shell.say(signature.certificate.x509.to_text)
34
+ end
35
+
36
+ def print_xml(shell)
37
+ shell.say document.to_xml(pretty: true), :green
108
38
  end
109
39
  end
110
40
  end