hammer_cli 0.10.1 → 0.10.2
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/bin/hammer +1 -1
- data/config/cli_config.template.yml +4 -1
- data/doc/release_notes.md +5 -0
- data/lib/hammer_cli/abstract.rb +9 -4
- data/lib/hammer_cli/apipie/api_connection.rb +1 -1
- data/lib/hammer_cli/ca_cert_fetcher.rb +15 -4
- data/lib/hammer_cli/ca_cert_manager.rb +18 -33
- data/lib/hammer_cli/exceptions.rb +1 -0
- data/lib/hammer_cli/exit_codes.rb +2 -1
- data/lib/hammer_cli/ssloptions.rb +19 -10
- data/lib/hammer_cli/version.rb +1 -1
- data/lib/hammer_cli.rb +1 -0
- data/man/hammer.1.gz +0 -0
- data/test/unit/apipie/api_connection_test.rb +0 -1
- data/test/unit/ca_cert_manager_test.rb +23 -33
- data/test/unit/fixtures/certs/non_ca_cert.pem +27 -0
- metadata +50 -322
- data/test/reports/TEST-Fields-ContainerField-display-.xml +0 -7
- data/test/reports/TEST-Fields-ContainerField-display-blank-is-allowed.xml +0 -15
- data/test/reports/TEST-Fields-ContainerField-display-blank-is-not-allowed.xml +0 -15
- data/test/reports/TEST-Fields-ContainerField.xml +0 -7
- data/test/reports/TEST-Fields-Field-display-.xml +0 -7
- data/test/reports/TEST-Fields-Field-display-blank-is-allowed.xml +0 -11
- data/test/reports/TEST-Fields-Field-display-blank-is-not-allowed.xml +0 -11
- data/test/reports/TEST-Fields-Field-hide-blank-.xml +0 -11
- data/test/reports/TEST-Fields-Field-parameters.xml +0 -9
- data/test/reports/TEST-Fields-Field.xml +0 -13
- data/test/reports/TEST-HammerCLI-AbstractCommand-build-options.xml +0 -15
- data/test/reports/TEST-HammerCLI-AbstractCommand-exception-handler.xml +0 -13
- data/test/reports/TEST-HammerCLI-AbstractCommand-logging.xml +0 -21
- data/test/reports/TEST-HammerCLI-AbstractCommand-option-builder.xml +0 -11
- data/test/reports/TEST-HammerCLI-AbstractCommand-options.xml +0 -11
- data/test/reports/TEST-HammerCLI-AbstractCommand-output.xml +0 -19
- data/test/reports/TEST-HammerCLI-AbstractCommand-subcommand-behavior-remove-subcommand.xml +0 -11
- data/test/reports/TEST-HammerCLI-AbstractCommand-subcommand-behavior-subcommand-.xml +0 -13
- data/test/reports/TEST-HammerCLI-AbstractCommand-subcommand-behavior-subcommand.xml +0 -11
- data/test/reports/TEST-HammerCLI-AbstractCommand-subcommand-behavior.xml +0 -7
- data/test/reports/TEST-HammerCLI-AbstractCommand.xml +0 -11
- data/test/reports/TEST-HammerCLI-Apipie-Command-options.xml +0 -11
- data/test/reports/TEST-HammerCLI-Apipie-Command-resource-defined.xml +0 -9
- data/test/reports/TEST-HammerCLI-Apipie-Command-setting-resources.xml +0 -19
- data/test/reports/TEST-HammerCLI-Apipie-Command.xml +0 -9
- data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder-aliasing-resources.xml +0 -13
- data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder-filtering-options.xml +0 -15
- data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder-required-options.xml +0 -11
- data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder-setting-correct-normalizers.xml +0 -9
- data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder-with-hash-params.xml +0 -11
- data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder-with-one-simple-param.xml +0 -15
- data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder.xml +0 -7
- data/test/reports/TEST-HammerCLI-Completer-command-completion.xml +0 -29
- data/test/reports/TEST-HammerCLI-Completer-option-value-completion.xml +0 -17
- data/test/reports/TEST-HammerCLI-Completer-subcommand-completion.xml +0 -19
- data/test/reports/TEST-HammerCLI-Completer.xml +0 -7
- data/test/reports/TEST-HammerCLI-CompleterLine-line-complete.xml +0 -25
- data/test/reports/TEST-HammerCLI-CompleterLine-splitting-words.xml +0 -29
- data/test/reports/TEST-HammerCLI-CompleterLine.xml +0 -7
- data/test/reports/TEST-HammerCLI-CompleterWord-complete-.xml +0 -23
- data/test/reports/TEST-HammerCLI-CompleterWord-quote.xml +0 -15
- data/test/reports/TEST-HammerCLI-CompleterWord-quoted-.xml +0 -13
- data/test/reports/TEST-HammerCLI-CompleterWord.xml +0 -7
- data/test/reports/TEST-HammerCLI-Connection.xml +0 -21
- data/test/reports/TEST-HammerCLI-ExceptionHandler.xml +0 -21
- data/test/reports/TEST-HammerCLI-I18n.xml +0 -11
- data/test/reports/TEST-HammerCLI-MainCommand-loading-context-password.xml +0 -11
- data/test/reports/TEST-HammerCLI-MainCommand-loading-context-username.xml +0 -11
- data/test/reports/TEST-HammerCLI-MainCommand-loading-context-verbose.xml +0 -9
- data/test/reports/TEST-HammerCLI-MainCommand-loading-context.xml +0 -7
- data/test/reports/TEST-HammerCLI-MainCommand.xml +0 -7
- data/test/reports/TEST-HammerCLI-Modules-find-by-name.xml +0 -13
- data/test/reports/TEST-HammerCLI-Modules-load-a-module-module-not-found.xml +0 -13
- data/test/reports/TEST-HammerCLI-Modules-load-a-module-module-runtime-exception.xml +0 -13
- data/test/reports/TEST-HammerCLI-Modules-load-a-module-success.xml +0 -15
- data/test/reports/TEST-HammerCLI-Modules-load-a-module.xml +0 -7
- data/test/reports/TEST-HammerCLI-Modules-load-all-modules.xml +0 -9
- data/test/reports/TEST-HammerCLI-Modules-names.xml +0 -13
- data/test/reports/TEST-HammerCLI-Modules.xml +0 -7
- data/test/reports/TEST-HammerCLI-OptionBuilderContainer.0.xml +0 -7
- data/test/reports/TEST-HammerCLI-OptionBuilderContainer.xml +0 -11
- data/test/reports/TEST-HammerCLI-Options-Normalizers-abstract.xml +0 -9
- data/test/reports/TEST-HammerCLI-Options-Normalizers-bool.xml +0 -31
- data/test/reports/TEST-HammerCLI-Options-Normalizers-datetime.xml +0 -17
- data/test/reports/TEST-HammerCLI-Options-Normalizers-enum.xml +0 -15
- data/test/reports/TEST-HammerCLI-Options-Normalizers-enumlist.xml +0 -21
- data/test/reports/TEST-HammerCLI-Options-Normalizers-json-input.xml +0 -15
- data/test/reports/TEST-HammerCLI-Options-Normalizers-key-value-list.xml +0 -17
- data/test/reports/TEST-HammerCLI-Options-Normalizers-list.xml +0 -15
- data/test/reports/TEST-HammerCLI-Options-Normalizers.xml +0 -7
- data/test/reports/TEST-HammerCLI-Options-OptionDefinition-context.xml +0 -9
- data/test/reports/TEST-HammerCLI-Options-OptionDefinition-formatters.xml +0 -11
- data/test/reports/TEST-HammerCLI-Options-OptionDefinition.xml +0 -7
- data/test/reports/TEST-HammerCLI-Output-Adapter-Abstract-error-messages.xml +0 -15
- data/test/reports/TEST-HammerCLI-Output-Adapter-Abstract-messages.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Adapter-Abstract-test-data-for-field.xml +0 -15
- data/test/reports/TEST-HammerCLI-Output-Adapter-Abstract.xml +0 -17
- data/test/reports/TEST-HammerCLI-Output-Adapter-Base-print-collection-show-ids.xml +0 -9
- data/test/reports/TEST-HammerCLI-Output-Adapter-Base-print-collection.xml +0 -27
- data/test/reports/TEST-HammerCLI-Output-Adapter-Base.xml +0 -7
- data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues-print-collection-formatters.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues-print-collection-handle-fields-with-collections.xml +0 -13
- data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues-print-collection-handle-fields-with-containers.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues-print-collection-handle-ids.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues-print-collection.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues-print-message.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues.xml +0 -7
- data/test/reports/TEST-HammerCLI-Output-Adapter-Table-print-collection-column-width.xml +0 -15
- data/test/reports/TEST-HammerCLI-Output-Adapter-Table-print-collection-formatters.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Adapter-Table-print-collection-handle-ids.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Adapter-Table-print-collection-sort-columns.xml +0 -9
- data/test/reports/TEST-HammerCLI-Output-Adapter-Table-print-collection.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Adapter-Table.xml +0 -7
- data/test/reports/TEST-HammerCLI-Output-Definition-empty-.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Definition.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Dsl-collection.xml +0 -13
- data/test/reports/TEST-HammerCLI-Output-Dsl-custom-fields.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Dsl-fields.xml +0 -15
- data/test/reports/TEST-HammerCLI-Output-Dsl-label.xml +0 -13
- data/test/reports/TEST-HammerCLI-Output-Dsl-path-definition.xml +0 -13
- data/test/reports/TEST-HammerCLI-Output-Dsl.xml +0 -9
- data/test/reports/TEST-HammerCLI-Output-FieldFilter.xml +0 -13
- data/test/reports/TEST-HammerCLI-Output-Formatters-BooleanFormatter.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Formatters-ColorFormatter.xml +0 -9
- data/test/reports/TEST-HammerCLI-Output-Formatters-DateFormatter.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Formatters-FieldFormatter.xml +0 -13
- data/test/reports/TEST-HammerCLI-Output-Formatters-FormatterContainer.xml +0 -13
- data/test/reports/TEST-HammerCLI-Output-Formatters-FormatterLibrary.xml +0 -11
- data/test/reports/TEST-HammerCLI-Output-Formatters-KeyValueFormatter.xml +0 -13
- data/test/reports/TEST-HammerCLI-Output-Formatters-ListFormatter.xml +0 -13
- data/test/reports/TEST-HammerCLI-Output-Formatters-LongTextFormatter.xml +0 -13
- data/test/reports/TEST-HammerCLI-Output-Output-adapters.xml +0 -17
- data/test/reports/TEST-HammerCLI-Output-Output-data.xml +0 -15
- data/test/reports/TEST-HammerCLI-Output-Output-formatters.xml +0 -9
- data/test/reports/TEST-HammerCLI-Output-Output-messages.xml +0 -19
- data/test/reports/TEST-HammerCLI-Output-Output.xml +0 -7
- data/test/reports/TEST-HammerCLI-Output-RecordCollection.xml +0 -13
- data/test/reports/TEST-HammerCLI-Settings-load-from-paths.xml +0 -15
- data/test/reports/TEST-HammerCLI-Settings.xml +0 -25
- data/test/reports/TEST-HammerCLI-ShellHistory-loading-old-history.xml +0 -11
- data/test/reports/TEST-HammerCLI-ShellHistory-saving-history.xml +0 -15
- data/test/reports/TEST-HammerCLI-ShellHistory.xml +0 -7
- data/test/reports/TEST-MiniTest-Spec.xml +0 -7
- data/test/reports/TEST-String-camelize.xml +0 -11
- data/test/reports/TEST-String-formatting.xml +0 -17
- data/test/reports/TEST-String-indent.xml +0 -11
- data/test/reports/TEST-String-interactive-.xml +0 -13
- data/test/reports/TEST-String.xml +0 -7
- data/test/reports/TEST-constraints-HammerCLI-Validator-AllConstraint-exist-.xml +0 -13
- data/test/reports/TEST-constraints-HammerCLI-Validator-AllConstraint.xml +0 -7
- data/test/reports/TEST-constraints-HammerCLI-Validator-AnyConstraint-exist-.xml +0 -13
- data/test/reports/TEST-constraints-HammerCLI-Validator-AnyConstraint.xml +0 -7
- data/test/reports/TEST-constraints-HammerCLI-Validator-BaseConstraint-exist-.xml +0 -9
- data/test/reports/TEST-constraints-HammerCLI-Validator-BaseConstraint-rejected.xml +0 -13
- data/test/reports/TEST-constraints-HammerCLI-Validator-BaseConstraint-required.xml +0 -13
- data/test/reports/TEST-constraints-HammerCLI-Validator-BaseConstraint.xml +0 -7
- data/test/reports/TEST-constraints.xml +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 230906bc19a41759805ad05e51cee6244938cc5e
|
|
4
|
+
data.tar.gz: 7e4389026de508ce212c3af34823bc1606b6851e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 55c6841e58e1645e48eb83e147d662abc847cf99f18df1f5636b6fb9a09be79e133d99429fa626c3e6ca2456003091e7e74f2813ac43dc22ee163c0f2862b54d
|
|
7
|
+
data.tar.gz: ddeec7d17a560050722bddc473bbc2ff8bba5e967c3cf3f7772249fcf300ca38d03db2f5d8d75df0be5e1b10025eafeef257bf4b8ca5280d71720537ea0e6a0f
|
data/bin/hammer
CHANGED
|
@@ -125,7 +125,7 @@ require 'hammer_cli'
|
|
|
125
125
|
|
|
126
126
|
if preparser.fetch_ca_cert
|
|
127
127
|
require 'hammer_cli/ca_cert_fetcher'
|
|
128
|
-
ca_path = HammerCLI::SSLOptions.
|
|
128
|
+
ca_path = HammerCLI::SSLOptions.new.get_local_ca_store_path
|
|
129
129
|
exit HammerCLI::CACertFetcher.new.fetch_ca_cert(preparser.fetch_ca_cert, ca_path)
|
|
130
130
|
end
|
|
131
131
|
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
#:ssl_ca_file: '/path/to/ca_certificate.pem'
|
|
39
39
|
|
|
40
40
|
# Path to a direcotry with ca file
|
|
41
|
-
#:ssl_ca_path: '
|
|
41
|
+
#:ssl_ca_path: '/path/to/ca'
|
|
42
42
|
|
|
43
43
|
# Turn SSL verification on/off
|
|
44
44
|
#:verify_ssl: true
|
|
@@ -51,3 +51,6 @@
|
|
|
51
51
|
|
|
52
52
|
# Enable standard authentication in addition to client certificate authentication
|
|
53
53
|
#:ssl_with_basic_auth: true
|
|
54
|
+
|
|
55
|
+
# local CA cert store path
|
|
56
|
+
#:local_ca_store_path: '~/.hammer/certs'
|
data/doc/release_notes.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
Release notes
|
|
2
2
|
=============
|
|
3
3
|
|
|
4
|
+
### 0.10.2 (2017-05-05)
|
|
5
|
+
* Retry command on session expiry ([#19431](http://projects.theforeman.org/issues/19431))
|
|
6
|
+
* Prevent fetching of non-CA certificates ([#19391](http://projects.theforeman.org/issues/19391))
|
|
7
|
+
* Use local ca cert store instead of ssl_ca_path ([#19390](http://projects.theforeman.org/issues/19390))
|
|
8
|
+
|
|
4
9
|
### 0.10.1 (2017-04-24)
|
|
5
10
|
* Require apipie-bindings >= 0.2.0 ([#19083](http://projects.theforeman.org/issues/19083))
|
|
6
11
|
* Install server CA cert without root access ([#19083](http://projects.theforeman.org/issues/19083))
|
data/lib/hammer_cli/abstract.rb
CHANGED
|
@@ -24,11 +24,16 @@ module HammerCLI
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def run(arguments)
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
begin
|
|
28
|
+
begin
|
|
29
|
+
exit_code = super
|
|
30
|
+
raise "exit code must be integer" unless exit_code.is_a? Integer
|
|
31
|
+
rescue => e
|
|
32
|
+
exit_code = handle_exception(e)
|
|
33
|
+
end
|
|
34
|
+
logger.debug 'Retrying the command' if (exit_code == HammerCLI::EX_RETRY)
|
|
35
|
+
end while (exit_code == HammerCLI::EX_RETRY)
|
|
29
36
|
return exit_code
|
|
30
|
-
rescue => e
|
|
31
|
-
handle_exception e
|
|
32
37
|
end
|
|
33
38
|
|
|
34
39
|
def parse(arguments)
|
|
@@ -7,7 +7,7 @@ module HammerCLI::Apipie
|
|
|
7
7
|
|
|
8
8
|
def initialize(params, options = {})
|
|
9
9
|
@logger = options[:logger]
|
|
10
|
-
@api = ApipieBindings::API.new(params, HammerCLI::SSLOptions.get_options)
|
|
10
|
+
@api = ApipieBindings::API.new(params, HammerCLI::SSLOptions.new.get_options(params[:uri]))
|
|
11
11
|
if options[:reload_cache]
|
|
12
12
|
@api.clean_cache
|
|
13
13
|
@logger.debug 'Apipie cache was cleared' unless @logger.nil?
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
require 'hammer_cli/ca_cert_manager'
|
|
2
2
|
module HammerCLI
|
|
3
3
|
class CACertFetcher
|
|
4
|
-
def fetch_ca_cert(service_uri,
|
|
4
|
+
def fetch_ca_cert(service_uri, ca_store_path)
|
|
5
5
|
begin
|
|
6
6
|
uri = URI.parse(service_uri)
|
|
7
7
|
raise URI::InvalidURIError.new(_("Unable to find hostname in #{service_uri}")) if uri.host.nil?
|
|
8
8
|
raise URI::InvalidURIError.new(scheme_error(uri)) unless uri.scheme == 'https'
|
|
9
|
-
ca_cert_manager = HammerCLI::CACertManager.new(
|
|
10
|
-
raw_cert = HammerCLI::
|
|
9
|
+
ca_cert_manager = HammerCLI::CACertManager.new(ca_store_path)
|
|
10
|
+
raw_cert = HammerCLI::CertDownloader.new.download(uri)
|
|
11
11
|
cert_file = ca_cert_manager.cert_file_name(uri)
|
|
12
12
|
ca_cert_manager.store_ca_cert(raw_cert, cert_file)
|
|
13
13
|
|
|
@@ -17,8 +17,9 @@ module HammerCLI
|
|
|
17
17
|
deb_update_cmd = "update-ca-certificates"
|
|
18
18
|
cert_file = ca_cert_manager.cert_file_name(uri)
|
|
19
19
|
|
|
20
|
-
puts _("CA certificate for
|
|
20
|
+
puts _("CA certificate for %{uri} was stored to %{file}") % {:uri => service_uri, :file => cert_file}
|
|
21
21
|
puts _("Now hammer can use the downloaded certificate to verify SSL connection to the server.")
|
|
22
|
+
puts _("It will be used automatically when ssl_ca_path and ssl_ca_file options are not set.")
|
|
22
23
|
puts
|
|
23
24
|
puts _("Be aware that hammer cannot verify whether the certificate is correct and you should verify its authenticity.")
|
|
24
25
|
puts
|
|
@@ -44,6 +45,16 @@ module HammerCLI
|
|
|
44
45
|
$stderr.puts _("Couldn't parse URI '%s'.") % service_uri
|
|
45
46
|
$stderr.puts e.message
|
|
46
47
|
return HammerCLI::EX_SOFTWARE
|
|
48
|
+
rescue HammerCLI::NoCACertificate => e
|
|
49
|
+
$stderr.puts _("The CA certificate for %{uri} couldn't be downloaded. No CA cert was found.") % {:uri => service_uri}
|
|
50
|
+
$stderr.puts
|
|
51
|
+
$stderr.puts _("Make sure your server sends cert chain including the CA.")
|
|
52
|
+
$stderr.puts _("To see the actual chain you can use openssl command")
|
|
53
|
+
$stderr.puts " $ openssl s_client -showcerts -connect #{uri.host}:#{uri.port} </dev/null"
|
|
54
|
+
$stderr.puts
|
|
55
|
+
$stderr.puts _("You can also download the certificate manually and store it as #{cert_file}")
|
|
56
|
+
$stderr.puts _("If you choose any other location set the ssl_ca_path or ssl_ca_file configuration options appropriately.")
|
|
57
|
+
return HammerCLI::EX_SOFTWARE
|
|
47
58
|
rescue StandardError => e
|
|
48
59
|
logger = Logging.logger['CACertFetcher']
|
|
49
60
|
msg = [_('Fetching the CA certificate failed:')]
|
|
@@ -2,58 +2,43 @@ require 'fileutils'
|
|
|
2
2
|
|
|
3
3
|
module HammerCLI
|
|
4
4
|
class CACertManager
|
|
5
|
-
attr_reader :
|
|
5
|
+
attr_reader :ca_store_path
|
|
6
6
|
|
|
7
|
-
def initialize(
|
|
8
|
-
@
|
|
7
|
+
def initialize(ca_store_path)
|
|
8
|
+
@ca_store_path = File.expand_path(ca_store_path)
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def store_ca_cert(raw_cert, cert_file)
|
|
12
|
-
|
|
12
|
+
raise HammerCLI::NoCACertificate.new unless is_ca_cert?(raw_cert)
|
|
13
|
+
ensure_ca_store_exist
|
|
13
14
|
File.write(cert_file, raw_cert)
|
|
14
|
-
hash = cert_hash(raw_cert)
|
|
15
|
-
create_link(hash, cert_file)
|
|
16
15
|
cert_file
|
|
17
16
|
end
|
|
18
17
|
|
|
19
|
-
def
|
|
20
|
-
|
|
21
|
-
subject = OpenSSL::X509::Name.new(cert.subject)
|
|
22
|
-
subject.hash
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def create_link(hash, cert_file)
|
|
26
|
-
ensure_ca_path_exist
|
|
27
|
-
cert_link = File.join(ca_path, "#{hash.to_s(16)}.%s")
|
|
28
|
-
count = 0
|
|
29
|
-
# increase hash index if file or link to different target already exist
|
|
30
|
-
while plain_file?(cert_link % count) || link_to_different_target?(cert_link % count, cert_file) do
|
|
31
|
-
count += 1
|
|
32
|
-
end
|
|
33
|
-
File.symlink(cert_file, cert_link % count) unless File.symlink?(cert_link % count)
|
|
18
|
+
def cert_file_name(uri)
|
|
19
|
+
File.join(ca_store_path, "#{uri.host}_#{uri.port}.pem")
|
|
34
20
|
end
|
|
35
21
|
|
|
36
|
-
def
|
|
37
|
-
File.
|
|
22
|
+
def cert_exist?(uri)
|
|
23
|
+
File.exist?(cert_file_name(uri))
|
|
38
24
|
end
|
|
39
25
|
|
|
40
26
|
protected
|
|
41
27
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
FileUtils.mkpath(ca_path) unless File.directory?(ca_path)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def plain_file?(path)
|
|
48
|
-
File.exist?(path) && !File.symlink?(path)
|
|
28
|
+
def ensure_ca_store_exist
|
|
29
|
+
FileUtils.mkpath(ca_store_path) unless File.directory?(ca_store_path)
|
|
49
30
|
end
|
|
50
31
|
|
|
51
|
-
def
|
|
52
|
-
|
|
32
|
+
def is_ca_cert?(cert)
|
|
33
|
+
cert = OpenSSL::X509::Certificate.new(cert) if cert.is_a? String
|
|
34
|
+
cert.extensions.any? do |ex|
|
|
35
|
+
(ex.oid == 'basicConstraints' && ex.value.upcase == 'CA:TRUE') ||
|
|
36
|
+
(ex.oid == 'keyUsage' && ex.value =~ /Cert(ificate )?Sign/i)
|
|
37
|
+
end
|
|
53
38
|
end
|
|
54
39
|
end
|
|
55
40
|
|
|
56
|
-
class
|
|
41
|
+
class CertDownloader
|
|
57
42
|
def download(uri)
|
|
58
43
|
noverify_ssl_connection = OpenSSL::SSL::SSLSocket.new(TCPSocket.new(uri.host, uri.port), noverify_ssl_context)
|
|
59
44
|
noverify_ssl_connection.connect
|
|
@@ -4,7 +4,7 @@ module HammerCLI
|
|
|
4
4
|
EX_USAGE = 64 # command line usage error
|
|
5
5
|
EX_DATAERR = 65 # data format error
|
|
6
6
|
EX_NOINPUT = 66 # cannot open input
|
|
7
|
-
EX_NOUSER = 67 # addressee unknown
|
|
7
|
+
EX_NOUSER = 67 # addressee unknown
|
|
8
8
|
EX_NOHOST = 68 # host name unknown
|
|
9
9
|
EX_UNAVAILABLE = 69 # service unavailable
|
|
10
10
|
EX_SOFTWARE = 70 # internal software error
|
|
@@ -20,4 +20,5 @@ module HammerCLI
|
|
|
20
20
|
# non POSIX codes
|
|
21
21
|
EX_NOT_FOUND = 128 # resource was not found
|
|
22
22
|
EX_UNAUTHORIZED = 129 # authorization failed
|
|
23
|
+
EX_RETRY = 666 # retry the command
|
|
23
24
|
end
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
module HammerCLI
|
|
2
2
|
class SSLOptions
|
|
3
|
-
|
|
3
|
+
DEFAULT_LOCAL_CA_STORE_PATH = "~/.hammer/certs"
|
|
4
4
|
|
|
5
|
-
def initialize(
|
|
6
|
-
@settings = settings
|
|
7
|
-
@logger = logger
|
|
5
|
+
def initialize(options={})
|
|
6
|
+
@settings = options.fetch(:settings, HammerCLI::Settings)
|
|
7
|
+
@logger = options.fetch(:logger, Logging.logger['SSLoptions'])
|
|
8
|
+
@ca_manager = options.fetch(:ca_manager, HammerCLI::CACertManager.new(DEFAULT_LOCAL_CA_STORE_PATH))
|
|
8
9
|
end
|
|
9
10
|
|
|
10
|
-
def
|
|
11
|
-
|
|
11
|
+
def get_local_ca_store_path
|
|
12
|
+
@settings.get(:ssl, :local_ca_store_path) || DEFAULT_LOCAL_CA_STORE_PATH
|
|
12
13
|
end
|
|
13
14
|
|
|
14
|
-
def get_options
|
|
15
|
+
def get_options(uri = nil)
|
|
15
16
|
ssl_options = {}
|
|
16
17
|
for sslopt in [:ssl_ca_file, :ssl_ca_path, :verify_ssl] do
|
|
17
18
|
ssloptval = read_ssl_option(sslopt)
|
|
@@ -19,13 +20,21 @@ module HammerCLI
|
|
|
19
20
|
end
|
|
20
21
|
ssl_options.merge!(cert_key_options)
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
# enable ssl verification
|
|
24
|
+
ssl_options[:verify_ssl] = true if ssl_options[:verify_ssl].nil?
|
|
25
|
+
|
|
26
|
+
if ssl_options[:verify_ssl] && uri && !ssl_options[:ssl_ca_file] && !ssl_options[:ssl_ca_path]
|
|
27
|
+
uri = URI.parse(uri) if uri.is_a?(String)
|
|
28
|
+
if @ca_manager.cert_exist?(uri)
|
|
29
|
+
ssl_options[:ssl_ca_file] = @ca_manager.cert_file_name(uri)
|
|
30
|
+
@logger.info("Matching CA cert was found in local CA store #{ssl_options[:ssl_ca_file]}")
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
23
34
|
[:ssl_ca_file, :ssl_ca_path].each do |opt|
|
|
24
35
|
ssl_options[opt] = File.expand_path(ssl_options[opt]) unless ssl_options[opt].nil?
|
|
25
36
|
end
|
|
26
37
|
|
|
27
|
-
# enable ssl verification
|
|
28
|
-
ssl_options[:verify_ssl] = true if ssl_options[:verify_ssl].nil?
|
|
29
38
|
@logger.debug("SSL options: #{ApipieBindings::Utils::inspect_data(ssl_options)}")
|
|
30
39
|
ssl_options
|
|
31
40
|
end
|
data/lib/hammer_cli/version.rb
CHANGED
data/lib/hammer_cli.rb
CHANGED
data/man/hammer.1.gz
CHANGED
|
Binary file
|
|
@@ -10,7 +10,6 @@ describe HammerCLI::Apipie::ApiConnection do
|
|
|
10
10
|
def api_stub(params = {}, options = {})
|
|
11
11
|
api_stub = stub()
|
|
12
12
|
options[:verify_ssl] = true if options[:verify_ssl].nil?
|
|
13
|
-
options[:ssl_ca_path] = File.expand_path(HammerCLI::SSLOptions::DEFAULT_SSL_CA_PATH) if options[:ssl_ca_path].nil?
|
|
14
13
|
ApipieBindings::API.expects(:new).with(params, options).returns(api_stub)
|
|
15
14
|
api_stub
|
|
16
15
|
end
|
|
@@ -6,59 +6,49 @@ require 'hammer_cli/ca_cert_manager'
|
|
|
6
6
|
describe HammerCLI::CACertManager do
|
|
7
7
|
|
|
8
8
|
before(:all) do
|
|
9
|
-
@
|
|
9
|
+
@ca_store_path = Dir.mktmpdir('ca_cert_manager')
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
after(:all) do
|
|
13
|
-
FileUtils.rm_rf(@
|
|
13
|
+
FileUtils.rm_rf(@ca_store_path) if File.exist?(@ca_store_path)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
let(:service_uri) { URI.parse("https://test.host.com") }
|
|
17
|
-
let(:ca_cert_manager) { HammerCLI::CACertManager.new(@
|
|
17
|
+
let(:ca_cert_manager) { HammerCLI::CACertManager.new(@ca_store_path) }
|
|
18
18
|
let(:cert_file) { ca_cert_manager.cert_file_name(service_uri) }
|
|
19
|
+
let(:ca_cert_fixture) { File.join(File.dirname(__FILE__), '/fixtures/certs/ca_cert.pem') }
|
|
20
|
+
let(:non_ca_cert_fixture) { File.join(File.dirname(__FILE__), '/fixtures/certs/non_ca_cert.pem') }
|
|
19
21
|
|
|
20
22
|
describe '#store_ca_cert' do
|
|
21
|
-
let(:cert_fixture) { File.join(File.dirname(__FILE__), '/fixtures/certs/ca_cert.pem') }
|
|
22
|
-
|
|
23
23
|
it 'stores ca cert' do
|
|
24
|
-
new_cert_file = ca_cert_manager.store_ca_cert(File.read(
|
|
25
|
-
assert File.exist?(File.join(@ca_path, "2c543cd1.0"))
|
|
24
|
+
new_cert_file = ca_cert_manager.store_ca_cert(File.read(ca_cert_fixture), cert_file)
|
|
26
25
|
assert File.exist?(cert_file)
|
|
27
26
|
assert_equal cert_file, new_cert_file
|
|
28
27
|
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
describe '#create_link' do
|
|
32
|
-
let(:hash) { 123456789 }
|
|
33
|
-
let(:hash_file) { hash.to_s(16) }
|
|
34
28
|
|
|
35
|
-
it
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
it 'refuses non-CA cert' do
|
|
30
|
+
assert_raises HammerCLI::NoCACertificate do
|
|
31
|
+
ca_cert_manager.store_ca_cert(File.read(non_ca_cert_fixture), cert_file)
|
|
32
|
+
end
|
|
39
33
|
end
|
|
34
|
+
end
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
ca_cert_manager.
|
|
44
|
-
|
|
45
|
-
assert File.exist?(File.join(@ca_path, "#{hash_file}.0"))
|
|
36
|
+
describe '#cert_exist?' do
|
|
37
|
+
it 'return true if the cert exist' do
|
|
38
|
+
ca_cert_manager.store_ca_cert(File.read(ca_cert_fixture), cert_file)
|
|
39
|
+
assert ca_cert_manager.cert_exist?(service_uri)
|
|
46
40
|
end
|
|
47
41
|
|
|
48
|
-
it
|
|
49
|
-
|
|
50
|
-
File.symlink(cert_file, File.join(@ca_path, "#{hash_file}.0"))
|
|
51
|
-
ca_cert_manager.create_link(hash, cert_file)
|
|
52
|
-
assert File.exist?(File.join(@ca_path, "#{hash_file}.0"))
|
|
53
|
-
refute File.exist?(File.join(@ca_path, "#{hash_file}.1"))
|
|
42
|
+
it 'return false if the cert does not exist' do
|
|
43
|
+
refute ca_cert_manager.cert_exist?(service_uri)
|
|
54
44
|
end
|
|
45
|
+
end
|
|
55
46
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
ca_cert_manager.
|
|
60
|
-
|
|
61
|
-
assert File.exist?(File.join(@ca_path, "#{hash_file}.1"))
|
|
47
|
+
describe '#cert_file_name' do
|
|
48
|
+
it 'make file name from host uri' do
|
|
49
|
+
uri = URI.parse("https://test.example.com:1111")
|
|
50
|
+
filename = ca_cert_manager.cert_file_name(uri)
|
|
51
|
+
assert_equal File.join(ca_cert_manager.ca_store_path,'test.example.com_1111.pem'), filename
|
|
62
52
|
end
|
|
63
53
|
end
|
|
64
54
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIEgDCCA2igAwIBAgIIdKMhNG6e8c4wDQYJKoZIhvcNAQELBQAwSTELMAkGA1UE
|
|
3
|
+
BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl
|
|
4
|
+
cm5ldCBBdXRob3JpdHkgRzIwHhcNMTcwNDEyMTMyODAwWhcNMTcwNzA1MTMyODAw
|
|
5
|
+
WjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwN
|
|
6
|
+
TW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UEAwwOd3d3
|
|
7
|
+
Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDI5ZXl
|
|
8
|
+
lffcMQiwJGs2CxZToWbi16Q7LL6H8y3xuRwDn//gp8qX8Jcv4x7KG4aEipB8wOUm
|
|
9
|
+
jrZs2Q1BT8VIqfQLLqhSrP61LZfuAzv/v1WAw7CmtvqCH91qKM/SkOXyCJK1Cf2/
|
|
10
|
+
+i5oLoY2NnxV7iM7+tidPSF4ZPMjtb13ABVcdr49lDlSZce8YXDoWtlr9hjfAPEF
|
|
11
|
+
mzxlSsA5gPv/BNUhgW8Rna3UWwl4jgKAFOgLybKTharhnEl14cYUeDJ/HnGLc8L1
|
|
12
|
+
6es05HjHsz6J3jpXi9x0X1b5lQfeEFYLBPQ3nPjGgOZvECLLl8esBkpAWy+BLGd0
|
|
13
|
+
vPYRWZnnnOU3+i33AgMBAAGjggFLMIIBRzAdBgNVHSUEFjAUBggrBgEFBQcDAQYI
|
|
14
|
+
KwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYBBQUHAQEE
|
|
15
|
+
XDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3J0
|
|
16
|
+
MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9vY3NwMB0G
|
|
17
|
+
A1UdDgQWBBRfEHz1zg9lsVjVptJ9ncVQH7wzIzAMBgNVHRMBAf8EAjAAMB8GA1Ud
|
|
18
|
+
IwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMCEGA1UdIAQaMBgwDAYKKwYBBAHW
|
|
19
|
+
eQIFATAIBgZngQwBAgIwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL3BraS5nb29n
|
|
20
|
+
bGUuY29tL0dJQUcyLmNybDANBgkqhkiG9w0BAQsFAAOCAQEAgo6rk/60YN5JYhPO
|
|
21
|
+
oBm3nTawx+0FW/rFh6tEsxUl2x6d6eYN/W95Wx2ofJFTe0blC5W40GHyFjuGoEGb
|
|
22
|
+
7soS+gUMsMNb1oiz8osD/OOce70afUcGMSB1qEXC2Q7plCqnJSTDIEsO1r7O0Y6n
|
|
23
|
+
JUqvdrB/LqihaKYnYKsSM6ya+i3fX55KfamkqeRmDIVOspDNcy8zl+EbAX3sJk3j
|
|
24
|
+
k2bitWNktp37t+suGhimvmOVaP/EVRMl8z5RUrNTi8q2M1BzDOZD5k/Hhxy1UFpr
|
|
25
|
+
QwHC6MuyOpgKBIHQguLvzD2I3dyK1GzzsfiyYx3eCJVq4f5iAfSkaxf8spWIhIRo
|
|
26
|
+
YgQaig==
|
|
27
|
+
-----END CERTIFICATE-----
|