WIP - v4 - rewrite to be feature complete
diff --git a/.fixtures-puppetv3.yml b/.fixtures-puppetv3.yml deleted file mode 100644 index e8a1576..0000000 --- a/.fixtures-puppetv3.yml +++ /dev/null
@@ -1,16 +0,0 @@ -fixtures: - repositories: - stdlib: - repo: 'https://github.com/puppetlabs/puppetlabs-stdlib.git' - ref: '4.6.0' - concat: - repo: 'https://github.com/puppetlabs/puppetlabs-concat.git' - ref: '2.2.1' - common: - repo: 'https://github.com/ghoneycutt/puppet-module-common.git' - ref: 'v1.4.1' - firewall: - repo: 'https://github.com/puppetlabs/puppetlabs-firewall.git' - ref: '1.9.0' - symlinks: - ssh: "#{source_dir}"
diff --git a/.fixtures.yml b/.fixtures.yml index 91a33d7..d0917ee 100644 --- a/.fixtures.yml +++ b/.fixtures.yml
@@ -2,18 +2,11 @@ repositories: stdlib: repo: 'https://github.com/puppetlabs/puppetlabs-stdlib.git' - ref: '4.6.0' + ref: '5.2.0' concat: repo: 'https://github.com/puppetlabs/puppetlabs-concat.git' - ref: '2.2.1' - common: - repo: 'https://github.com/ghoneycutt/puppet-module-common.git' - ref: 'v1.4.1' - firewall: - repo: 'https://github.com/puppetlabs/puppetlabs-firewall.git' - ref: '1.9.0' + ref: '5.2.0' sshkeys: - repo: 'git://github.com/puppetlabs/puppetlabs-sshkeys_core.git' - ref: '1.0.1' - symlinks: - ssh: "#{source_dir}" + repo: 'https://github.com/puppetlabs/puppetlabs-sshkeys_core.git' + ref: '1.0.2' + puppet_version: '>= 6.0.0'
diff --git a/.gitignore b/.gitignore index 29471a6..178b162 100644 --- a/.gitignore +++ b/.gitignore
@@ -12,6 +12,7 @@ test/tmp test/version_tmp tmp +Gemfile.lock # YARD artifacts .yardoc @@ -31,7 +32,10 @@ coverage/ spec/fixtures/manifests/* spec/fixtures/modules/* -Gemfile.lock +log/ + +# Vagrant +.vagrant/* # JetBrains IDE .idea/
diff --git a/.puppet-lint.rc b/.puppet-lint.rc new file mode 100644 index 0000000..f7e6028 --- /dev/null +++ b/.puppet-lint.rc
@@ -0,0 +1,3 @@ +--no-relative +--no-80chars-check +--no-140chars-check
diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..bab9844 --- /dev/null +++ b/.rubocop.yml
@@ -0,0 +1,151 @@ +--- +require: rubocop-rspec +AllCops: + DisplayCopNames: true + TargetRubyVersion: '2.1' + Include: + - "./**/*.rb" + Exclude: + - bin/* + - ".vendor/**/*" + - "**/Gemfile" + - "**/Rakefile" + - pkg/**/* + - spec/fixtures/**/* + - vendor/**/* + - "**/Puppetfile" + - "**/Vagrantfile" + - "**/Guardfile" +Metrics/LineLength: + Description: People have wide screens, use them. + Max: 200 +GetText/DecorateString: + Description: We don't want to decorate test output. + Exclude: + - spec/* +RSpec/BeforeAfterAll: + Description: Beware of using after(:all) as it may cause state to leak between tests. + A necessary evil in acceptance testing. + Exclude: + - spec/acceptance/**/*.rb +RSpec/HookArgument: + Description: Prefer explicit :each argument, matching existing module's style + EnforcedStyle: each + Enabled: false +Style/BlockDelimiters: + Description: Prefer braces for chaining. Mostly an aesthetical choice. Better to + be consistent then. + EnforcedStyle: braces_for_chaining +Style/ClassAndModuleChildren: + Description: Compact style reduces the required amount of indentation. + EnforcedStyle: compact +Style/EmptyElse: + Description: Enforce against empty else clauses, but allow `nil` for clarity. + EnforcedStyle: empty +Style/FormatString: + Description: Following the main puppet project's style, prefer the % format format. + EnforcedStyle: percent +Style/FormatStringToken: + Description: Following the main puppet project's style, prefer the simpler template + tokens over annotated ones. + EnforcedStyle: template +Style/Lambda: + Description: Prefer the keyword for easier discoverability. + EnforcedStyle: literal +Style/RegexpLiteral: + Description: Community preference. See https://github.com/voxpupuli/modulesync_config/issues/168 + EnforcedStyle: percent_r + Enabled: false +Style/TernaryParentheses: + Description: Checks for use of parentheses around ternary conditions. Enforce parentheses + on complex expressions for better readability, but seriously consider breaking + it up. + EnforcedStyle: require_parentheses_when_complex +Style/TrailingCommaInArguments: + Description: Prefer always trailing comma on multiline argument lists. This makes + diffs, and re-ordering nicer. + EnforcedStyleForMultiline: comma +Style/TrailingCommaInLiteral: + Description: Prefer always trailing comma on multiline literals. This makes diffs, + and re-ordering nicer. + EnforcedStyleForMultiline: comma + Enabled: false +Style/SymbolArray: + Description: Using percent style obscures symbolic intent of array's contents. + EnforcedStyle: brackets +Layout/AlignHash: + Enabled: false +Layout/IndentationConsistency: + Enabled: false +Layout/IndentHash: + Enabled: false +Layout/SpaceAfterNot: + Enabled: false +Layout/SpaceInsideParens: + Enabled: false +RSpec/EmptyLineAfterFinalLet: + Enabled: false +RSpec/ExampleWording: + Enabled: false +RSpec/ImplicitExpect: + Enabled: false +RSpec/NamedSubject: + Enabled: false +Style/AndOr: + Enabled: false +Style/BracesAroundHashParameters: + Enabled: false +Style/HashSyntax: + Enabled: false +Style/NegatedIf: + Enabled: false +RSpec/MessageSpies: + EnforcedStyle: receive +Style/Documentation: + Exclude: + - lib/puppet/parser/functions/**/* + - spec/**/* +Style/WordArray: + EnforcedStyle: brackets +Style/CollectionMethods: + Enabled: true +Style/MethodCalledOnDoEndBlock: + Enabled: true +Style/StringMethods: + Enabled: true +Layout/EndOfLine: + Enabled: false +Layout/IndentHeredoc: + Enabled: false +Metrics/AbcSize: + Enabled: false +Metrics/BlockLength: + Enabled: false +Metrics/ClassLength: + Enabled: false +Metrics/CyclomaticComplexity: + Enabled: false +Metrics/MethodLength: + Enabled: false +Metrics/ModuleLength: + Enabled: false +Metrics/ParameterLists: + Enabled: false +Metrics/PerceivedComplexity: + Enabled: false +RSpec/DescribeClass: + Enabled: false +RSpec/ExampleLength: + Enabled: false +RSpec/MessageExpectation: + Enabled: false +RSpec/MultipleExpectations: + Enabled: false +RSpec/NestedGroups: + Enabled: false +Style/AsciiComments: + Enabled: false +Style/IfUnlessModifier: + Enabled: false +Style/SymbolProc: + Enabled: false
diff --git a/.travis.yml b/.travis.yml index 0650a11..bf14b20 100644 --- a/.travis.yml +++ b/.travis.yml
@@ -15,29 +15,39 @@ sudo: false -script: 'SPEC_OPTS="--format documentation" bundle exec rake validate lint spec' +script: 'SPEC_OPTS="--format documentation" bundle exec rake validate lint strings:generate reference spec' matrix: fast_finish: true include: - - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3 - - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" FUTURE_PARSER="yes" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3 - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3 - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" FUTURE_PARSER="yes" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3 - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3 - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 3" FIXTURES_YML=".fixtures-puppetv3.yml" FUTURE_PARSER="yes" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3 - - rvm: 2.1.9 - env: PUPPET_GEM_VERSION="~> 4" RUBYGEMS_VERSION=2.7.8 BUNDLER_VERSION=1.17.3 - - rvm: 2.4.1 + - rvm: 2.4.4 env: PUPPET_GEM_VERSION="~> 5" - - rvm: 2.5.1 + - rvm: 2.5.3 env: PUPPET_GEM_VERSION="~> 6" + - rvm: 2.4.4 + sudo: required + services: docker + env: BEAKER_set="centos-6" BEAKER_PUPPET_COLLECTION=puppet5 + bundler_args: + script: bundle exec rake beaker + - rvm: 2.5.3 + sudo: required + services: docker + env: BEAKER_set="centos-6" BEAKER_PUPPET_COLLECTION=puppet6 + bundler_args: + script: bundle exec rake beaker + - rvm: 2.4.4 + sudo: required + services: docker + env: BEAKER_set="centos-7" BEAKER_PUPPET_COLLECTION=puppet5 + bundler_args: + script: bundle exec rake beaker + - rvm: 2.5.3 + sudo: required + services: docker + env: BEAKER_set="centos-7" BEAKER_PUPPET_COLLECTION=puppet6 + bundler_args: + script: bundle exec rake beaker notifications: email: false
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..be75c27 --- /dev/null +++ b/CONTRIBUTING.md
@@ -0,0 +1,55 @@ +# Contribution Guidelines + +## Tests + + - Pull requests that add any additional functionality should have + tests which cover the new feature to ensure it does what is +expected. + + - All platforms must have spec tests. + + - Only supported platforms will run functional tests with Beaker and + Vagrant. Once a platform is end of life (EOL), it will no longer + be supported and functional tests will be removed, though spec + tests will remain. + + - Pull requests with failing tests will not be merged. + +## Features + + - Keep feature based PRs as small as possible, with as few commits as + necessary. These are easier to review and will be merged quicker. + +## Bug Fixes + + - Make sure you reference the issue you're closing with `Fixes #<issue + number>`. + +## Commits + + - Squash/rebase any commits where possible to reduce the noise in the PR + +## Git commits + +Reference the issue number, in the format `(GH-###)`. + +``` +(GH-901) Add support for foo +``` + +# Release process + +1. update version in `metadata.json` +1. run `github_changelog_generator` +1. update `CHANGELOG.md` and change `unreleased` at the top to the + version, such as `v2.0.0`, and change `HEAD` to the same version, + such as `v2.0.0`. +1. Update `REFERENCE.md` with the command `bundle exec rake reference` +1. Commit changes and push to master +1. Tag the new version, such as `git tag -a 'v2.0.0' -m 'v2.0.0'` +1. Push tags `git push --tags` +1. Update the puppet strings documentation with `bundle exec rake strings:gh_pages:update` +1. Clean up tests with `bundle exec rake spec_clean` +1. Remove junit directory from beaker runs `rm -fr junit` +1. Build module with `puppet module build` +1. Upload module to Puppet Forge.
diff --git a/Gemfile b/Gemfile index f8bdb02..0f45b5c 100644 --- a/Gemfile +++ b/Gemfile
@@ -6,33 +6,35 @@ gem 'puppet', :require => false end -gem 'facter', '>= 1.7.0', :require => false -gem 'rspec-puppet', '>= 2.4.0', :require => false -gem 'puppet-lint', '~> 2.0', :require => false -gem 'puppet-lint-absolute_classname-check', :require => false -gem 'puppet-lint-alias-check', :require => false -gem 'puppet-lint-empty_string-check', :require => false -gem 'puppet-lint-file_ensure-check', :require => false -gem 'puppet-lint-file_source_rights-check', :require => false -gem 'puppet-lint-leading_zero-check', :require => false +gem 'rake' +gem 'metadata-json-lint', :require => false +gem 'puppetlabs_spec_helper', :require => false +gem 'rspec-puppet', :require => false +gem 'puppet-lint', :require => false +gem 'puppet-lint-absolute_classname-check', :require => false +gem 'puppet-lint-alias-check', :require => false +gem 'puppet-lint-empty_string-check', :require => false +gem 'puppet-lint-file_ensure-check', :require => false +gem 'puppet-lint-file_source_rights-check', :require => false +gem 'puppet-lint-leading_zero-check', :require => false gem 'puppet-lint-spaceship_operator_without_tag-check', :require => false -gem 'puppet-lint-trailing_comma-check', :require => false -gem 'puppet-lint-undef_in_function-check', :require => false -gem 'puppet-lint-unquoted_string-check', :require => false -gem 'puppet-lint-variable_contains_upcase', :require => false +gem 'puppet-lint-trailing_comma-check', :require => false +gem 'puppet-lint-undef_in_function-check', :require => false +gem 'puppet-lint-unquoted_string-check', :require => false +gem 'puppet-lint-variable_contains_upcase', :require => false -gem 'rspec', '~> 2.0', :require => false if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9' -gem 'rake', '~> 10.0', :require => false if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9' -gem 'json', '<= 1.8', :require => false if RUBY_VERSION < '2.0.0' -gem 'json_pure', '<= 2.0.1', :require => false if RUBY_VERSION < '2.0.0' -gem 'metadata-json-lint', '0.0.11' if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9' -gem 'metadata-json-lint', '1.0.0' if RUBY_VERSION >= '1.9' && RUBY_VERSION < '2.0' -gem 'metadata-json-lint' if RUBY_VERSION >= '2.0' +group :documentation do + gem 'puppet-strings', require: false + gem 'redcarpet', require: false + gem 'yard', require: false +end -gem 'puppetlabs_spec_helper', '2.0.2', :require => false if RUBY_VERSION >= '1.8.7' && RUBY_VERSION < '1.9' -gem 'puppetlabs_spec_helper', '>= 2.0.0', :require => false if RUBY_VERSION >= '1.9' -gem 'parallel_tests', '<= 2.9.0', :require => false if RUBY_VERSION < '2.0.0' - -if puppetversion && puppetversion < '5.0' - gem 'semantic_puppet', :require => false +group :system_tests do + gem 'beaker', :require => false + gem 'beaker-docker', :require => false + gem 'beaker-module_install_helper', :require => false + gem 'beaker-puppet', :require => false + gem 'beaker-puppet_install_helper', :require => false + gem 'beaker-rspec', :require => false + gem 'serverspec', :require => false end
diff --git a/REFERENCE.md b/REFERENCE.md new file mode 100644 index 0000000..a3e1daa --- /dev/null +++ b/REFERENCE.md
@@ -0,0 +1,1821 @@ +# Reference +<!-- DO NOT EDIT: This document was generated by Puppet Strings --> + +## Table of Contents + +**Classes** + +* [`ssh`](#ssh): Class to manage SSH client +* [`ssh::server`](#sshserver): Class to manage SSH server + +**Defined types** + +* [`ssh::config_entry`](#sshconfig_entry): Create config entries in a users' ~/.ssh/config + +## Classes + +### ssh + +Notes: `Match` and `Host` attributes are not directly supported as multiple +match/host blocks can exist. Use the `custom` parameter for that. + +#### Parameters + +The following parameters are available in the `ssh` class. + +##### `packages` + +Data type: `Variant[String[1], Array[String[1]]]` + + + +Default value: 'openssh-clients' + +##### `package_source` + +Data type: `Optional[Stdlib::Absolutepath]` + + + +Default value: `undef` + +##### `package_adminfile` + +Data type: `Optional[Stdlib::Absolutepath]` + + + +Default value: `undef` + +##### `config_path` + +Data type: `Stdlib::Absolutepath` + + + +Default value: '/etc/ssh/ssh_config' + +##### `config_owner` + +Data type: `String[1]` + + + +Default value: 'root' + +##### `config_group` + +Data type: `String[1]` + + + +Default value: 'root' + +##### `config_mode` + +Data type: `Stdlib::Filemode` + + + +Default value: '0644' + +##### `global_known_hosts` + +Data type: `Stdlib::Absolutepath` + + + +Default value: '/etc/ssh/ssh_known_hosts' + +##### `global_known_hosts_owner` + +Data type: `String[1]` + + + +Default value: 'root' + +##### `global_known_hosts_group` + +Data type: `String[1]` + + + +Default value: 'root' + +##### `global_known_hosts_mode` + +Data type: `Stdlib::Filemode` + + + +Default value: '0644' + +##### `manage_root_ssh_config` + +Data type: `Boolean` + + + +Default value: `false` + +##### `root_ssh_config_content` + +Data type: `String[1]` + + + +Default value: "# This file is being maintained by Puppet.\n# DO NOT EDIT\n" + +##### `manage_server` + +Data type: `Boolean` + + + +Default value: `true` + +##### `key_export` + +Data type: `Boolean` + + + +Default value: `false` + +##### `purge_keys` + +Data type: `Boolean` + + + +Default value: `true` + +##### `ssh_key_ensure` + +Data type: `Enum['present', 'absent']` + + + +Default value: 'present' + +##### `ssh_key_import` + +Data type: `Boolean` + + + +Default value: `false` + +##### `ssh_key_type` + +Data type: `Ssh::Key::Type` + + + +Default value: 'ssh-rsa' + +##### `keys` + +Data type: `Hash` + + + +Default value: `undef` + +##### `config_entries` + +Data type: `Hash` + + + +Default value: {} + +##### `host` + +Data type: `String[1]` + + + +Default value: '*' + +##### `add_keys_to_agent` + +Data type: `Optional[Enum['yes', 'no', 'ask', 'confirm']]` + + + +Default value: `undef` + +##### `address_family` + +Data type: `Optional[Enum['any', 'inet', 'inet6']]` + + + +Default value: `undef` + +##### `batch_mode` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `bind_address` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `bind_interface` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `canonical_domains` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `canonicalize_fallback_local` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `canonicalize_hostname` + +Data type: `Optional[Enum['yes', 'no', 'always']]` + + + +Default value: `undef` + +##### `canonicalize_max_dots` + +Data type: `Optional[Integer[0]]` + + + +Default value: `undef` + +##### `canonicalize_permitted_cnames` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `ca_signature_algorithms` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `certificate_file` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `challenge_response_authentication` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `check_host_ip` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `ciphers` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `clear_all_forwardings` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `compression` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `connection_attempts` + +Data type: `Optional[Integer[0]]` + + + +Default value: `undef` + +##### `connect_timeout` + +Data type: `Optional[Integer[0]]` + + + +Default value: `undef` + +##### `control_master` + +Data type: `Optional[Enum['yes', 'no', 'ask', 'auto', 'autoask']]` + + + +Default value: `undef` + +##### `control_path` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `control_persist` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `dynamic_forward` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `enable_ssh_keysign` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `escape_char` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `exit_on_forward_failure` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `fingerprint_hash` + +Data type: `Optional[Enum['sha256', 'md5']]` + + + +Default value: `undef` + +##### `forward_agent` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `forward_x11` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `forward_x11_timeout` + +Data type: `Variant[Undef, String[1], Integer[0]]` + + + +Default value: `undef` + +##### `forward_x11_trusted` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `gateway_ports` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `global_known_hosts_file` + +Data type: `Variant[Undef, String[1], Array[String[1]]]` + + + +Default value: `undef` + +##### `gss_api_authentication` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `gss_api_delegate_credentials` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `hash_known_hosts` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `hostbased_authentication` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `hostbased_key_types` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `host_key_algorithms` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `host_key_alias` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `host_name` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `identities_only` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `identity_agent` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `identity_file` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `ignore_unknown` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `include` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `ip_qos` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `kbd_interactive_authentication` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `kbd_interactive_devices` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `kex_algorithms` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `local_command` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `local_forward` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `log_level` + +Data type: `Optional[Ssh::Log_level]` + + + +Default value: `undef` + +##### `no_host_authentication_for_localhost` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `number_of_password_prompts` + +Data type: `Optional[Integer]` + + + +Default value: `undef` + +##### `password_authentication` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `permit_local_command` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `pkcs11_provider` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `port` + +Data type: `Optional[Stdlib::Port]` + + + +Default value: `undef` + +##### `preferred_authentications` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `proxy_command` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `proxy_jump` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `proxy_use_fdpass` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `pubkey_accepted_key_types` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `pubkey_authentication` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `rekey_limit` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `remote_command` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `remote_forward` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `request_tty` + +Data type: `Optional[Enum['no', 'yes', 'force', 'auto']]` + + + +Default value: `undef` + +##### `revoked_host_keys` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `send_env` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `server_alive_count_max` + +Data type: `Variant[Undef, String[1], Integer[0]]` + + + +Default value: `undef` + +##### `server_alive_interval` + +Data type: `Variant[Undef, String[1], Integer[0]]` + + + +Default value: `undef` + +##### `set_env` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `stream_local_bind_mask` + +Data type: `Optional[Pattern[/^[0-7]{4}$/]]` + + + +Default value: `undef` + +##### `stream_local_bind_unlink` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `strict_host_key_checking` + +Data type: `Optional[Enum['yes', 'no', 'accept-new', 'off', 'ask']]` + + + +Default value: `undef` + +##### `syslog_facility` + +Data type: `Optional[Ssh::Syslog_facility]` + + + +Default value: `undef` + +##### `tcp_keep_alive` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `tunnel` + +Data type: `Optional[Enum['yes', 'no', 'point-to-point', 'ethernet']]` + + + +Default value: `undef` + +##### `tunnel_device` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `update_host_keys` + +Data type: `Optional[Enum['yes', 'no', 'ask']]` + + + +Default value: `undef` + +##### `user` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `user_known_hosts_file` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `verify_host_key_dns` + +Data type: `Optional[Enum['yes', 'no', 'ask']]` + + + +Default value: `undef` + +##### `visual_host_key` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `xauth_location` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `custom` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +### ssh::server + +Notes: `Match` attribute is not directly supported as multiple match blocks can +exist. Use the `custom` parameter for that. + +#### Parameters + +The following parameters are available in the `ssh::server` class. + +##### `packages` + +Data type: `Variant[String[1], Array[String[1]]]` + + + +Default value: 'openssh-server' + +##### `package_source` + +Data type: `Optional[Stdlib::Absolutepath]` + + + +Default value: `undef` + +##### `package_adminfile` + +Data type: `Optional[Stdlib::Absolutepath]` + + + +Default value: `undef` + +##### `config_path` + +Data type: `Stdlib::Absolutepath` + + + +Default value: '/etc/ssh/sshd_config' + +##### `config_owner` + +Data type: `String[1]` + + + +Default value: 'root' + +##### `config_group` + +Data type: `String[1]` + + + +Default value: 'root' + +##### `config_mode` + +Data type: `Stdlib::Filemode` + + + +Default value: '0600' + +##### `banner_path` + +Data type: `Stdlib::Absolutepath` + + + +Default value: '/etc/sshd_banner' + +##### `banner_content` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `banner_owner` + +Data type: `String[1]` + + + +Default value: 'root' + +##### `banner_group` + +Data type: `String[1]` + + + +Default value: 'root' + +##### `banner_mode` + +Data type: `Stdlib::Filemode` + + + +Default value: '0644' + +##### `manage_service` + +Data type: `Boolean` + + + +Default value: `true` + +##### `service_ensure` + +Data type: `Stdlib::Ensure::Service` + + + +Default value: 'running' + +##### `service_name` + +Data type: `String[1]` + + + +Default value: 'sshd' + +##### `service_enable` + +Data type: `Boolean` + + + +Default value: `true` + +##### `service_hasrestart` + +Data type: `Boolean` + + + +Default value: `true` + +##### `service_hasstatus` + +Data type: `Boolean` + + + +Default value: `true` + +##### `accept_env` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `address_family` + +Data type: `Optional[Enum['any', 'inet', 'inet6']]` + + + +Default value: `undef` + +##### `allow_agent_forwarding` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `allow_groups` + +Data type: `Variant[Undef, String[1], Array[String[1]]]` + + + +Default value: `undef` + +##### `allow_stream_local_forwarding` + +Data type: `Optional[Enum['yes', 'all', 'no', 'local', 'remote']]` + + + +Default value: `undef` + +##### `allow_tcp_forwarding` + +Data type: `Optional[Enum['yes', 'no', 'local', 'remote']]` + + + +Default value: `undef` + +##### `allow_users` + +Data type: `Variant[Undef, String[1], Array[String[1]]]` + + + +Default value: `undef` + +##### `authentication_methods` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `authorized_keys_command` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `authorized_keys_command_user` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `authorized_keys_file` + +Data type: `Variant[Undef, String[1], Array[String[1]]]` + + + +Default value: `undef` + +##### `authorized_principals_command` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `authorized_principals_command_user` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `authorized_principals_file` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `banner` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `ca_signature_algorithms` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `challenge_response_authentication` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `chroot_directory` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `ciphers` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `client_alive_count_max` + +Data type: `Optional[Integer[0]]` + + + +Default value: `undef` + +##### `client_alive_interval` + +Data type: `Optional[Integer[0]]` + + + +Default value: `undef` + +##### `compression` + +Data type: `Optional[Enum['yes', 'delayed', 'no']]` + + + +Default value: `undef` + +##### `deny_groups` + +Data type: `Variant[Undef, String[1], Array[String[1]]]` + + + +Default value: `undef` + +##### `deny_users` + +Data type: `Variant[Undef, String[1], Array[String[1]]]` + + + +Default value: `undef` + +##### `disable_forwarding` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `expose_auth_info` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `fingerprint_hash` + +Data type: `Optional[Enum['md5', 'sha256']]` + + + +Default value: `undef` + +##### `force_command` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `gateway_ports` + +Data type: `Optional[Enum['no', 'yes', 'clientspecified']]` + + + +Default value: `undef` + +##### `gss_api_authentication` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `gss_api_cleanup_credentials` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `gss_api_strict_acceptor_check` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `hostbased_accepted_key_types` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `hostbased_authentication` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `hostbased_uses_name_from_packet_only` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `host_certificate` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `host_key` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `host_key_agent` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `host_key_algorithms` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `ignore_rhosts` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `ignore_user_known_hosts` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `ip_qos` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `kbd_interactive_authentication` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `kerberos_authentication` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `kerberos_get_afs_token` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `kerberos_or_local_passwd` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `kerberos_ticket_cleanup` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `kex_algorithms` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `listen_address` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `login_grace_time` + +Data type: `Optional[Integer[0]]` + + + +Default value: `undef` + +##### `log_level` + +Data type: `Optional[Ssh::Log_level]` + + + +Default value: `undef` + +##### `macs` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `max_auth_tries` + +Data type: `Optional[Integer[2]]` + + + +Default value: `undef` + +##### `max_sessions` + +Data type: `Optional[Integer[0]]` + + + +Default value: `undef` + +##### `max_startups` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `password_authentication` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `permit_empty_passwords` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `permit_listen` + +Data type: `Variant[Undef, String[1], Array[String[1]]]` + + + +Default value: `undef` + +##### `permit_root_login` + +Data type: `Optional[Ssh::Permit_root_login]` + + + +Default value: `undef` + +##### `permit_tty` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `permit_tunnel` + +Data type: `Optional[Enum['yes', 'point-to-point', 'ethernet', 'no']]` + + + +Default value: `undef` + +##### `permit_user_environment` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `permit_user_rc` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `pid_file` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `port` + +Data type: `Optional[Stdlib::Port]` + + + +Default value: `undef` + +##### `print_last_log` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `print_motd` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `pubkey_accepted_key_types` + +Data type: `Optional[Array[String[1]]]` + + + +Default value: `undef` + +##### `pubkey_authentication` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `rekey_limit` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `revoked_keys` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `rdomain` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `set_env` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `stream_local_bind_mask` + +Data type: `Optional[Pattern[/^[0-7]{4}$/]]` + + + +Default value: `undef` + +##### `stream_local_bind_unlink` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `strict_modes` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `subsystem` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `syslog_facility` + +Data type: `Optional[Ssh::Syslog_facility]` + + + +Default value: `undef` + +##### `tcp_keep_alive` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `trusted_user_ca_keys` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `use_dns` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `use_pam` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `version_addendum` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `x11_display_offset` + +Data type: `Optional[Integer[0]]` + + + +Default value: `undef` + +##### `x11_forwarding` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `x11_use_localhost` + +Data type: `Optional[Ssh::Yes_no]` + + + +Default value: `undef` + +##### `xauth_location` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +##### `custom` + +Data type: `Optional[String[1]]` + + + +Default value: `undef` + +## Defined types + +### ssh::config_entry + +Manage an entry in ~/.ssh/config for a particular user. Lines model the +lines in each Host block. + +#### Parameters + +The following parameters are available in the `ssh::config_entry` defined type. + +##### `owner` + +Data type: `String[1]` + + + +##### `group` + +Data type: `String[1]` + + + +##### `path` + +Data type: `Stdlib::Absolutepath` + + + +##### `host` + +Data type: `String[1]` + + + +##### `order` + +Data type: `Integer[0]` + + + +Default value: 10 + +##### `ensure` + +Data type: `Enum['present','absent']` + + + +Default value: 'present' + +##### `lines` + +Data type: `Array[String]` + + + +Default value: [] +
diff --git a/Rakefile b/Rakefile index 93b6400..f0514ed 100644 --- a/Rakefile +++ b/Rakefile
@@ -5,9 +5,21 @@ PuppetLint.configuration.relative = true PuppetLint.configuration.ignore_paths = ['spec/**/*.pp', 'pkg/**/*.pp', 'vendor/**/*.pp'] -desc 'Validate manifests, templates, ruby files and shell scripts' +desc 'Validate ruby files' task :validate do - Dir['spec/**/*.rb', 'lib/**/*.rb'].each do |ruby_file| + Dir['spec/**/*.rb','lib/**/*.rb'].each do |ruby_file| sh "ruby -c #{ruby_file}" unless ruby_file =~ /spec\/fixtures/ end end + +# Puppet Strings (Documentation generation from inline comments) +# See: https://github.com/puppetlabs/puppet-strings#rake-tasks +require 'puppet-strings/tasks' + +desc 'Alias for strings:generate' +task :doc => ['strings:generate'] + +desc 'Generate REFERENCE.md' +task :reference do + sh 'puppet strings generate --format markdown' +end
diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..a0a1b3b --- /dev/null +++ b/Vagrantfile
@@ -0,0 +1,69 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : +# +if not Vagrant.has_plugin?('vagrant-vbguest') + abort <<-EOM + +vagrant plugin vagrant-vbguest >= 0.16.0 is required. +https://github.com/dotless-de/vagrant-vbguest +To install the plugin, please run, 'vagrant plugin install vagrant-vbguest'. + + EOM +end + +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + + config.vm.synced_folder ".", "/vagrant", type: "virtualbox" + + config.vm.provider :virtualbox do |vb| + vb.customize ["modifyvm", :id, "--memory", "512"] + end + + # TODO: remove comments around provision once we have a clean copy of + # sshd_config and ssh_config from that platform and the platform has been + # added to the module and those spec tests work. + config.vm.define "el7-ssh", autostart: true do |c| + c.vm.box = "centos/7" + c.vm.hostname = 'el7-ssh.example.com' + c.vm.provision :shell, :path => "tests/provision.sh", :args => "el" + c.vm.provision :shell, :inline => "puppet apply /vagrant/tests/init.pp" + end + + config.vm.define "el6-ssh", autostart: false do |c| + c.vm.box = "centos/6" + c.vm.hostname = 'el6-ssh.example.com' + c.vm.provision :shell, :path => "tests/provision.sh", :args => "el" + c.vm.provision :shell, :inline => "puppet apply /vagrant/tests/init.pp" + end + + config.vm.define "debian8-ssh", autostart: false do |c| + c.vm.box = "debian/jessie64" + c.vm.hostname = 'debian8-ssh.example.com' + c.vm.provision :shell, :path => "tests/provision.sh", :args => "debian" +# c.vm.provision :shell, :inline => "puppet apply /vagrant/tests/init.pp" + end + + config.vm.define "debian9-ssh", autostart: false do |c| + c.vm.box = "debian/stretch64" + c.vm.hostname = 'debian9-ssh.example.com' + c.vm.provision :shell, :path => "tests/provision.sh", :args => "debian" +# c.vm.provision :shell, :inline => "puppet apply /vagrant/tests/init.pp" + end + + config.vm.define "ubuntu1604-ssh", autostart: false do |c| + c.vm.box = "ubuntu/xenial64" + c.vm.hostname = 'ubuntu1604-ssh.example.com' + c.vm.provision :shell, :path => "tests/provision.sh", :args => "debian" +# c.vm.provision :shell, :inline => "puppet apply /vagrant/tests/init.pp" + end + + config.vm.define "ubuntu1804-ssh", autostart: false do |c| + c.vm.box = "ubuntu/bionic64" + c.vm.hostname = 'ubuntu1804-ssh.example.com' + c.vm.provision :shell, :path => "tests/provision.sh", :args => "debian" +# c.vm.provision :shell, :inline => "puppet apply /vagrant/tests/init.pp" + end +end
diff --git a/data/os/Debian/7.yaml b/data/os/Debian/7.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/data/os/Debian/7.yaml
@@ -0,0 +1,2 @@ +--- +
diff --git a/data/os/Debian/8.yaml b/data/os/Debian/8.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/data/os/Debian/8.yaml
@@ -0,0 +1,2 @@ +--- +
diff --git a/data/os/RedHat/5.yaml b/data/os/RedHat/5.yaml new file mode 100644 index 0000000..40e39a2 --- /dev/null +++ b/data/os/RedHat/5.yaml
@@ -0,0 +1,51 @@ +--- + +ssh::forward_x11_trusted: 'yes' +ssh::gss_api_authentication: 'yes' + +ssh::send_env: + - 'LANG' + - 'LANGUAGE' + - 'LC_ADDRESS' + - 'LC_ALL' + - 'LC_COLLATE' + - 'LC_CTYPE' + - 'LC_IDENTIFICATION' + - 'LC_MEASUREMENT' + - 'LC_MESSAGES' + - 'LC_MONETARY' + - 'LC_NAME' + - 'LC_NUMERIC' + - 'LC_PAPER' + - 'LC_TELEPHONE' + - 'LC_TIME' + +ssh::server::packages: 'openssh-server' + +ssh::server::accept_env: + - 'LANG' + - 'LANGUAGE' + - 'LC_ADDRESS' + - 'LC_ALL' + - 'LC_COLLATE' + - 'LC_CTYPE' + - 'LC_IDENTIFICATION' + - 'LC_MEASUREMENT' + - 'LC_MESSAGES' + - 'LC_MONETARY' + - 'LC_NAME' + - 'LC_NUMERIC' + - 'LC_PAPER' + - 'LC_TELEPHONE' + - 'LC_TIME' + +ssh::server::challenge_response_authentication: 'no' +ssh::server::gss_api_authentication: 'yes' +ssh::server::gss_api_cleanup_credentials: 'yes' +ssh::server::password_authentication: 'yes' +ssh::server::subsystem: 'sftp /usr/libexec/openssh/sftp-server' +ssh::server::syslog_facility: 'AUTHPRIV' +ssh::server::use_pam: 'yes' +ssh::server::x11_forwarding: 'yes' + +ssh::server::custom: 'Protocol 2'
diff --git a/data/os/RedHat/6.yaml b/data/os/RedHat/6.yaml new file mode 100644 index 0000000..7398dbc --- /dev/null +++ b/data/os/RedHat/6.yaml
@@ -0,0 +1,54 @@ +--- + +ssh::forward_x11_trusted: 'yes' +ssh::gss_api_authentication: 'yes' + +ssh::send_env: + - 'LANG' + - 'LANGUAGE' + - 'LC_ADDRESS' + - 'LC_ALL' + - 'LC_COLLATE' + - 'LC_CTYPE' + - 'LC_IDENTIFICATION' + - 'LC_MEASUREMENT' + - 'LC_MESSAGES' + - 'LC_MONETARY' + - 'LC_NAME' + - 'LC_NUMERIC' + - 'LC_PAPER' + - 'LC_TELEPHONE' + - 'LC_TIME' + - 'XMODIFIERS' + +ssh::server::packages: 'openssh-server' + +ssh::server::accept_env: + - 'LANG' + - 'LANGUAGE' + - 'LC_ADDRESS' + - 'LC_ALL' + - 'LC_COLLATE' + - 'LC_CTYPE' + - 'LC_IDENTIFICATION' + - 'LC_MEASUREMENT' + - 'LC_MESSAGES' + - 'LC_MONETARY' + - 'LC_NAME' + - 'LC_NUMERIC' + - 'LC_PAPER' + - 'LC_TELEPHONE' + - 'LC_TIME' + - 'XMODIFIERS' + +ssh::server::challenge_response_authentication: 'no' +ssh::server::gss_api_authentication: 'yes' +ssh::server::gss_api_cleanup_credentials: 'yes' +ssh::server::password_authentication: 'no' +ssh::server::subsystem: 'sftp /usr/libexec/openssh/sftp-server' +ssh::server::syslog_facility: 'AUTHPRIV' +ssh::server::use_dns: 'no' +ssh::server::use_pam: 'yes' +ssh::server::x11_forwarding: 'yes' + +ssh::server::custom: 'Protocol 2'
diff --git a/data/os/RedHat/7.yaml b/data/os/RedHat/7.yaml new file mode 100644 index 0000000..512aca5 --- /dev/null +++ b/data/os/RedHat/7.yaml
@@ -0,0 +1,58 @@ +--- + +ssh::forward_x11_trusted: 'yes' +ssh::gss_api_authentication: 'yes' + +ssh::send_env: + - 'LANG' + - 'LANGUAGE' + - 'LC_ADDRESS' + - 'LC_ALL' + - 'LC_COLLATE' + - 'LC_CTYPE' + - 'LC_IDENTIFICATION' + - 'LC_MEASUREMENT' + - 'LC_MESSAGES' + - 'LC_MONETARY' + - 'LC_NAME' + - 'LC_NUMERIC' + - 'LC_PAPER' + - 'LC_TELEPHONE' + - 'LC_TIME' + - 'XMODIFIERS' + +ssh::server::packages: 'openssh-server' + +ssh::server::accept_env: + - 'LANG' + - 'LC_CTYPE' + - 'LC_NUMERIC' + - 'LC_TIME' + - 'LC_COLLATE' + - 'LC_MONETARY' + - 'LC_MESSAGES' + - 'LC_PAPER' + - 'LC_NAME' + - 'LC_ADDRESS' + - 'LC_TELEPHONE' + - 'LC_MEASUREMENT' + - 'LC_IDENTIFICATION' + - 'LC_ALL' + - 'LANGUAGE' + - 'XMODIFIERS' + +ssh::server::authorized_keys_file: '.ssh/authorized_keys' +ssh::server::challenge_response_authentication: 'no' +ssh::server::gss_api_authentication: 'yes' +ssh::server::gss_api_cleanup_credentials: 'no' +ssh::server::host_key: + - '/etc/ssh/ssh_host_ecdsa_key' + - '/etc/ssh/ssh_host_ed25519_key' + - '/etc/ssh/ssh_host_rsa_key' + +ssh::server::password_authentication: 'no' +ssh::server::subsystem: 'sftp /usr/libexec/openssh/sftp-server' +ssh::server::syslog_facility: 'AUTHPRIV' +ssh::server::use_dns: 'no' +ssh::server::use_pam: 'yes' +ssh::server::x11_forwarding: 'yes'
diff --git a/data/os/Solaris/5.10.yaml b/data/os/Solaris/5.10.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/data/os/Solaris/5.10.yaml
@@ -0,0 +1,2 @@ +--- +
diff --git a/data/os/Solaris/5.11.yaml b/data/os/Solaris/5.11.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/data/os/Solaris/5.11.yaml
@@ -0,0 +1,2 @@ +--- +
diff --git a/data/os/Solaris/5.9.yaml b/data/os/Solaris/5.9.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/data/os/Solaris/5.9.yaml
@@ -0,0 +1,2 @@ +--- +
diff --git a/data/os/Suse/10.yaml b/data/os/Suse/10.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/data/os/Suse/10.yaml
@@ -0,0 +1,2 @@ +--- +
diff --git a/data/os/Suse/11.yaml b/data/os/Suse/11.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/data/os/Suse/11.yaml
@@ -0,0 +1,2 @@ +--- +
diff --git a/data/os/Suse/12.yaml b/data/os/Suse/12.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/data/os/Suse/12.yaml
@@ -0,0 +1,2 @@ +--- +
diff --git a/data/os/Suse/13.yaml b/data/os/Suse/13.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/data/os/Suse/13.yaml
@@ -0,0 +1,2 @@ +--- +
diff --git a/data/os/Suse/9.yaml b/data/os/Suse/9.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/data/os/Suse/9.yaml
@@ -0,0 +1,2 @@ +--- +
diff --git a/data/os/Ubuntu/12.04.yaml b/data/os/Ubuntu/12.04.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/data/os/Ubuntu/12.04.yaml
@@ -0,0 +1,2 @@ +--- +
diff --git a/data/os/Ubuntu/14.04.yaml b/data/os/Ubuntu/14.04.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/data/os/Ubuntu/14.04.yaml
@@ -0,0 +1,2 @@ +--- +
diff --git a/data/os/Ubuntu/16.04.yaml b/data/os/Ubuntu/16.04.yaml new file mode 100644 index 0000000..cd21505 --- /dev/null +++ b/data/os/Ubuntu/16.04.yaml
@@ -0,0 +1,2 @@ +--- +
diff --git a/hiera.yaml b/hiera.yaml new file mode 100644 index 0000000..4ab76e5 --- /dev/null +++ b/hiera.yaml
@@ -0,0 +1,17 @@ +--- +version: 5 +defaults: + datadir: data + data_hash: yaml_data +hierarchy: + - name: "osfamily/major release" + paths: + - "os/%{facts.os.family}/%{facts.os.release.major}.yaml" + # Used for Solaris + - "os/%{facts.os.family}/%{facts.kernelrelease}.yaml" + # Used to distinguish between Debian and Ubuntu + - "os/%{facts.os.name}/%{facts.os.release.major}.yaml" + - name: "osfamily" + paths: + - "os/%{facts.os.family}.yaml" + - "os/%{facts.os.name}.yaml"
diff --git a/manifests/config_entry.pp b/manifests/config_entry.pp index 3b368db..3b89bfc 100644 --- a/manifests/config_entry.pp +++ b/manifests/config_entry.pp
@@ -1,21 +1,36 @@ -# == Define: ssh::config_entry +# @summary Create config entries in a users' ~/.ssh/config # -# Manage an entry in ~/.ssh/config for a particular user. Lines model the lines -# in each Host block. +# Manage an entry in ~/.ssh/config for a particular user. Lines model the +# lines in each Host block. +# +# @param owner +# +# @param group +# +# @param path +# +# @param host +# +# @param order +# +# @param ensure +# +# @param lines +# define ssh::config_entry ( - $owner, - $group, - $path, - $host, - $order = '10', - $ensure = 'present', - $lines = [], + String[1] $owner, + String[1] $group, + Stdlib::Absolutepath $path, + String[1] $host, + Enum['present','absent'] $ensure = 'present', + Integer[0] $order = 10, + Array[String] $lines = [], ) { - # All lines including the host line. This will be joined with "\n " for + # All lines including the host line. This will be joined with "\n " for # indentation. $entry = concat(["Host ${host}"], $lines) - $content = join($entry, "\n") + $content = join($entry, "\n ") if ! defined(Concat[$path]) { concat { $path:
diff --git a/manifests/init.pp b/manifests/init.pp index 66788b9..399c7b7 100644 --- a/manifests/init.pp +++ b/manifests/init.pp
@@ -1,159 +1,347 @@ -# == Class: ssh +# @summary Class to manage SSH client # -# Manage ssh client and server +# Notes: `Match` and `Host` attributes are not directly supported as multiple +# match/host blocks can exist. Use the `custom` parameter for that. +# +# @param packages +# +# @param package_source +# +# @param package_adminfile +# +# @param config_path +# +# @param config_owner +# +# @param config_group +# +# @param config_mode +# +# @param global_known_hosts +# +# @param global_known_hosts_owner +# +# @param global_known_hosts_group +# +# @param global_known_hosts_mode +# +# @param manage_root_ssh_config +# +# @param root_ssh_config_content +# +# @param manage_server +# +# @param key_export +# +# @param purge_keys +# +# @param ssh_key_ensure +# +# @param ssh_key_import +# +# @param ssh_key_type +# +# @param keys +# +# @param config_entries +# +# @param host +# +# @param add_keys_to_agent +# +# @param address_family +# +# @param batch_mode +# +# @param bind_address +# +# @param bind_interface +# +# @param canonical_domains +# +# @param canonicalize_fallback_local +# +# @param canonicalize_hostname +# +# @param canonicalize_max_dots +# +# @param canonicalize_permitted_cnames +# +# @param ca_signature_algorithms +# +# @param certificate_file +# +# @param challenge_response_authentication +# +# @param check_host_ip +# +# @param ciphers +# +# @param clear_all_forwardings +# +# @param compression +# +# @param connection_attempts +# +# @param connect_timeout +# +# @param control_master +# +# @param control_path +# +# @param control_persist +# +# @param dynamic_forward +# +# @param enable_ssh_keysign +# +# @param escape_char +# +# @param exit_on_forward_failure +# +# @param fingerprint_hash +# +# @param forward_agent +# +# @param forward_x11 +# +# @param forward_x11_timeout +# +# @param forward_x11_trusted +# +# @param gateway_ports +# +# @param global_known_hosts_file +# +# @param gss_api_authentication +# +# @param gss_api_delegate_credentials +# +# @param hash_known_hosts +# +# @param hostbased_authentication +# +# @param hostbased_key_types +# +# @param host_key_algorithms +# +# @param host_key_alias +# +# @param host_name +# +# @param identities_only +# +# @param identity_agent +# +# @param identity_file +# +# @param ignore_unknown +# +# @param include +# +# @param ip_qos +# +# @param kbd_interactive_authentication +# +# @param kbd_interactive_devices +# +# @param kex_algorithms +# +# @param local_command +# +# @param local_forward +# +# @param log_level +# +# @param no_host_authentication_for_localhost +# +# @param number_of_password_prompts +# +# @param password_authentication +# +# @param permit_local_command +# +# @param pkcs11_provider +# +# @param port +# +# @param preferred_authentications +# +# @param proxy_command +# +# @param proxy_jump +# +# @param proxy_use_fdpass +# +# @param pubkey_accepted_key_types +# +# @param pubkey_authentication +# +# @param rekey_limit +# +# @param remote_command +# +# @param remote_forward +# +# @param request_tty +# +# @param revoked_host_keys +# +# @param send_env +# +# @param server_alive_count_max +# +# @param server_alive_interval +# +# @param set_env +# +# @param stream_local_bind_mask +# +# @param stream_local_bind_unlink +# +# @param strict_host_key_checking +# +# @param syslog_facility +# +# @param tcp_keep_alive +# +# @param tunnel +# +# @param tunnel_device +# +# @param update_host_keys +# +# @param user +# +# @param user_known_hosts_file +# +# @param verify_host_key_dns +# +# @param visual_host_key +# +# @param xauth_location +# +# @param custom # class ssh ( - $hiera_merge = false, - $packages = 'USE_DEFAULTS', - $permit_root_login = 'yes', - $purge_keys = true, - $manage_firewall = false, - $ssh_package_source = 'USE_DEFAULTS', - $ssh_package_adminfile = 'USE_DEFAULTS', - $ssh_config_hash_known_hosts = 'USE_DEFAULTS', - $ssh_config_path = '/etc/ssh/ssh_config', - $ssh_config_owner = 'root', - $ssh_config_group = 'root', - $ssh_config_mode = '0644', - $ssh_config_forward_x11 = undef, - $ssh_config_forward_x11_trusted = 'USE_DEFAULTS', - $ssh_config_forward_agent = undef, - $ssh_config_server_alive_interval = undef, - $ssh_config_sendenv_xmodifiers = false, - $ssh_hostbasedauthentication = undef, - $ssh_config_proxy_command = undef, - $ssh_strict_host_key_checking = undef, - $ssh_config_ciphers = undef, - $ssh_config_kexalgorithms = undef, - $ssh_config_macs = undef, - $ssh_config_use_roaming = 'USE_DEFAULTS', - $ssh_config_template = 'ssh/ssh_config.erb', - $ssh_sendenv = 'USE_DEFAULTS', - $ssh_gssapiauthentication = 'yes', - $ssh_gssapidelegatecredentials = undef, - $sshd_config_path = '/etc/ssh/sshd_config', - $sshd_config_owner = 'root', - $sshd_config_group = 'root', - $sshd_config_loglevel = 'INFO', - $sshd_config_mode = 'USE_DEFAULTS', - $sshd_config_permitemptypasswords = undef, - $sshd_config_permituserenvironment = undef, - $sshd_config_compression = undef, - $sshd_config_port = '22', - $sshd_config_syslog_facility = 'AUTH', - $sshd_config_template = 'ssh/sshd_config.erb', - $sshd_config_login_grace_time = '120', - $sshd_config_challenge_resp_auth = 'yes', - $sshd_config_print_motd = 'yes', - $sshd_config_print_last_log = undef, - $sshd_config_use_dns = 'USE_DEFAULTS', - $sshd_config_authkey_location = undef, - $sshd_config_strictmodes = undef, - $sshd_config_serverkeybits = 'USE_DEFAULTS', - $sshd_config_banner = 'none', - $sshd_config_ciphers = undef, - $sshd_config_kexalgorithms = undef, - $sshd_config_macs = undef, - $ssh_enable_ssh_keysign = undef, - $sshd_config_allowgroups = [], - $sshd_config_allowusers = [], - $sshd_config_denygroups = [], - $sshd_config_denyusers = [], - $sshd_config_maxauthtries = undef, - $sshd_config_maxstartups = undef, - $sshd_config_maxsessions = undef, - $sshd_config_chrootdirectory = undef, - $sshd_config_forcecommand = undef, - $sshd_config_match = undef, - $sshd_authorized_keys_command = undef, - $sshd_authorized_keys_command_user = undef, - $sshd_banner_content = undef, - $sshd_banner_owner = 'root', - $sshd_banner_group = 'root', - $sshd_banner_mode = '0644', - $sshd_config_xauth_location = 'USE_DEFAULTS', - $sshd_config_subsystem_sftp = 'USE_DEFAULTS', - $sshd_kerberos_authentication = undef, - $sshd_password_authentication = 'yes', - $sshd_allow_tcp_forwarding = 'yes', - $sshd_x11_forwarding = 'yes', - $sshd_x11_use_localhost = 'yes', - $sshd_use_pam = 'USE_DEFAULTS', - $sshd_client_alive_count_max = '3', - $sshd_client_alive_interval = '0', - $sshd_gssapiauthentication = 'yes', - $sshd_gssapikeyexchange = 'USE_DEFAULTS', - $sshd_pamauthenticationviakbdint = 'USE_DEFAULTS', - $sshd_gssapicleanupcredentials = 'USE_DEFAULTS', - $sshd_acceptenv = 'USE_DEFAULTS', - $sshd_config_hostkey = 'USE_DEFAULTS', - $sshd_listen_address = undef, - $sshd_hostbasedauthentication = 'no', - $sshd_pubkeyacceptedkeytypes = undef, - $sshd_pubkeyauthentication = 'yes', - $sshd_ignoreuserknownhosts = 'no', - $sshd_ignorerhosts = 'yes', - $sshd_config_authenticationmethods = undef, - $manage_service = true, - $sshd_addressfamily = 'USE_DEFAULTS', - $service_ensure = 'running', - $service_name = 'USE_DEFAULTS', - $service_enable = true, - $service_hasrestart = true, - $service_hasstatus = 'USE_DEFAULTS', - $ssh_key_ensure = 'present', - $ssh_key_import = true, - $ssh_key_type = 'ssh-rsa', - $ssh_config_global_known_hosts_file = '/etc/ssh/ssh_known_hosts', - $ssh_config_global_known_hosts_list = undef, - $ssh_config_global_known_hosts_owner = 'root', - $ssh_config_global_known_hosts_group = 'root', - $ssh_config_global_known_hosts_mode = '0644', - $ssh_config_user_known_hosts_file = undef, - $config_entries = {}, - $keys = undef, - $manage_root_ssh_config = false, - $root_ssh_config_content = "# This file is being maintained by Puppet.\n# DO NOT EDIT\n", - $sshd_config_tcp_keepalive = undef, - $sshd_config_use_privilege_separation = undef, - $sshd_config_permittunnel = undef, - $sshd_config_hostcertificate = undef, - $sshd_config_trustedusercakeys = undef, - $sshd_config_key_revocation_list = undef, - $sshd_config_authorized_principals_file = undef, - $sshd_config_allowagentforwarding = undef, + Variant[String[1], Array[String[1]]] $packages = 'openssh-clients', + Optional[Stdlib::Absolutepath] $package_source = undef, + Optional[Stdlib::Absolutepath] $package_adminfile = undef, + Stdlib::Absolutepath $config_path = '/etc/ssh/ssh_config', + String[1] $config_owner = 'root', + String[1] $config_group = 'root', + Stdlib::Filemode $config_mode = '0644', + Stdlib::Absolutepath $global_known_hosts = '/etc/ssh/ssh_known_hosts', + String[1] $global_known_hosts_owner = 'root', + String[1] $global_known_hosts_group = 'root', + Stdlib::Filemode $global_known_hosts_mode = '0644', + Boolean $manage_root_ssh_config = false, + String[1] $root_ssh_config_content = "# This file is being maintained by Puppet.\n# DO NOT EDIT\n", + Boolean $manage_server = true, + Boolean $key_export = false, + Boolean $purge_keys = true, + Enum['present', 'absent'] $ssh_key_ensure = 'present', + Boolean $ssh_key_import = false, + Ssh::Key::Type $ssh_key_type = 'ssh-rsa', + Hash $keys = {}, + Hash $config_entries = {}, + # class parameters below this line directly correlate with ssh_config parameters + String[1] $host = '*', + Optional[Enum['yes', 'no', 'ask', 'confirm']] $add_keys_to_agent = undef, + Optional[Enum['any', 'inet', 'inet6']] $address_family = undef, + Optional[Ssh::Yes_no] $batch_mode = undef, + Optional[String[1]] $bind_address = undef, + Optional[String[1]] $bind_interface = undef, + Optional[Array[String[1]]] $canonical_domains = undef, + Optional[Ssh::Yes_no] $canonicalize_fallback_local = undef, + Optional[Enum['yes', 'no', 'always']] $canonicalize_hostname = undef, + Optional[Integer[0]] $canonicalize_max_dots = undef, + Optional[Array[String[1]]] $canonicalize_permitted_cnames = undef, + Optional[Array[String[1]]] $ca_signature_algorithms = undef, + Optional[Array[String[1]]] $certificate_file = undef, + Optional[Ssh::Yes_no] $challenge_response_authentication = undef, + Optional[Ssh::Yes_no] $check_host_ip = undef, + Optional[Array[String[1]]] $ciphers = undef, + Optional[Ssh::Yes_no] $clear_all_forwardings = undef, + Optional[Ssh::Yes_no] $compression = undef, + Optional[Integer[0]] $connection_attempts = undef, + Optional[Integer[0]] $connect_timeout = undef, + Optional[Enum['yes', 'no', 'ask', 'auto', 'autoask']] $control_master = undef, + Optional[String[1]] $control_path = undef, + Optional[String[1]] $control_persist = undef, + Optional[String[1]] $dynamic_forward = undef, + Optional[Ssh::Yes_no] $enable_ssh_keysign = undef, + Optional[String[1]] $escape_char = undef, + Optional[Ssh::Yes_no] $exit_on_forward_failure = undef, + Optional[Enum['sha256', 'md5']] $fingerprint_hash = undef, + Optional[Ssh::Yes_no] $forward_agent = undef, + Optional[Ssh::Yes_no] $forward_x11 = undef, + Variant[Undef, String[1], Integer[0]] $forward_x11_timeout = undef, + Optional[Ssh::Yes_no] $forward_x11_trusted = undef, + Optional[Ssh::Yes_no] $gateway_ports = undef, + Variant[Undef, String[1], Array[String[1]]] $global_known_hosts_file = undef, + Optional[Ssh::Yes_no] $gss_api_authentication = undef, + Optional[Ssh::Yes_no] $gss_api_delegate_credentials = undef, + Optional[Ssh::Yes_no] $hash_known_hosts = undef, + Optional[Ssh::Yes_no] $hostbased_authentication = undef, + Optional[Array[String[1]]] $hostbased_key_types = undef, + Optional[Array[String[1]]] $host_key_algorithms = undef, + Optional[String[1]] $host_key_alias = undef, + Optional[String[1]] $host_name = undef, + Optional[Ssh::Yes_no] $identities_only = undef, + Optional[String[1]] $identity_agent = undef, + Optional[Array[String[1]]] $identity_file = undef, + Optional[Array[String[1]]] $ignore_unknown = undef, + Optional[String[1]] $include = undef, + Optional[String[1]] $ip_qos = undef, + Optional[Ssh::Yes_no] $kbd_interactive_authentication = undef, + Optional[Array[String[1]]] $kbd_interactive_devices = undef, + Optional[Array[String[1]]] $kex_algorithms = undef, + Optional[String[1]] $local_command = undef, + Optional[String[1]] $local_forward = undef, + Optional[Ssh::Log_level] $log_level = undef, + Optional[Ssh::Yes_no] $no_host_authentication_for_localhost = undef, + Optional[Integer] $number_of_password_prompts = undef, + Optional[Ssh::Yes_no] $password_authentication = undef, + Optional[Ssh::Yes_no] $permit_local_command = undef, + Optional[String[1]] $pkcs11_provider = undef, + Optional[Stdlib::Port] $port = undef, + Optional[Array[String[1]]] $preferred_authentications = undef, + Optional[String[1]] $proxy_command = undef, + Optional[Array[String[1]]] $proxy_jump = undef, + Optional[Ssh::Yes_no] $proxy_use_fdpass = undef, + Optional[Array[String[1]]] $pubkey_accepted_key_types = undef, + Optional[Ssh::Yes_no] $pubkey_authentication = undef, + Optional[String[1]] $rekey_limit = undef, + Optional[String[1]] $remote_command = undef, + Optional[String[1]] $remote_forward = undef, + Optional[Enum['no', 'yes', 'force', 'auto']] $request_tty = undef, + Optional[String[1]] $revoked_host_keys = undef, + Optional[Array[String[1]]] $send_env = undef, + Variant[Undef, String[1], Integer[0]] $server_alive_count_max = undef, + Variant[Undef, String[1], Integer[0]] $server_alive_interval = undef, + Optional[Array[String[1]]] $set_env = undef, + Optional[Pattern[/^[0-7]{4}$/]] $stream_local_bind_mask = undef, + Optional[Ssh::Yes_no] $stream_local_bind_unlink = undef, + Optional[Enum['yes', 'no', 'accept-new', 'off', 'ask']] $strict_host_key_checking = undef, + Optional[Ssh::Syslog_facility] $syslog_facility = undef, + Optional[Ssh::Yes_no] $tcp_keep_alive = undef, + Optional[Enum['yes', 'no', 'point-to-point', 'ethernet']] $tunnel = undef, + Optional[String[1]] $tunnel_device = undef, + Optional[Enum['yes', 'no', 'ask']] $update_host_keys = undef, + Optional[String[1]] $user = undef, + Optional[Array[String[1]]] $user_known_hosts_file = undef, + Optional[Enum['yes', 'no', 'ask']] $verify_host_key_dns = undef, + Optional[Ssh::Yes_no] $visual_host_key = undef, + Optional[String[1]] $xauth_location = undef, + # custom is a string that allows for multiple lines to be appended to end of + # the sshd_config file. + Optional[String[1]] $custom = undef, ) { - case $::osfamily { - 'RedHat': { - $default_packages = ['openssh-server', - 'openssh-clients'] - $default_service_name = 'sshd' - $default_ssh_config_hash_known_hosts = 'no' - $default_ssh_config_forward_x11_trusted = 'yes' - $default_ssh_package_source = undef - $default_ssh_package_adminfile = undef - $default_ssh_sendenv = true - $default_sshd_config_subsystem_sftp = '/usr/libexec/openssh/sftp-server' - $default_sshd_config_mode = '0600' - $default_sshd_config_use_dns = 'yes' - $default_sshd_config_xauth_location = '/usr/bin/xauth' - $default_sshd_use_pam = 'yes' - $default_sshd_gssapikeyexchange = undef - $default_sshd_pamauthenticationviakbdint = undef - $default_sshd_gssapicleanupcredentials = 'yes' - $default_sshd_acceptenv = true - $default_service_hasstatus = true - if versioncmp($::operatingsystemrelease, '7.4') < 0 { - $default_sshd_config_serverkeybits = '1024' - } else { - $default_sshd_config_serverkeybits = undef - } - $default_sshd_config_hostkey = [ '/etc/ssh/ssh_host_rsa_key' ] - $default_sshd_addressfamily = 'any' - $default_sshd_config_tcp_keepalive = 'yes' - $default_sshd_config_permittunnel = 'no' - } + # TODO: This huge case statement is getting transitioned to hiera + case $facts['os']['family'] { + 'RedHat': {} 'Suse': { $default_packages = 'openssh' $default_service_name = 'sshd' @@ -386,7 +574,7 @@ } } default: { - fail("ssh supports osfamilies RedHat, Suse, Debian and Solaris. Detected osfamily is <${::osfamily}>.") + fail("ssh supports osfamilies RedHat, Suse, Debian and Solaris. Detected os family is <${facts['os']['family']}>.") } } @@ -405,639 +593,29 @@ $default_ssh_config_use_roaming = 'unset' } - if $packages == 'USE_DEFAULTS' { - $packages_real = $default_packages - } else { - $packages_real = $packages - } - - case $ssh_config_hash_known_hosts { - 'unset': { $ssh_config_hash_known_hosts_real = undef } - 'USE_DEFAULTS': { $ssh_config_hash_known_hosts_real = $default_ssh_config_hash_known_hosts } - default: { $ssh_config_hash_known_hosts_real = $ssh_config_hash_known_hosts } - } - - if $service_name == 'USE_DEFAULTS' { - $service_name_real = $default_service_name - } else { - $service_name_real = $service_name - } - - if $sshd_config_subsystem_sftp == 'USE_DEFAULTS' { - $sshd_config_subsystem_sftp_real = $default_sshd_config_subsystem_sftp - } else { - $sshd_config_subsystem_sftp_real = $sshd_config_subsystem_sftp - } - - if $sshd_config_mode == 'USE_DEFAULTS' { - $sshd_config_mode_real = $default_sshd_config_mode - } else { - $sshd_config_mode_real = $sshd_config_mode - } - - if $sshd_config_xauth_location == 'USE_DEFAULTS' { - $sshd_config_xauth_location_real = $default_sshd_config_xauth_location - } else { - $sshd_config_xauth_location_real = $sshd_config_xauth_location - } - - if $sshd_config_xauth_location_real != undef { - validate_absolute_path($sshd_config_xauth_location_real) - } - - if $ssh_package_source == 'USE_DEFAULTS' { - $ssh_package_source_real = $default_ssh_package_source - } else { - $ssh_package_source_real = $ssh_package_source - } - - if $ssh_package_source_real != undef { - validate_absolute_path($ssh_package_source_real) - } - - if $ssh_package_adminfile == 'USE_DEFAULTS' { - $ssh_package_adminfile_real = $default_ssh_package_adminfile - } else { - $ssh_package_adminfile_real = $ssh_package_adminfile - } - - if $ssh_package_adminfile_real != undef { - validate_absolute_path($ssh_package_adminfile_real) - } - - if $sshd_config_use_dns == 'USE_DEFAULTS' { - $sshd_config_use_dns_real = $default_sshd_config_use_dns - } else { - $sshd_config_use_dns_real = $sshd_config_use_dns - } - - if $sshd_use_pam == 'USE_DEFAULTS' { - $sshd_use_pam_real = $default_sshd_use_pam - } else { - $sshd_use_pam_real = $sshd_use_pam - } - - if $sshd_config_serverkeybits == 'USE_DEFAULTS' { - $sshd_config_serverkeybits_real = $default_sshd_config_serverkeybits - } else { - $sshd_config_serverkeybits_real = $sshd_config_serverkeybits - } - - if $ssh_config_forward_x11_trusted == 'USE_DEFAULTS' { - $ssh_config_forward_x11_trusted_real = $default_ssh_config_forward_x11_trusted - } else { - $ssh_config_forward_x11_trusted_real = $ssh_config_forward_x11_trusted - } - if $ssh_config_forward_x11_trusted_real != undef { - validate_re($ssh_config_forward_x11_trusted_real, '^(yes|no)$', "ssh::ssh_config_forward_x11_trusted may be either 'yes' or 'no' and is set to <${ssh_config_forward_x11_trusted_real}>.") - } - - if $sshd_gssapikeyexchange == 'USE_DEFAULTS' { - $sshd_gssapikeyexchange_real = $default_sshd_gssapikeyexchange - } else { - $sshd_gssapikeyexchange_real = $sshd_gssapikeyexchange - } - - if $sshd_pamauthenticationviakbdint == 'USE_DEFAULTS' { - $sshd_pamauthenticationviakbdint_real = $default_sshd_pamauthenticationviakbdint - } else { - $sshd_pamauthenticationviakbdint_real = $sshd_pamauthenticationviakbdint - } - - if $sshd_gssapicleanupcredentials == 'USE_DEFAULTS' { - $sshd_gssapicleanupcredentials_real = $default_sshd_gssapicleanupcredentials - } else { - $sshd_gssapicleanupcredentials_real = $sshd_gssapicleanupcredentials - } - - if $ssh_config_use_roaming == 'USE_DEFAULTS' { - $ssh_config_use_roaming_real = $default_ssh_config_use_roaming - } else { - $ssh_config_use_roaming_real = $ssh_config_use_roaming - } - - if $ssh_sendenv == 'USE_DEFAULTS' { - $ssh_sendenv_real = $default_ssh_sendenv - } else { - case type3x($ssh_sendenv) { - 'string': { - validate_re($ssh_sendenv, '^(true|false)$', "ssh::ssh_sendenv may be either 'true' or 'false' and is set to <${ssh_sendenv}>.") - $ssh_sendenv_real = str2bool($ssh_sendenv) - } - 'boolean': { - $ssh_sendenv_real = $ssh_sendenv - } - default: { - fail('ssh::ssh_sendenv type must be true or false.') - } - } - } - - if $sshd_acceptenv == 'USE_DEFAULTS' { - $sshd_acceptenv_real = $default_sshd_acceptenv - } else { - case type3x($sshd_acceptenv) { - 'string': { - validate_re($sshd_acceptenv, '^(true|false)$', "ssh::sshd_acceptenv may be either 'true' or 'false' and is set to <${sshd_acceptenv}>.") - $sshd_acceptenv_real = str2bool($sshd_acceptenv) - } - 'boolean': { - $sshd_acceptenv_real = $sshd_acceptenv - } - default: { - fail('ssh::sshd_acceptenv type must be true or false.') - } - } - } - - if $sshd_config_hostkey == 'USE_DEFAULTS' { - $sshd_config_hostkey_real = $default_sshd_config_hostkey - } else { - validate_array($sshd_config_hostkey) - validate_absolute_path($sshd_config_hostkey) - $sshd_config_hostkey_real = $sshd_config_hostkey - } - - if $sshd_listen_address { - validate_array($sshd_listen_address) - } - - if $service_hasstatus == 'USE_DEFAULTS' { - $service_hasstatus_real = $default_service_hasstatus - } else { - case type3x($service_hasstatus) { - 'string': { - validate_re($service_hasstatus, '^(true|false)$', "ssh::service_hasstatus must be 'true' or 'false' and is set to <${service_hasstatus}>.") - $service_hasstatus_real = str2bool($service_hasstatus) - } - 'boolean': { - $service_hasstatus_real = $service_hasstatus - } - default: { - fail('ssh::service_hasstatus must be true or false.') - } - } - } - - if $sshd_addressfamily == 'USE_DEFAULTS' { - $sshd_addressfamily_real = $default_sshd_addressfamily - } else { - $sshd_addressfamily_real = $sshd_addressfamily - } - - case $sshd_config_maxsessions { - 'unset', undef: { $sshd_config_maxsessions_integer = undef } - default: { $sshd_config_maxsessions_integer = floor($sshd_config_maxsessions) } - } - - case $sshd_config_tcp_keepalive { - 'unset': { $sshd_config_tcp_keepalive_real = undef } - undef: { $sshd_config_tcp_keepalive_real = $default_sshd_config_tcp_keepalive } - default: { $sshd_config_tcp_keepalive_real = $sshd_config_tcp_keepalive } - } - - case $sshd_config_permittunnel { - 'unset': { $sshd_config_permittunnel_real = undef } - undef: { $sshd_config_permittunnel_real = $default_sshd_config_permittunnel } - default: { $sshd_config_permittunnel_real = $sshd_config_permittunnel } - } - - case $sshd_config_hostcertificate { - 'unset', undef: { $sshd_config_hostcertificate_real = undef } - default: { $sshd_config_hostcertificate_real = $sshd_config_hostcertificate } - } - - case $sshd_config_trustedusercakeys { - 'unset', undef: { $sshd_config_trustedusercakeys_real = undef } - default: { $sshd_config_trustedusercakeys_real = $sshd_config_trustedusercakeys } - } - - case $sshd_config_key_revocation_list { - 'unset', undef: { $sshd_config_key_revocation_list_real = undef } - default: { $sshd_config_key_revocation_list_real = $sshd_config_key_revocation_list } - } - - case $sshd_config_authorized_principals_file { - 'unset', undef: { $sshd_config_authorized_principals_file_real = undef } - default: { $sshd_config_authorized_principals_file_real = $sshd_config_authorized_principals_file } - } - - # validate params - if $ssh_config_ciphers != undef { - validate_array($ssh_config_ciphers) - } - - if $sshd_config_ciphers != undef { - validate_array($sshd_config_ciphers) - } - - if $ssh_config_kexalgorithms != undef { - validate_array($ssh_config_kexalgorithms) - } - - if $sshd_config_kexalgorithms != undef { - validate_array($sshd_config_kexalgorithms) - } - - if $ssh_config_macs != undef { - validate_array($ssh_config_macs) - } - - if $sshd_config_macs != undef { - validate_array($sshd_config_macs) - } - - if $ssh_config_hash_known_hosts_real != undef { - validate_re($ssh_config_hash_known_hosts_real, '^(yes|no)$', "ssh::ssh_config_hash_known_hosts may be either 'yes', 'no' or 'unset' and is set to <${ssh_config_hash_known_hosts_real}>.") - } - if $sshd_config_permitemptypasswords != undef { - validate_re($sshd_config_permitemptypasswords, '^(yes|no)$', "ssh::sshd_config_permitemptypasswords may be either 'yes' or 'no' and is set to <${sshd_config_permitemptypasswords}>.") - } - if $sshd_config_permituserenvironment != undef { - validate_re($sshd_config_permituserenvironment, '^(yes|no)$', "ssh::sshd_config_permituserenvironment may be either 'yes' or 'no' and is set to <${sshd_config_permituserenvironment}>.") - } - if $sshd_config_compression != undef { - validate_re($sshd_config_compression, '^(yes|no|delayed)$', "ssh::sshd_config_compression may be either 'yes', 'no' or 'delayed' and is set to <${sshd_config_compression}>.") - } - case type3x($sshd_config_port) { - 'string': { - validate_re($sshd_config_port, '^\d+$', "ssh::sshd_config_port must be a valid number and is set to <${sshd_config_port}>.") - $sshd_config_port_array = [ str2num($sshd_config_port) ] - } - 'array': { - $sshd_config_port_array = $sshd_config_port - } - 'integer': { - $sshd_config_port_array = [ $sshd_config_port ] - } - default: { - fail('ssh:sshd_config_port must be a string, an integer or an array. ') - } - } - validate_numeric($sshd_config_port_array, 65535, 1) - if $sshd_kerberos_authentication != undef { - validate_re($sshd_kerberos_authentication, '^(yes|no)$', "ssh::sshd_kerberos_authentication may be either 'yes' or 'no' and is set to <${sshd_kerberos_authentication}>.") - } - validate_re($sshd_password_authentication, '^(yes|no)$', "ssh::sshd_password_authentication may be either 'yes' or 'no' and is set to <${sshd_password_authentication}>.") - validate_re($sshd_allow_tcp_forwarding, '^(yes|no)$', "ssh::sshd_allow_tcp_forwarding may be either 'yes' or 'no' and is set to <${sshd_allow_tcp_forwarding}>.") - validate_re($sshd_x11_forwarding, '^(yes|no)$', "ssh::sshd_x11_forwarding may be either 'yes' or 'no' and is set to <${sshd_x11_forwarding}>.") - validate_re($sshd_x11_use_localhost, '^(yes|no)$', "ssh::sshd_x11_use_localhost may be either 'yes' or 'no' and is set to <${sshd_x11_use_localhost}>.") - if $sshd_config_print_last_log != undef { - validate_re($sshd_config_print_last_log, '^(yes|no)$', "ssh::sshd_config_print_last_log may be either 'yes' or 'no' and is set to <${sshd_config_print_last_log}>.") - } - if $sshd_use_pam_real != undef { - validate_re($sshd_use_pam_real, '^(yes|no)$', "ssh::sshd_use_pam may be either 'yes' or 'no' and is set to <${sshd_use_pam_real}>.") - } - if $sshd_config_serverkeybits_real != undef { - if is_integer($sshd_config_serverkeybits_real) == false { fail("ssh::sshd_config_serverkeybits must be an integer and is set to <${sshd_config_serverkeybits}>.") } - } - if $ssh_config_use_roaming_real != undef { - validate_re($ssh_config_use_roaming_real, '^(yes|no|unset)$', "ssh::ssh_config_use_roaming may be either 'yes', 'no' or 'unset' and is set to <${$ssh_config_use_roaming}>.") - } - if is_integer($sshd_client_alive_interval) == false { fail("ssh::sshd_client_alive_interval must be an integer and is set to <${sshd_client_alive_interval}>.") } - if is_integer($sshd_client_alive_count_max) == false { fail("ssh::sshd_client_alive_count_max must be an integer and is set to <${sshd_client_alive_count_max}>.") } - - if $sshd_config_banner != 'none' { - validate_absolute_path($sshd_config_banner) - } - if $sshd_banner_content != undef and $sshd_config_banner == 'none' { - fail('ssh::sshd_config_banner must be set to be able to use sshd_banner_content.') - } - - validate_re($ssh_gssapiauthentication, '^(yes|no)$', "ssh::ssh_gssapiauthentication may be either 'yes' or 'no' and is set to <${ssh_gssapiauthentication}>.") - - if $ssh_gssapidelegatecredentials != undef { - validate_re($ssh_gssapidelegatecredentials, '^(yes|no)$', "ssh::ssh_gssapidelegatecredentials may be either 'yes' or 'no' and is set to <${ssh_gssapidelegatecredentials}>.") - } - - validate_re($sshd_gssapiauthentication, '^(yes|no)$', "ssh::sshd_gssapiauthentication may be either 'yes' or 'no' and is set to <${sshd_gssapiauthentication}>.") - - if $sshd_gssapikeyexchange_real != undef { - validate_re($sshd_gssapikeyexchange_real, '^(yes|no)$', "ssh::sshd_gssapikeyexchange may be either 'yes' or 'no' and is set to <${sshd_gssapikeyexchange_real}>.") - } - - if $sshd_pamauthenticationviakbdint_real != undef { - validate_re($sshd_pamauthenticationviakbdint_real, '^(yes|no)$', "ssh::sshd_pamauthenticationviakbdint may be either 'yes' or 'no' and is set to <${sshd_pamauthenticationviakbdint_real}>.") - } - - if $sshd_gssapicleanupcredentials_real != undef { - validate_re($sshd_gssapicleanupcredentials_real, '^(yes|no)$', "ssh::sshd_gssapicleanupcredentials may be either 'yes' or 'no' and is set to <${sshd_gssapicleanupcredentials_real}>.") - } - - if $ssh_strict_host_key_checking != undef { - validate_re($ssh_strict_host_key_checking, '^(yes|no|ask)$', "ssh::ssh_strict_host_key_checking may be 'yes', 'no' or 'ask' and is set to <${ssh_strict_host_key_checking}>.") - } - - if $ssh_config_proxy_command != undef { - validate_string($ssh_config_proxy_command) - } - - if $ssh_enable_ssh_keysign != undef { - validate_re($ssh_enable_ssh_keysign, '^(yes|no)$', "ssh::ssh_enable_ssh_keysign may be either 'yes' or 'no' and is set to <${ssh_enable_ssh_keysign}>.") - } - - if $sshd_config_authkey_location != undef { - validate_string($sshd_config_authkey_location) - } - - if $sshd_config_maxauthtries != undef { - if is_integer($sshd_config_maxauthtries) == false { - fail("ssh::sshd_config_maxauthtries must be a valid number and is set to <${sshd_config_maxauthtries}>.") - } - } - - if $sshd_config_maxstartups != undef { - validate_re($sshd_config_maxstartups,'^((\d+)|(\d+?:\d+?:\d+)?)$', - "ssh::sshd_config_maxstartups may be either an integer or three integers separated with colons, such as 10:30:100. Detected value is <${sshd_config_maxstartups}>.") - } - - if $sshd_config_chrootdirectory != undef { - validate_absolute_path($sshd_config_chrootdirectory) - } - - if $sshd_config_forcecommand != undef { - validate_string($sshd_config_forcecommand) - } - - if $sshd_authorized_keys_command != undef { - validate_absolute_path($sshd_authorized_keys_command) - } - - if $sshd_authorized_keys_command_user != undef { - validate_string($sshd_authorized_keys_command_user) - } - - if $sshd_config_match != undef { - validate_hash($sshd_config_match) - } - - if $sshd_config_strictmodes != undef { - validate_re($sshd_config_strictmodes, '^(yes|no)$', "ssh::sshd_config_strictmodes may be either 'yes' or 'no' and is set to <${sshd_config_strictmodes}>.") - } - if $ssh_hostbasedauthentication != undef { - validate_re($ssh_hostbasedauthentication, '^(yes|no)$', "ssh::ssh_hostbasedauthentication may be either 'yes' or 'no' and is set to <${ssh_hostbasedauthentication}>.") - } - - validate_re($sshd_hostbasedauthentication, '^(yes|no)$', "ssh::sshd_hostbasedauthentication may be either 'yes' or 'no' and is set to <${sshd_hostbasedauthentication}>.") - - if $sshd_pubkeyacceptedkeytypes != undef { - validate_array($sshd_pubkeyacceptedkeytypes) - } - - if $sshd_config_authenticationmethods != undef { - validate_array($sshd_config_authenticationmethods) - } - - validate_re($sshd_pubkeyauthentication, '^(yes|no)$', "ssh::sshd_pubkeyauthentication may be either 'yes' or 'no' and is set to <${sshd_pubkeyauthentication}>.") - - validate_re($sshd_ignoreuserknownhosts, '^(yes|no)$', "ssh::sshd_ignoreuserknownhosts may be either 'yes' or 'no' and is set to <${sshd_ignoreuserknownhosts}>.") - - validate_re($sshd_ignorerhosts, '^(yes|no)$', "ssh::sshd_ignorerhosts may be either 'yes' or 'no' and is set to <${sshd_ignorerhosts}>.") - - case type3x($hiera_merge) { - 'string': { - validate_re($hiera_merge, '^(true|false)$', "ssh::hiera_merge may be either 'true' or 'false' and is set to <${hiera_merge}>.") - $hiera_merge_real = str2bool($hiera_merge) - } - 'boolean': { - $hiera_merge_real = $hiera_merge - } - default: { - fail('ssh::hiera_merge type must be true or false.') - } - } - - case type3x($ssh_key_import) { - 'string': { - validate_re($ssh_key_import, '^(true|false)$', "ssh::ssh_key_import may be either 'true' or 'false' and is set to <${ssh_key_import}>.") - $ssh_key_import_real = str2bool($ssh_key_import) - } - 'boolean': { - $ssh_key_import_real = $ssh_key_import - } - default: { - fail('ssh::ssh_key_import type must be true or false.') - } - } - validate_bool($ssh_key_import_real) - - case type3x($ssh_config_sendenv_xmodifiers) { - 'string': { - $ssh_config_sendenv_xmodifiers_real = str2bool($ssh_config_sendenv_xmodifiers) - } - 'boolean': { - $ssh_config_sendenv_xmodifiers_real = $ssh_config_sendenv_xmodifiers - } - default: { - fail('ssh::ssh_config_sendenv_xmodifiers type must be true or false.') - } - } - - case $permit_root_login { - 'no', 'yes', 'without-password', 'forced-commands-only': { - # noop - } - default: { - fail("ssh::permit_root_login may be either 'yes', 'without-password', 'forced-commands-only' or 'no' and is set to <${permit_root_login}>.") - } - } - - case $ssh_key_type { - 'ssh-rsa','rsa': { - $key = $::sshrsakey - } - 'ssh-dsa','dsa': { - $key = $::sshdsakey - } - 'ecdsa-sha2-nistp256': { - $key = $::sshecdsakey - } - default: { - fail("ssh::ssh_key_type must be 'ecdsa-sha2-nistp256', 'ssh-rsa', 'rsa', 'ssh-dsa', or 'dsa' and is <${ssh_key_type}>.") - } - } - - validate_absolute_path($ssh_config_global_known_hosts_file) - $ssh_config_global_known_hosts_file_real = any2array($ssh_config_global_known_hosts_file) - - if $ssh_config_global_known_hosts_list != undef { - validate_array($ssh_config_global_known_hosts_list) - validate_absolute_path($ssh_config_global_known_hosts_list) - $ssh_config_global_known_hosts_list_real = concat($ssh_config_global_known_hosts_file_real, $ssh_config_global_known_hosts_list) - } else { - $ssh_config_global_known_hosts_list_real = $ssh_config_global_known_hosts_file_real - } - - if $ssh_config_user_known_hosts_file != undef { - validate_array($ssh_config_user_known_hosts_file) - } - - validate_string($ssh_config_global_known_hosts_owner) - validate_string($ssh_config_global_known_hosts_group) - validate_re($ssh_config_global_known_hosts_mode, '^[0-7]{4}$', - "ssh::ssh_config_global_known_hosts_mode must be a valid 4 digit mode in octal notation. Detected value is <${ssh_config_global_known_hosts_mode}>.") - - if type3x($purge_keys) == 'string' { - $purge_keys_real = str2bool($purge_keys) - } else { - $purge_keys_real = $purge_keys - } - validate_bool($purge_keys_real) - - if type3x($manage_service) == 'string' { - $manage_service_real = str2bool($manage_service) - } else { - $manage_service_real = $manage_service - } - validate_bool($manage_service_real) - - if type3x($service_enable) == 'string' { - $service_enable_real = str2bool($service_enable) - } else { - $service_enable_real = $service_enable - } - validate_bool($service_enable_real) - - if type3x($service_hasrestart) == 'string' { - $service_hasrestart_real = str2bool($service_hasrestart) - } else { - $service_hasrestart_real = $service_hasrestart - } - validate_bool($service_hasrestart_real) - - if type3x($manage_root_ssh_config) == 'string' { - $manage_root_ssh_config_real = str2bool($manage_root_ssh_config) - } else { - $manage_root_ssh_config_real = $manage_root_ssh_config - } - validate_bool($manage_root_ssh_config_real) - - #ssh_config template - validate_string($ssh_config_template) - - #sshd_config template - validate_string($sshd_config_template) - - #loglevel - $supported_loglevel_vals=['QUIET', 'FATAL', 'ERROR', 'INFO', 'VERBOSE'] - validate_re($sshd_config_loglevel, $supported_loglevel_vals) - - #enable hiera merging for groups, users, and config_entries - if $hiera_merge_real == true { - $sshd_config_allowgroups_real = hiera_array('ssh::sshd_config_allowgroups',[]) - $sshd_config_allowusers_real = hiera_array('ssh::sshd_config_allowusers',[]) - $sshd_config_denygroups_real = hiera_array('ssh::sshd_config_denygroups',[]) - $sshd_config_denyusers_real = hiera_array('ssh::sshd_config_denyusers',[]) - $config_entries_real = hiera_hash('ssh::config_entries',{}) - } else { - $sshd_config_allowgroups_real = $sshd_config_allowgroups - $sshd_config_allowusers_real = $sshd_config_allowusers - $sshd_config_denygroups_real = $sshd_config_denygroups - $sshd_config_denyusers_real = $sshd_config_denyusers - $config_entries_real = $config_entries - } - validate_hash($config_entries_real) - - if $sshd_config_denyusers_real != [] { - validate_array($sshd_config_denyusers_real) - } - - if $sshd_config_denygroups_real != [] { - validate_array($sshd_config_denygroups_real) - } - - if $sshd_config_allowusers_real != [] { - validate_array($sshd_config_allowusers_real) - } - - if $sshd_config_allowgroups_real != [] { - validate_array($sshd_config_allowgroups_real) - } - - - if $sshd_config_tcp_keepalive_real != undef { - validate_re($sshd_config_tcp_keepalive_real, '^(yes|no)$', "ssh::sshd_config_tcp_keepalive may be either 'yes', 'no' or 'unset' and is set to <${sshd_config_tcp_keepalive_real}>.") - } - - if $sshd_config_use_privilege_separation != undef { - validate_re($sshd_config_use_privilege_separation, '^(yes|no|sandbox)$', "ssh::sshd_config_use_privilege_separation may be either 'yes', 'no' or 'sandbox' and is set to <${sshd_config_use_privilege_separation}>.") - } - - if $sshd_config_permittunnel_real != undef { - validate_re($sshd_config_permittunnel_real, '^(yes|no|point-to-point|ethernet|unset)$', "ssh::sshd_config_permittunnel may be either 'yes', 'point-to-point', 'ethernet', 'no' or 'unset' and is set to <${sshd_config_permittunnel_real}>.") - } - - if $sshd_config_hostcertificate_real != undef { - if is_array($sshd_config_hostcertificate_real) { - validate_array($sshd_config_hostcertificate_real) - } - validate_absolute_path($sshd_config_hostcertificate_real) - } - - if $sshd_config_trustedusercakeys_real != undef { - # TrustedUserCAKeys may be a path to the keys or 'none' - if $sshd_config_trustedusercakeys_real != 'none' { - validate_absolute_path($sshd_config_trustedusercakeys_real) - } - } - if $sshd_config_key_revocation_list_real != undef { - # RevokedKeys may be a path to the key revocation list or 'none' - if $sshd_config_key_revocation_list_real != 'none' { - validate_absolute_path($sshd_config_key_revocation_list) - } - } - - if $sshd_config_authorized_principals_file_real != undef { - validate_string($sshd_config_authorized_principals_file_real) - } - - if $sshd_config_allowagentforwarding != undef { - validate_re($sshd_config_allowagentforwarding, '^(yes|no)$', "ssh::sshd_config_allowagentforwarding may be either 'yes' or 'no' and is set to <${sshd_config_allowagentforwarding}>.") - } - - package { $packages_real: + package { $packages: ensure => installed, - source => $ssh_package_source_real, - adminfile => $ssh_package_adminfile_real, + source => $package_source, + adminfile => $package_adminfile, } file { 'ssh_config' : ensure => file, - path => $ssh_config_path, - owner => $ssh_config_owner, - group => $ssh_config_group, - mode => $ssh_config_mode, - content => template($ssh_config_template), - require => Package[$packages_real], + path => $config_path, + owner => $config_owner, + group => $config_group, + mode => $config_mode, + content => template('ssh/ssh_config.erb'), + require => Package[$packages], } - file { 'sshd_config' : - ensure => file, - path => $sshd_config_path, - mode => $sshd_config_mode_real, - owner => $sshd_config_owner, - group => $sshd_config_group, - content => template($sshd_config_template), - require => Package[$packages_real], - } + if $manage_root_ssh_config == true { - if $sshd_config_banner != 'none' and $sshd_banner_content != undef { - file { 'sshd_banner' : - ensure => file, - path => $sshd_config_banner, - owner => $sshd_banner_owner, - group => $sshd_banner_group, - mode => $sshd_banner_mode, - content => $sshd_banner_content, - require => Package[$packages_real], + exec { "mkdir_p-${::root_home}/.ssh": + command => "mkdir -p ${::root_home}/.ssh", + unless => "test -d ${::root_home}/.ssh", + path => '/bin:/usr/bin', } - } - - if $manage_root_ssh_config_real == true { - - include ::common - - common::mkdir_p { "${::root_home}/.ssh": } file { 'root_ssh_dir': ensure => directory, @@ -1045,7 +623,7 @@ owner => 'root', group => 'root', mode => '0700', - require => Common::Mkdir_p["${::root_home}/.ssh"], + require => Exec["mkdir_p-${::root_home}/.ssh"], } file { 'root_ssh_config': @@ -1058,25 +636,6 @@ } } - if $manage_service_real { - service { 'sshd_service' : - ensure => $service_ensure, - name => $service_name_real, - enable => $service_enable_real, - hasrestart => $service_hasrestart_real, - hasstatus => $service_hasstatus_real, - subscribe => File['sshd_config'], - } - } - - if $manage_firewall == true { - firewall { '22 open port 22 for SSH': - action => 'accept', - dport => 22, - proto => 'tcp', - } - } - # If either IPv4 or IPv6 stack is not configured on the agent, the # corresponding $::ipaddress(6)? fact is not present. So, we cannot assume # these variables are defined. Getvar (Stdlib 4.13+, ruby 1.8.7+) handles @@ -1086,55 +645,57 @@ else { $host_aliases = [$::hostname, $::ipaddress] } # export each node's ssh key - @@sshkey { $::fqdn : - ensure => $ssh_key_ensure, - host_aliases => $host_aliases, - type => $ssh_key_type, - key => $key, + if $key_export == true { + # ssh_key_type might start with 'ssh-' though facter stores them without + # the 'ssh-' prefix. + #$key_type = delete_regex($ssh_key_type, '^ssh-') + $key_type = 'rsa' + @@sshkey { $::fqdn : + ensure => $ssh_key_ensure, + host_aliases => $host_aliases, + type => $ssh_key_type, + key => $facts['ssh'][$key_type]['key'], + } } file { 'ssh_known_hosts': ensure => file, - path => $ssh_config_global_known_hosts_file, - owner => $ssh_config_global_known_hosts_owner, - group => $ssh_config_global_known_hosts_group, - mode => $ssh_config_global_known_hosts_mode, - require => Package[$packages_real], + path => $global_known_hosts, + owner => $global_known_hosts_owner, + group => $global_known_hosts_group, + mode => $global_known_hosts_mode, + require => Package[$packages], } # import all nodes' ssh keys - if $ssh_key_import_real == true { + if $ssh_key_import == true { Sshkey <<||>> { - target => $ssh_config_global_known_hosts_file, + target => $global_known_hosts, } } # remove ssh key's not managed by puppet resources { 'sshkey': - purge => $purge_keys_real, + purge => $purge_keys, } # manage users' ssh config entries if present - create_resources('ssh::config_entry',$config_entries_real) - - # manage users' ssh authorized keys if present - if $keys != undef { - if $hiera_merge_real == true { - $keys_real = hiera_hash('ssh::keys') - } else { - $keys_real = $keys - notice('Future versions of the ssh module will default ssh::hiera_merge_real to true') + $config_entries.each |$key,$value| { + ssh::config_entry { $key: + * => $value, } - validate_hash($keys_real) - create_resources('ssh_authorized_key', $keys_real) } - if $sshd_addressfamily_real != undef { - if $::osfamily == 'Solaris' { - fail("ssh::sshd_addressfamily is not supported on Solaris and is set to <${sshd_addressfamily}>.") - } else { - validate_re($sshd_addressfamily_real, '^(any|inet|inet6)$', - "ssh::sshd_addressfamily can be undef, 'any', 'inet' or 'inet6' and is set to ${sshd_addressfamily_real}.") + # manage users' ssh authorized keys if present + if $keys.empty == false { + $keys.each |$key,$value| { + ssh_authorized_key { $key: + * => $value, + } } } + + if $manage_server == true { + include ssh::server + } }
diff --git a/manifests/server.pp b/manifests/server.pp new file mode 100644 index 0000000..5d7b3bc --- /dev/null +++ b/manifests/server.pp
@@ -0,0 +1,536 @@ +# @summary Class to manage SSH server +# +# Notes: `Match` attribute is not directly supported as multiple match blocks can +# exist. Use the `custom` parameter for that. +# +# @param packages +# +# @param package_source +# +# @param package_adminfile +# +# @param config_path +# +# @param config_owner +# +# @param config_group +# +# @param config_mode +# +# @param banner_path +# +# @param banner_content +# +# @param banner_owner +# +# @param banner_group +# +# @param banner_mode +# +# @param manage_service +# +# @param service_ensure +# +# @param service_name +# +# @param service_enable +# +# @param service_hasrestart +# +# @param service_hasstatus +# +# @param accept_env +# +# @param address_family +# +# @param allow_agent_forwarding +# +# @param allow_groups +# +# @param allow_stream_local_forwarding +# +# @param allow_tcp_forwarding +# +# @param allow_users +# +# @param authentication_methods +# +# @param authorized_keys_command +# +# @param authorized_keys_command_user +# +# @param authorized_keys_file +# +# @param authorized_principals_command +# +# @param authorized_principals_command_user +# +# @param authorized_principals_file +# +# @param banner +# +# @param ca_signature_algorithms +# +# @param challenge_response_authentication +# +# @param chroot_directory +# +# @param ciphers +# +# @param client_alive_count_max +# +# @param client_alive_interval +# +# @param compression +# +# @param deny_groups +# +# @param deny_users +# +# @param disable_forwarding +# +# @param expose_auth_info +# +# @param fingerprint_hash +# +# @param force_command +# +# @param gateway_ports +# +# @param gss_api_authentication +# +# @param gss_api_cleanup_credentials +# +# @param gss_api_strict_acceptor_check +# +# @param hostbased_accepted_key_types +# +# @param hostbased_authentication +# +# @param hostbased_uses_name_from_packet_only +# +# @param host_certificate +# +# @param host_key +# +# @param host_key_agent +# +# @param host_key_algorithms +# +# @param ignore_rhosts +# +# @param ignore_user_known_hosts +# +# @param ip_qos +# +# @param kbd_interactive_authentication +# +# @param kerberos_authentication +# +# @param kerberos_get_afs_token +# +# @param kerberos_or_local_passwd +# +# @param kerberos_ticket_cleanup +# +# @param kex_algorithms +# +# @param listen_address +# +# @param login_grace_time +# +# @param log_level +# +# @param macs +# +# @param max_auth_tries +# +# @param max_sessions +# +# @param max_startups +# +# @param password_authentication +# +# @param permit_empty_passwords +# +# @param permit_listen +# +# @param permit_root_login +# +# @param permit_tty +# +# @param permit_tunnel +# +# @param permit_user_environment +# +# @param permit_user_rc +# +# @param pid_file +# +# @param port +# +# @param print_last_log +# +# @param print_motd +# +# @param pubkey_accepted_key_types +# +# @param pubkey_authentication +# +# @param rekey_limit +# +# @param revoked_keys +# +# @param rdomain +# +# @param set_env +# +# @param stream_local_bind_mask +# +# @param stream_local_bind_unlink +# +# @param strict_modes +# +# @param subsystem +# +# @param syslog_facility +# +# @param tcp_keep_alive +# +# @param trusted_user_ca_keys +# +# @param use_dns +# +# @param use_pam +# +# @param version_addendum +# +# @param x11_display_offset +# +# @param x11_forwarding +# +# @param x11_use_localhost +# +# @param xauth_location +# +# @param custom +# +class ssh::server ( + Variant[String[1], Array[String[1]]] $packages = 'openssh-server', + Optional[Stdlib::Absolutepath] $package_source = undef, + Optional[Stdlib::Absolutepath] $package_adminfile = undef, + Stdlib::Absolutepath $config_path = '/etc/ssh/sshd_config', + String[1] $config_owner = 'root', + String[1] $config_group = 'root', + Stdlib::Filemode $config_mode = '0600', + Stdlib::Absolutepath $banner_path = '/etc/sshd_banner', + Optional[String[1]] $banner_content = undef, + String[1] $banner_owner = 'root', + String[1] $banner_group = 'root', + Stdlib::Filemode $banner_mode = '0644', + Boolean $manage_service = true, + Stdlib::Ensure::Service $service_ensure = 'running', + String[1] $service_name = 'sshd', + Boolean $service_enable = true, + Boolean $service_hasrestart = true, + Boolean $service_hasstatus = true, + # all paramters below this line are for sshd_config + Optional[Array[String[1]]] $accept_env = undef, + Optional[Enum['any', 'inet', 'inet6']] $address_family = undef, + Optional[Ssh::Yes_no] $allow_agent_forwarding = undef, + Variant[Undef, String[1], Array[String[1]]] $allow_groups = undef, + Optional[Enum['yes', 'all', 'no', 'local', 'remote']] $allow_stream_local_forwarding = undef, + Optional[Enum['yes', 'no', 'local', 'remote']] $allow_tcp_forwarding = undef, + Variant[Undef, String[1], Array[String[1]]] $allow_users = undef, + Optional[Array[String[1]]] $authentication_methods = undef, + Optional[String[1]] $authorized_keys_command = undef, + Optional[String[1]] $authorized_keys_command_user = undef, + Variant[Undef, String[1], Array[String[1]]] $authorized_keys_file = undef, + Optional[String[1]] $authorized_principals_command = undef, + Optional[String[1]] $authorized_principals_command_user = undef, + Optional[String[1]] $authorized_principals_file = undef, + Optional[String[1]] $banner = undef, + Optional[Array[String[1]]] $ca_signature_algorithms = undef, + Optional[String[1]] $challenge_response_authentication = undef, + Optional[String[1]] $chroot_directory = undef, + Optional[Array[String[1]]] $ciphers = undef, + Optional[Integer[0]] $client_alive_count_max = undef, + Optional[Integer[0]] $client_alive_interval = undef, + Optional[Enum['yes', 'delayed', 'no']] $compression = undef, + Variant[Undef, String[1], Array[String[1]]] $deny_groups = undef, + Variant[Undef, String[1], Array[String[1]]] $deny_users = undef, + Optional[Ssh::Yes_no] $disable_forwarding = undef, + Optional[Ssh::Yes_no] $expose_auth_info = undef, + Optional[Enum['md5', 'sha256']] $fingerprint_hash = undef, + Optional[String[1]] $force_command = undef, + Optional[Enum['no', 'yes', 'clientspecified']] $gateway_ports = undef, + Optional[Ssh::Yes_no] $gss_api_authentication = undef, + Optional[Ssh::Yes_no] $gss_api_cleanup_credentials = undef, + Optional[Ssh::Yes_no] $gss_api_strict_acceptor_check = undef, + Optional[Array[String[1]]] $hostbased_accepted_key_types = undef, + Optional[Ssh::Yes_no] $hostbased_authentication = undef, + Optional[Ssh::Yes_no] $hostbased_uses_name_from_packet_only = undef, + Optional[String[1]] $host_certificate = undef, + Optional[Array[String[1]]] $host_key = undef, + Optional[String[1]] $host_key_agent = undef, + Optional[Array[String[1]]] $host_key_algorithms = undef, + Optional[Ssh::Yes_no] $ignore_rhosts = undef, + Optional[Ssh::Yes_no] $ignore_user_known_hosts = undef, + Optional[String[1]] $ip_qos = undef, + Optional[Ssh::Yes_no] $kbd_interactive_authentication = undef, + Optional[Ssh::Yes_no] $kerberos_authentication = undef, + Optional[Ssh::Yes_no] $kerberos_get_afs_token = undef, + Optional[Ssh::Yes_no] $kerberos_or_local_passwd = undef, + Optional[Ssh::Yes_no] $kerberos_ticket_cleanup = undef, + Optional[Array[String[1]]] $kex_algorithms = undef, + Optional[Array[String[1]]] $listen_address = undef, + Optional[Integer[0]] $login_grace_time = undef, + Optional[Ssh::Log_level] $log_level = undef, + Optional[Array[String[1]]] $macs = undef, + Optional[Integer[2]] $max_auth_tries = undef, + Optional[Integer[0]] $max_sessions = undef, + Optional[String[1]] $max_startups = undef, + Optional[Ssh::Yes_no] $password_authentication = undef, + Optional[Ssh::Yes_no] $permit_empty_passwords = undef, + Variant[Undef, String[1], Array[String[1]]] $permit_listen = undef, + Optional[Ssh::Permit_root_login] $permit_root_login = undef, + Optional[Ssh::Yes_no] $permit_tty = undef, + Optional[Enum['yes', 'point-to-point', 'ethernet', 'no']] $permit_tunnel = undef, + Optional[String[1]] $permit_user_environment = undef, + Optional[Ssh::Yes_no] $permit_user_rc = undef, + Optional[String[1]] $pid_file = undef, + Optional[Stdlib::Port] $port = undef, #TODO, this can be specified multiple times + Optional[Ssh::Yes_no] $print_last_log = undef, + Optional[Ssh::Yes_no] $print_motd = undef, + Optional[Array[String[1]]] $pubkey_accepted_key_types = undef, + Optional[Ssh::Yes_no] $pubkey_authentication = undef, + Optional[String[1]] $rekey_limit = undef, + Optional[String[1]] $revoked_keys = undef, + Optional[String[1]] $rdomain = undef, + Optional[String[1]] $set_env = undef, + Optional[Pattern[/^[0-7]{4}$/]] $stream_local_bind_mask = undef, + Optional[Ssh::Yes_no] $stream_local_bind_unlink = undef, + Optional[Ssh::Yes_no] $strict_modes = undef, + Optional[String[1]] $subsystem = undef, + Optional[Ssh::Syslog_facility] $syslog_facility = undef, + Optional[Ssh::Yes_no] $tcp_keep_alive = undef, + Optional[String[1]] $trusted_user_ca_keys = undef, + Optional[Ssh::Yes_no] $use_dns = undef, + Optional[Ssh::Yes_no] $use_pam = undef, + Optional[String[1]] $version_addendum = undef, + Optional[Integer[0]] $x11_display_offset = undef, + Optional[Ssh::Yes_no] $x11_forwarding = undef, + Optional[Ssh::Yes_no] $x11_use_localhost = undef, + Optional[String[1]] $xauth_location = undef, + # custom is a string that allows for multiple lines to be appended to end of + # the sshd_config file. + Optional[String[1]] $custom = undef, +) { + +# if $authorized_keys_command_user != undef and $authorized_keys_command == undef { +# fail("If AuthorizedKeysCommand is specified but AuthorizedKeysCommandUser is not, then sshd(8) will refuse to start. authorized_keys_command_user = <${authorized_keys_command_user}> and authorized_keys_command = <${authorized_keys_command}>") +# } +# +# if $authorized_principals_command_user != undef and $authorized_principals_command == undef { +# fail("If AuthorizedPrincipalsCommand is specified but AuthorizedPrincipalsCommandUser is not, then sshd(8) will refuse to start. authorized_principals_command_user = <${authorized_principals_command_user}> and authorized_principals_command = <${authorized_principals_command}>") +# } + +# TODO: This huge case statement is getting transitioned to hiera + case $facts['os']['family'] { + 'RedHat': {} + 'Suse': { + $default_packages = 'openssh' + $default_service_name = 'sshd' + $default_ssh_config_hash_known_hosts = 'no' + $default_ssh_package_source = undef + $default_ssh_package_adminfile = undef + $default_ssh_sendenv = true + $default_ssh_config_forward_x11_trusted = 'yes' + $default_sshd_config_mode = '0600' + $default_sshd_config_use_dns = 'yes' + $default_sshd_config_xauth_location = '/usr/bin/xauth' + $default_sshd_use_pam = 'yes' + $default_sshd_gssapikeyexchange = undef + $default_sshd_pamauthenticationviakbdint = undef + $default_sshd_gssapicleanupcredentials = 'yes' + $default_sshd_acceptenv = true + $default_service_hasstatus = true + $default_sshd_config_serverkeybits = '1024' + $default_sshd_config_hostkey = [ '/etc/ssh/ssh_host_rsa_key' ] + $default_sshd_addressfamily = 'any' + $default_sshd_config_tcp_keepalive = 'yes' + $default_sshd_config_permittunnel = 'no' + case $::architecture { + 'x86_64': { + if ($::operatingsystem == 'SLES') and ($::operatingsystemrelease =~ /^12\./) { + $default_sshd_config_subsystem_sftp = '/usr/lib/ssh/sftp-server' + } else { + $default_sshd_config_subsystem_sftp = '/usr/lib64/ssh/sftp-server' + } + } + 'i386' : { + $default_sshd_config_subsystem_sftp = '/usr/lib/ssh/sftp-server' + } + default: { + fail("ssh supports architectures x86_64 and i386 for Suse. Detected architecture is <${::architecture}>.") + } + } + } + 'Debian': { + # Ubuntu 16.04 + if $::operatingsystemrelease == '16.04' { + $default_sshd_config_hostkey = [ + '/etc/ssh/ssh_host_rsa_key', + '/etc/ssh/ssh_host_dsa_key', + '/etc/ssh/ssh_host_ecdsa_key', + '/etc/ssh/ssh_host_ed25519_key', + ] + $default_ssh_config_hash_known_hosts = 'yes' + $default_sshd_config_xauth_location = undef + } else { + $default_sshd_config_hostkey = [ '/etc/ssh/ssh_host_rsa_key' ] + $default_ssh_config_hash_known_hosts = 'no' + $default_sshd_config_xauth_location = '/usr/bin/xauth' + } + $default_packages = ['openssh-server', + 'openssh-client'] + $default_service_name = 'ssh' + $default_ssh_config_forward_x11_trusted = 'yes' + $default_ssh_package_source = undef + $default_ssh_package_adminfile = undef + $default_ssh_sendenv = true + $default_sshd_config_subsystem_sftp = '/usr/lib/openssh/sftp-server' + $default_sshd_config_mode = '0600' + $default_sshd_config_use_dns = 'yes' + $default_sshd_use_pam = 'yes' + $default_sshd_gssapikeyexchange = undef + $default_sshd_pamauthenticationviakbdint = undef + $default_sshd_gssapicleanupcredentials = 'yes' + $default_sshd_acceptenv = true + $default_service_hasstatus = true + $default_sshd_config_serverkeybits = '1024' + $default_sshd_addressfamily = 'any' + $default_sshd_config_tcp_keepalive = 'yes' + $default_sshd_config_permittunnel = 'no' + } + 'Solaris': { + $default_ssh_config_hash_known_hosts = undef + $default_ssh_sendenv = false + $default_ssh_config_forward_x11_trusted = undef + $default_sshd_config_subsystem_sftp = '/usr/lib/ssh/sftp-server' + $default_sshd_config_mode = '0644' + $default_sshd_config_use_dns = undef + $default_sshd_config_xauth_location = '/usr/openwin/bin/xauth' + $default_sshd_use_pam = undef + $default_sshd_gssapikeyexchange = 'yes' + $default_sshd_pamauthenticationviakbdint = 'yes' + $default_sshd_gssapicleanupcredentials = undef + $default_sshd_acceptenv = false + $default_sshd_config_serverkeybits = '768' + $default_ssh_package_adminfile = undef + $default_sshd_config_hostkey = [ '/etc/ssh/ssh_host_rsa_key' ] + $default_sshd_addressfamily = undef + $default_sshd_config_tcp_keepalive = undef + $default_sshd_config_permittunnel = undef + case $::kernelrelease { + '5.11': { + $default_packages = ['network/ssh', + 'network/ssh/ssh-key', + 'service/network/ssh'] + $default_service_name = 'ssh' + $default_service_hasstatus = true + $default_ssh_package_source = undef + } + '5.10': { + $default_packages = ['SUNWsshcu', + 'SUNWsshdr', + 'SUNWsshdu', + 'SUNWsshr', + 'SUNWsshu'] + $default_service_name = 'ssh' + $default_service_hasstatus = true + $default_ssh_package_source = '/var/spool/pkg' + } + '5.9' : { + $default_packages = ['SUNWsshcu', + 'SUNWsshdr', + 'SUNWsshdu', + 'SUNWsshr', + 'SUNWsshu'] + $default_service_name = 'sshd' + $default_service_hasstatus = false + $default_ssh_package_source = '/var/spool/pkg' + } + default: { + fail('ssh module supports Solaris kernel release 5.9, 5.10 and 5.11.') + } + } + } + default: { + fail("ssh supports osfamilies RedHat, Suse, Debian and Solaris. Detected os.family is <${facts['os']['family']}>.") + } + } + + if "${::ssh_version}" =~ /^OpenSSH/ { # lint:ignore:only_variable_string + $ssh_version_array = split($::ssh_version_numeric, '\.') + $ssh_version_maj_int = 0 + $ssh_version_array[0] + $ssh_version_min_int = 0 + $ssh_version_array[1] + if $ssh_version_maj_int > 5 { + $default_ssh_config_use_roaming = 'no' + } elsif $ssh_version_maj_int == 5 and $ssh_version_min_int >= 4 { + $default_ssh_config_use_roaming = 'no' + } else { + $default_ssh_config_use_roaming = 'unset' + } + } else { + $default_ssh_config_use_roaming = 'unset' + } + + package { $packages: + ensure => installed, + source => $package_source, + adminfile => $package_adminfile, + } + + file { 'sshd_config' : + ensure => file, + path => $config_path, + mode => $config_mode, + owner => $config_owner, + group => $config_group, + content => template('ssh/sshd_config.erb'), + require => Package[$packages], + } + + if $banner_content != undef { + file { 'sshd_banner' : + ensure => file, + path => $banner_path, + owner => $banner_owner, + group => $banner_group, + mode => $banner_mode, + content => $banner_content, + require => Package[$packages], + } + } + + if $manage_service { + service { 'sshd_service' : + ensure => $service_ensure, + name => $service_name, + enable => $service_enable, + hasrestart => $service_hasrestart, + hasstatus => $service_hasstatus, + subscribe => File['sshd_config'], + } + } + + # TODO: remove and document that the code will not check these types of + # things. It introduces too much complexity here and in the testing. Anyone + # using this would test their own custom options to ensure they work anyhow. + if $address_family != undef { + if $facts['os']['family'] == 'Solaris' { + fail("address_family is not supported on Solaris and is set to <${address_family}>.") + } + } +}
diff --git a/metadata.json b/metadata.json index 3ca9272..e7857e3 100644 --- a/metadata.json +++ b/metadata.json
@@ -1,6 +1,6 @@ { "name": "ghoneycutt-ssh", - "version": "3.61.0", + "version": "4.0.0", "author": "ghoneycutt", "summary": "Manages SSH", "license": "Apache-2.0", @@ -10,7 +10,7 @@ "requirements": [ { "name": "puppet", - "version_requirement": ">= 3.8.7 < 7.0.0" + "version_requirement": ">= 5.5.10 < 7.0.0" } ], "operatingsystem_support": [ @@ -25,7 +25,6 @@ { "operatingsystem": "RedHat", "operatingsystemrelease": [ - "5", "6", "7" ] @@ -33,7 +32,6 @@ { "operatingsystem": "CentOS", "operatingsystemrelease": [ - "5", "6", "7" ] @@ -41,7 +39,6 @@ { "operatingsystem": "OracleLinux", "operatingsystemrelease": [ - "5", "6", "7" ] @@ -49,7 +46,6 @@ { "operatingsystem": "Scientific", "operatingsystemrelease": [ - "5", "6", "7" ] @@ -90,10 +86,8 @@ ], "description": "Manage SSH", "dependencies": [ - {"name":"puppetlabs/stdlib","version_requirement":">= 4.6.0 < 6.0.0"}, - {"name":"puppetlabs/concat","version_requirement":">= 2.0.0 < 6.0.0"}, - {"name":"ghoneycutt/common","version_requirement":">= 1.4.1 < 2.0.0"}, - {"name":"puppetlabs/firewall","version_requirement":">= 1.9.0 < 2.0.0"}, - {"name":"puppetlabs/sshkeys_core","version_requirement":">= 1.0.1 <2.0.0"} + {"name":"puppetlabs/stdlib","version_requirement":">= 5.2.0 < 6.0.0"}, + {"name":"puppetlabs/concat","version_requirement":">= 5.2.0 < 6.0.0"}, + {"name":"puppetlabs/sshkeys_core","version_requirement":">= 1.0.2 < 2.0.0"} ] }
diff --git a/spec/acceptance/nodesets/centos-6.yml b/spec/acceptance/nodesets/centos-6.yml new file mode 100644 index 0000000..dbafe0c --- /dev/null +++ b/spec/acceptance/nodesets/centos-6.yml
@@ -0,0 +1,20 @@ +HOSTS: + centos-6: + roles: + - agent + platform: el-6-x86_64 + hypervisor: docker + image: centos:6 + docker_preserve_image: true + docker_cmd: + - '/sbin/init' + docker_image_commands: + - 'yum install -y tar wget cronie git' + docker_container_name: 'ssh-el6' +CONFIG: + log_level: debug + type: foss +ssh: + password: root + auth_methods: ["password"] +
diff --git a/spec/acceptance/nodesets/centos-7.yml b/spec/acceptance/nodesets/centos-7.yml new file mode 100644 index 0000000..983b909 --- /dev/null +++ b/spec/acceptance/nodesets/centos-7.yml
@@ -0,0 +1,20 @@ +HOSTS: + centos-7: + roles: + - agent + platform: el-7-x86_64 + hypervisor: docker + image: centos:7 + docker_preserve_image: true + docker_cmd: + - '/usr/sbin/init' + docker_image_commands: + - 'yum install -y tar wget cronie git iproute' + docker_container_name: 'ssh-el7' +CONFIG: + log_level: debug + type: foss +ssh: + password: root + auth_methods: ["password"] +
diff --git a/spec/acceptance/nodesets/debian-8.yml b/spec/acceptance/nodesets/debian-8.yml new file mode 100644 index 0000000..d6c5b87 --- /dev/null +++ b/spec/acceptance/nodesets/debian-8.yml
@@ -0,0 +1,25 @@ +HOSTS: + debian-8: + roles: + - agent + platform: debian-8-amd64 + hypervisor: docker + image: debian:8 + docker_preserve_image: true + docker_cmd: + - '/sbin/init' + docker_image_commands: + - 'apt-get install -y tar wget cron git net-tools locales' + - 'rm -f /usr/sbin/policy-rc.d' + - 'echo "LC_ALL=en_US.UTF-8" >> /etc/environment' + - 'echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen' + - 'echo "LANG=en_US.UTF-8" > /etc/locale.conf' + - 'locale-gen en_US.UTF-8' + docker_container_name: 'ssh-debian8' +CONFIG: + log_level: debug + type: foss +ssh: + password: root + auth_methods: ["password"] +
diff --git a/spec/acceptance/nodesets/debian-9.yml b/spec/acceptance/nodesets/debian-9.yml new file mode 100644 index 0000000..84ae7f7 --- /dev/null +++ b/spec/acceptance/nodesets/debian-9.yml
@@ -0,0 +1,24 @@ +HOSTS: + debian-9: + roles: + - agent + platform: debian-9-amd64 + hypervisor: docker + image: debian:9 + docker_preserve_image: true + docker_cmd: + - '/sbin/init' + docker_image_commands: + - 'apt-get install -y tar wget cron git net-tools systemd-sysv locales' + - 'echo "LC_ALL=en_US.UTF-8" >> /etc/environment' + - 'echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen' + - 'echo "LANG=en_US.UTF-8" > /etc/locale.conf' + - 'locale-gen en_US.UTF-8' + docker_container_name: 'ssh-debian9' +CONFIG: + log_level: debug + type: foss +ssh: + password: root + auth_methods: ["password"] +
diff --git a/spec/acceptance/nodesets/default.yml b/spec/acceptance/nodesets/default.yml new file mode 100644 index 0000000..983b909 --- /dev/null +++ b/spec/acceptance/nodesets/default.yml
@@ -0,0 +1,20 @@ +HOSTS: + centos-7: + roles: + - agent + platform: el-7-x86_64 + hypervisor: docker + image: centos:7 + docker_preserve_image: true + docker_cmd: + - '/usr/sbin/init' + docker_image_commands: + - 'yum install -y tar wget cronie git iproute' + docker_container_name: 'ssh-el7' +CONFIG: + log_level: debug + type: foss +ssh: + password: root + auth_methods: ["password"] +
diff --git a/spec/acceptance/nodesets/ubuntu-1404.yml b/spec/acceptance/nodesets/ubuntu-1404.yml new file mode 100644 index 0000000..100656e --- /dev/null +++ b/spec/acceptance/nodesets/ubuntu-1404.yml
@@ -0,0 +1,21 @@ +HOSTS: + ubuntu-1404: + roles: + - agent + platform: ubuntu-14.04-amd64 + hypervisor : docker + image: ubuntu:14.04 + docker_preserve_image: true + docker_cmd: '["/sbin/init"]' + docker_image_commands: + - 'rm /usr/sbin/policy-rc.d' + - 'rm /sbin/initctl; dpkg-divert --rename --remove /sbin/initctl' + - 'apt-get install -y -q net-tools wget' + - 'locale-gen en_US.UTF-8' +CONFIG: + type: foss + log_level: debug +ssh: + password: root + auth_methods: ["password"] +
diff --git a/spec/acceptance/nodesets/ubuntu-1604.yml b/spec/acceptance/nodesets/ubuntu-1604.yml new file mode 100644 index 0000000..9763af0 --- /dev/null +++ b/spec/acceptance/nodesets/ubuntu-1604.yml
@@ -0,0 +1,19 @@ +HOSTS: + ubuntu-1604: + roles: + - agent + platform: ubuntu-16.04-amd64 + hypervisor : docker + image: ubuntu:16.04 + docker_preserve_image: true + docker_cmd: '["/sbin/init"]' + docker_image_commands: + - 'apt-get install -y -q net-tools wget locales' + - 'locale-gen en_US.UTF-8' +CONFIG: + type: foss + log_level: debug +ssh: + password: root + auth_methods: ["password"] +
diff --git a/spec/acceptance/nodesets/ubuntu-1804.yml b/spec/acceptance/nodesets/ubuntu-1804.yml new file mode 100644 index 0000000..030af55 --- /dev/null +++ b/spec/acceptance/nodesets/ubuntu-1804.yml
@@ -0,0 +1,19 @@ +HOSTS: + ubuntu-1804: + roles: + - agent + platform: ubuntu-18.04-amd64 + hypervisor : docker + image: ubuntu:18.04 + docker_preserve_image: true + docker_cmd: '["/sbin/init"]' + docker_image_commands: + - 'apt-get install -y -q net-tools wget locales' + - 'locale-gen en_US.UTF-8' +CONFIG: + type: foss + log_level: debug +ssh: + password: root + auth_methods: ["password"] +
diff --git a/spec/acceptance/ssh_spec.rb b/spec/acceptance/ssh_spec.rb new file mode 100644 index 0000000..e05f6cf --- /dev/null +++ b/spec/acceptance/ssh_spec.rb
@@ -0,0 +1,40 @@ +require 'spec_helper_acceptance' + +describe 'ssh class' do + context 'ssh' do + context 'with default values for all parameters' do + context 'it should be idempotent' do +# if fact('osfamily') == 'Debian' and fact('operatingsystemrelease') == '16.04' +# before { skip('Ubuntu 16.04 has a systemd issue that makes setting the service enable not idempotent. Skipping test.') } +# end + + it 'should work with no errors' do + pp = <<-EOS + include ssh + EOS + + # Run it twice and test for idempotency + apply_manifest(pp, :catch_failures => true) + apply_manifest(pp, :catch_changes => true) + end + end + + context 'should contain resources' do + pp = <<-EOS + include ssh + EOS + + apply_manifest(pp, :catch_failures => true) + + describe package('openssh-clients') do + it { is_expected.to be_installed } + end + + describe service('sshd') do + it { is_expected.to be_running } + it { is_expected.to be_enabled } + end + end + end + end +end
diff --git a/spec/classes/init_spec.rb b/spec/classes/init_spec.rb index 5ca3914..800d98c 100644 --- a/spec/classes/init_spec.rb +++ b/spec/classes/init_spec.rb
@@ -6,14 +6,22 @@ :fqdn => 'monkey.example.com', :hostname => 'monkey', :ipaddress => '127.0.0.1', - :lsbmajdistrelease => '6', - :operatingsystemrelease => '6.7', - :osfamily => 'RedHat', + :os => { + :family => 'RedHat', + :release => { + :major => '7', + }, + }, :root_home => '/root', :specific => 'dummy', :ssh_version => 'OpenSSH_6.6p1', :ssh_version_numeric => '6.6', :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==', + :ssh => { + :rsa => { + :key => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1 AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==', + } + } } default_solaris_facts = { @@ -27,248 +35,187 @@ :ssh_version => 'Sun_SSH_2.2', :ssh_version_numeric => '2.2', :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==', + :ssh => { + :rsa => { + :key => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1 AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==', + } + } } let(:facts) { default_facts } osfamily_matrix = { - 'Debian-7' => { - :architecture => 'x86_64', - :osfamily => 'Debian', - :operatingsystemrelease => '7', - :ssh_version => 'OpenSSH_6.0p1', - :ssh_version_numeric => '6.0', - :ssh_packages => ['openssh-server', 'openssh-client'], - :sshd_config_mode => '0600', - :sshd_service_name => 'ssh', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_debian', - :ssh_config_fixture => 'ssh_config_debian', - }, - 'Debian-8' => { - :architecture => 'x86_64', - :osfamily => 'Debian', - :operatingsystemrelease => '8', - :ssh_version => 'OpenSSH_6.7p1', - :ssh_version_numeric => '8.11', - :ssh_packages => ['openssh-server', 'openssh-client'], - :sshd_config_mode => '0600', - :sshd_service_name => 'ssh', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_debian8', - :ssh_config_fixture => 'ssh_config_debian8', - }, - 'Debian-9' => { - :architecture => 'x86_64', - :osfamily => 'Debian', - :operatingsystemrelease => '9', - :ssh_version => 'OpenSSH_7.4p1', - :ssh_version_numeric => '7.4', - :ssh_packages => ['openssh-server', 'openssh-client'], - :sshd_config_mode => '0600', - :sshd_service_name => 'ssh', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_debian9', - :ssh_config_fixture => 'ssh_config_debian9', - }, +# 'Debian-7' => { +# :architecture => 'x86_64', +# :osfamily => 'Debian', +# :operatingsystemrelease => '7', +# :ssh_version => 'OpenSSH_6.0p1', +# :ssh_version_numeric => '6.0', +# :ssh_packages => ['openssh-server', 'openssh-client'], +# :ssh_config_fixture => 'ssh_config_debian', +# }, +# 'Debian-8' => { +# :architecture => 'x86_64', +# :osfamily => 'Debian', +# :operatingsystemrelease => '8', +# :ssh_version => 'OpenSSH_6.7p1', +# :ssh_version_numeric => '8.11', +# :ssh_packages => ['openssh-server', 'openssh-client'], +# :ssh_config_fixture => 'ssh_config_debian8', +# }, +# 'Debian-9' => { +# :architecture => 'x86_64', +# :osfamily => 'Debian', +# :operatingsystemrelease => '9', +# :ssh_version => 'OpenSSH_7.4p1', +# :ssh_version_numeric => '7.4', +# :ssh_packages => ['openssh-server', 'openssh-client'], +# :ssh_config_fixture => 'ssh_config_debian9', +# }, 'RedHat-5' => { :architecture => 'x86_64', - :osfamily => 'RedHat', - :operatingsystemrelease => '5.11', + :os => { + :family => 'RedHat', + :release => { + :major => '5', + }, + }, :ssh_version => 'OpenSSH_4.3p2', :ssh_version_numeric => '4.3', - :ssh_packages => ['openssh-server', 'openssh-clients'], - :sshd_config_mode => '0600', - :sshd_service_name => 'sshd', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_rhel', - :ssh_config_fixture => 'ssh_config_rhel_old', + :ssh_packages => ['openssh-clients'], + :ssh_config_fixture => 'ssh_config_el5', }, - 'RedHat-6' => { + 'EL-6' => { :architecture => 'x86_64', - :osfamily => 'RedHat', - :operatingsystemrelease => '6.7', + :os => { + :family => 'RedHat', + :release => { + :major => '6', + }, + }, :ssh_version => 'OpenSSH_5.3p1', :ssh_version_numeric => '5.3', - :ssh_packages => ['openssh-server', 'openssh-clients'], - :sshd_config_mode => '0600', - :sshd_service_name => 'sshd', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_rhel', - :ssh_config_fixture => 'ssh_config_rhel_old', + :ssh_packages => ['openssh-clients'], + :ssh_config_fixture => 'ssh_config_el6', }, - 'RedHat-7' => { + 'EL-7' => { :architecture => 'x86_64', - :osfamily => 'RedHat', - :operatingsystemrelease => '7.2', - :ssh_version => 'OpenSSH_6.6p1', - :ssh_version_numeric => '6.6', - :ssh_packages => ['openssh-server', 'openssh-clients'], - :sshd_config_mode => '0600', - :sshd_service_name => 'sshd', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_rhel', - :ssh_config_fixture => 'ssh_config_rhel', + :os => { + :family => 'RedHat', + :release => { + :major => '7', + }, + }, + :ssh_version => 'OpenSSH_7.4p1', + :ssh_version_numeric => '7.4', + :ssh_packages => ['openssh-clients'], + :ssh_config_fixture => 'ssh_config_el7', }, - 'RedHat-7.4' => { - :architecture => 'x86_64', - :osfamily => 'RedHat', - :operatingsystemrelease => '7.4', - :ssh_version => 'OpenSSH_6.6p1', - :ssh_version_numeric => '6.6', - :ssh_packages => ['openssh-server', 'openssh-clients'], - :sshd_config_mode => '0600', - :sshd_service_name => 'sshd', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_rhel7', - :ssh_config_fixture => 'ssh_config_rhel', - }, - 'Suse-10-x86_64' => { - :architecture => 'x86_64', - :osfamily => 'Suse', - :operatingsystem => 'SLES', - :operatingsystemrelease => '10.4', - :ssh_version => 'OpenSSH_5.1p1', - :ssh_version_numeric => '5.1', - :ssh_packages => ['openssh'], - :sshd_config_mode => '0600', - :sshd_service_name => 'sshd', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_suse_x86_64', - :ssh_config_fixture => 'ssh_config_suse_old', - }, - 'Suse-10-i386' => { - :architecture => 'i386', - :osfamily => 'Suse', - :operatingsystem => 'SLES', - :operatingsystemrelease => '10.4', - :ssh_version => 'OpenSSH_5.1p1', - :ssh_version_numeric => '5.1', - :ssh_packages => ['openssh'], - :sshd_config_mode => '0600', - :sshd_service_name => 'sshd', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_suse_i386', - :ssh_config_fixture => 'ssh_config_suse_old', - }, - 'Suse-11-x86_64' => { - :architecture => 'x86_64', - :osfamily => 'Suse', - :operatingsystem => 'SLES', - :operatingsystemrelease => '11.4', - :ssh_version => 'OpenSSH_6.6.1p1', - :ssh_version_numeric => '6.6', - :ssh_packages => ['openssh'], - :sshd_config_mode => '0600', - :sshd_service_name => 'sshd', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_suse_x86_64', - :ssh_config_fixture => 'ssh_config_suse', - }, - 'Suse-11-i386' => { - :architecture => 'i386', - :osfamily => 'Suse', - :operatingsystem => 'SLES', - :operatingsystemrelease => '11.4', - :ssh_version => 'OpenSSH_6.6.1p1', - :ssh_version_numeric => '6.6', - :ssh_packages => ['openssh'], - :sshd_config_mode => '0600', - :sshd_service_name => 'sshd', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_suse_i386', - :ssh_config_fixture => 'ssh_config_suse', - }, - 'Suse-12-x86_64' => { - :architecture => 'x86_64', - :osfamily => 'Suse', - :operatingsystem => 'SLES', - :operatingsystemrelease => '12.0', - :ssh_version => 'OpenSSH_6.6.1p1', - :ssh_version_numeric => '6.6', - :ssh_packages => ['openssh'], - :sshd_config_mode => '0600', - :sshd_service_name => 'sshd', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_sles_12_x86_64', - :ssh_config_fixture => 'ssh_config_suse', - }, - 'Solaris-5.11' => { - :architecture => 'i86pc', - :osfamily => 'Solaris', - :kernelrelease => '5.11', - :ssh_version => 'Sun_SSH_2.2', - :ssh_version_numeric => '2.2', - :ssh_packages => ['network/ssh', 'network/ssh/ssh-key', 'service/network/ssh'], - :sshd_config_mode => '0644', - :sshd_service_name => 'ssh', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_solaris', - :ssh_config_fixture => 'ssh_config_solaris', - }, - 'Solaris-5.10' => { - :architecture => 'i86pc', - :osfamily => 'Solaris', - :kernelrelease => '5.10', - :ssh_version => 'Sun_SSH_2.2', - :ssh_version_numeric => '2.2', - :ssh_packages => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'], - :sshd_config_mode => '0644', - :sshd_service_name => 'ssh', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_solaris', - :ssh_config_fixture => 'ssh_config_solaris', - }, - 'Solaris-5.9' => { - :architecture => 'i86pc', - :osfamily => 'Solaris', - :kernelrelease => '5.9', - :ssh_version => 'Sun_SSH_2.2', - :ssh_version_numeric => '2.2', - :ssh_packages => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'], - :sshd_config_mode => '0644', - :sshd_service_name => 'sshd', - :sshd_service_hasstatus => false, - :sshd_config_fixture => 'sshd_config_solaris', - :ssh_config_fixture => 'ssh_config_solaris', - }, - 'Ubuntu-1604' => { - :architecture => 'x86_64', - :osfamily => 'Debian', - :operatingsystemrelease => '16.04', - :ssh_version => 'OpenSSH_7.2p2', - :ssh_version_numeric => '7.2', - :ssh_packages => ['openssh-server', 'openssh-client'], - :sshd_config_mode => '0600', - :sshd_service_name => 'ssh', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_ubuntu1604', - :ssh_config_fixture => 'ssh_config_ubuntu1604', - }, - 'Ubuntu-1804' => { - :architecture => 'x86_64', - :osfamily => 'Debian', - :operatingsystemrelease => '18.04', - :ssh_version => 'OpenSSH_7.6p1', - :ssh_version_numeric => '7.6', - :ssh_packages => ['openssh-server', 'openssh-client'], - :sshd_config_mode => '0600', - :sshd_service_name => 'ssh', - :sshd_service_hasstatus => true, - :sshd_config_fixture => 'sshd_config_ubuntu1804', - :ssh_config_fixture => 'ssh_config_ubuntu1804', - }, +# 'Suse-10-x86_64' => { +# :architecture => 'x86_64', +# :osfamily => 'Suse', +# :operatingsystem => 'SLES', +# :operatingsystemrelease => '10.4', +# :ssh_version => 'OpenSSH_5.1p1', +# :ssh_version_numeric => '5.1', +# :ssh_packages => ['openssh'], +# :ssh_config_fixture => 'ssh_config_suse_old', +# }, +# 'Suse-10-i386' => { +# :architecture => 'i386', +# :osfamily => 'Suse', +# :operatingsystem => 'SLES', +# :operatingsystemrelease => '10.4', +# :ssh_version => 'OpenSSH_5.1p1', +# :ssh_version_numeric => '5.1', +# :ssh_packages => ['openssh'], +# :ssh_config_fixture => 'ssh_config_suse_old', +# }, +# 'Suse-11-x86_64' => { +# :architecture => 'x86_64', +# :osfamily => 'Suse', +# :operatingsystem => 'SLES', +# :operatingsystemrelease => '11.4', +# :ssh_version => 'OpenSSH_6.6.1p1', +# :ssh_version_numeric => '6.6', +# :ssh_packages => ['openssh'], +# :ssh_config_fixture => 'ssh_config_suse', +# }, +# 'Suse-11-i386' => { +# :architecture => 'i386', +# :osfamily => 'Suse', +# :operatingsystem => 'SLES', +# :operatingsystemrelease => '11.4', +# :ssh_version => 'OpenSSH_6.6.1p1', +# :ssh_version_numeric => '6.6', +# :ssh_packages => ['openssh'], +# :ssh_config_fixture => 'ssh_config_suse', +# }, +# 'Suse-12-x86_64' => { +# :architecture => 'x86_64', +# :osfamily => 'Suse', +# :operatingsystem => 'SLES', +# :operatingsystemrelease => '12.0', +# :ssh_version => 'OpenSSH_6.6.1p1', +# :ssh_version_numeric => '6.6', +# :ssh_packages => ['openssh'], +# :ssh_config_fixture => 'ssh_config_suse', +# }, +# 'Solaris-5.11' => { +# :architecture => 'i86pc', +# :osfamily => 'Solaris', +# :kernelrelease => '5.11', +# :ssh_version => 'Sun_SSH_2.2', +# :ssh_version_numeric => '2.2', +# :ssh_packages => ['network/ssh', 'network/ssh/ssh-key', 'service/network/ssh'], +# :ssh_config_fixture => 'ssh_config_solaris', +# }, +# 'Solaris-5.10' => { +# :architecture => 'i86pc', +# :osfamily => 'Solaris', +# :kernelrelease => '5.10', +# :ssh_version => 'Sun_SSH_2.2', +# :ssh_version_numeric => '2.2', +# :ssh_packages => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'], +# :ssh_config_fixture => 'ssh_config_solaris', +# }, +# 'Solaris-5.9' => { +# :architecture => 'i86pc', +# :osfamily => 'Solaris', +# :kernelrelease => '5.9', +# :ssh_version => 'Sun_SSH_2.2', +# :ssh_version_numeric => '2.2', +# :ssh_packages => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'], +# :ssh_config_fixture => 'ssh_config_solaris', +# }, +# 'Ubuntu-1604' => { +# :architecture => 'x86_64', +# :osfamily => 'Debian', +# :operatingsystemrelease => '16.04', +# :ssh_version => 'OpenSSH_7.2p2', +# :ssh_version_numeric => '7.2', +# :ssh_packages => ['openssh-server', 'openssh-client'], +# :ssh_config_fixture => 'ssh_config_ubuntu1604', +# }, +# 'Ubuntu-1804' => { +# :architecture => 'x86_64', +# :osfamily => 'Debian', +# :operatingsystemrelease => '18.04', +# :ssh_version => 'OpenSSH_7.6p1', +# :ssh_version_numeric => '7.6', +# :ssh_packages => ['openssh-server', 'openssh-client'], +# :ssh_config_fixture => 'ssh_config_ubuntu1804', +# }, } osfamily_matrix.each do |os, facts| context "with default params on osfamily #{os}" do - let(:facts) { default_facts.merge( facts )} + let(:facts) { default_facts.merge( facts ) } it { should compile.with_all_deps } - it { should contain_class('ssh')} - - it { should_not contain_class('common')} + it { should contain_class('ssh') } + it { should contain_class('ssh::server') } facts[:ssh_packages].each do |pkg| it { @@ -279,6 +226,25 @@ end it { + should contain_file('ssh_config').with({ + 'ensure' => 'file', + 'path' => '/etc/ssh/ssh_config', + 'owner' => 'root', + 'group' => 'root', + 'mode' => '0644', + }) + } + + facts[:ssh_packages].each do |pkg| + it { + should contain_file('ssh_config').that_requires("Package[#{pkg}]") + } + end + + ssh_config_fixture = File.read(fixtures("#{facts[:ssh_config_fixture]}_sorted")) + it { should contain_file('ssh_config').with_content(ssh_config_fixture) } + + it { should contain_file('ssh_known_hosts').with({ 'ensure' => 'file', 'path' => '/etc/ssh/ssh_known_hosts', @@ -294,54 +260,11 @@ } end - it { - should contain_file('ssh_config').with({ - 'ensure' => 'file', - 'path' => '/etc/ssh/ssh_config', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - }) - } - - ssh_config_fixture = File.read(fixtures(facts[:ssh_config_fixture])) - it { should contain_file('ssh_config').with_content(ssh_config_fixture) } - - facts[:ssh_packages].each do |pkg| - it { - should contain_file('ssh_config').that_requires("Package[#{pkg}]") - } - end - - it { - should contain_file('sshd_config').with({ - 'ensure' => 'file', - 'path' => '/etc/ssh/sshd_config', - 'owner' => 'root', - 'group' => 'root', - 'mode' => facts[:sshd_config_mode], - }) - } - - facts[:ssh_packages].each do |pkg| - it { - should contain_file('sshd_config').that_requires("Package[#{pkg}]") - } - end - - sshd_config_fixture = File.read(fixtures(facts[:sshd_config_fixture])) - it { should contain_file('sshd_config').with_content(sshd_config_fixture) } - - it { - should contain_service('sshd_service').with({ - 'ensure' => 'running', - 'name' => facts[:sshd_service_name], - 'enable' => 'true', - 'hasrestart' => 'true', - 'hasstatus' => facts[:sshd_service_hasstatus], - 'subscribe' => 'File[sshd_config]', - }) - } + it { should_not contain_exec("mkdir_p-#{facts[:root_home]}/.ssh") } + it { should_not contain_file('root_ssh_dir') } + it { should_not contain_file('root_ssh_config') } + it { should have_ssh__config_entry_resource_count(0) } + it { should have_sshkey_resource_count(0) } it { should contain_resources('sshkey').with({ @@ -349,1135 +272,67 @@ }) } - it { should have_ssh__config_entry_resource_count(0) } - - context 'with exported sshkey resources' do - subject { exported_resources} - context 'With only IPv4 address' do - let(:facts) { default_facts.merge( facts )} - it { should contain_sshkey('monkey.example.com').with( - 'ensure' => 'present', - 'host_aliases' => ['monkey', '127.0.0.1'] - )} - end - context 'With dual stack IP' do - let(:facts) { default_facts.merge({ :ipaddress6 => 'dead:beef::1/64' }) } - it { should contain_sshkey('monkey.example.com').with( - 'ensure' => 'present', - 'host_aliases' => ['monkey', '127.0.0.1', 'dead:beef::1/64'] - )} - end - context 'With only IPv6 address' do - let(:facts) { default_facts.merge({ :ipaddress6 => 'dead:beef::1/64', :ipaddress => nil }) } - it { should contain_sshkey('monkey.example.com').with( - 'ensure' => 'present', - 'host_aliases' => ['monkey', 'dead:beef::1/64'] - )} - end - end - + it { should have_ssh_authorized_key_resource_count(0) } end end - context 'with default params on invalid osfamily' do - let(:facts) { default_facts.merge({ :osfamily => 'C64' }) } - let(:params) { { :manage_root_ssh_config => 'invalid' } } +# TODO: FIXME: access facts hash incorrectly? +# +# describe 'with exported sshkey resources' do +# subject { exported_resources } +# +# let(:params) { { :key_export => true } } +# +# context 'With only IPv4 address' do +# let(:facts) { default_facts.merge( facts ) } +# it { +# should contain_sshkey('monkey.example.com').with( +# 'ensure' => 'present', +# 'host_aliases' => ['monkey', '127.0.0.1'], +# 'type' => 'ssh-rsa', +# 'key' => facts[:ssh['rsa']['key']], +# ) +# } +# end +# context 'With dual stack IP' do +# let(:facts) { default_facts.merge({ :ipaddress6 => 'dead:beef::1/64' }) } +# +# it { +# should contain_sshkey('monkey.example.com').with( +# 'ensure' => 'present', +# 'host_aliases' => ['monkey', '127.0.0.1', 'dead:beef::1/64'], +# 'type' => 'ssh-rsa', +# 'key' => facts[:ssh[:rsa][:key]], +# ) +# } +# end +# +# context 'With only IPv6 address' do +# let(:facts) { default_facts.merge({ :ipaddress6 => 'dead:beef::1/64', :ipaddress => nil }) } +# it { +# should contain_sshkey('monkey.example.com').with( +# 'ensure' => 'present', +# 'host_aliases' => ['monkey', 'dead:beef::1/64'], +# 'type' => 'ssh-rsa', +# 'key' => facts[:ssh[:rsa][:key]], +# ) +# } +# end +# end - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh supports osfamilies RedHat, Suse, Debian and Solaris\. Detected osfamily is <C64>\./) - end - end +# TODO: FIXME: access facts hash incorrectly? +# +# context 'with default params on invalid osfamily' do +# let(:facts) { default_facts.merge({ :os['family'] => 'C64' }) } +# +# it 'should fail' do +# expect { +# should contain_class('ssh') +# }.to raise_error(Puppet::Error, /ssh supports osfamilies RedHat, Suse, Debian and Solaris\. Detected os family is <C64>\./) +# end +# end - context 'with optional params used in ssh_config set on valid osfamily' do - let(:params) do - { - :ssh_config_hash_known_hosts => 'yes', - :ssh_config_forward_agent => 'yes', - :ssh_config_forward_x11 => 'yes', - :ssh_config_use_roaming => 'yes', - :ssh_config_server_alive_interval => '300', - :ssh_config_sendenv_xmodifiers => true, - :ssh_config_ciphers => [ 'aes128-cbc', - '3des-cbc', - 'blowfish-cbc', - 'cast128-cbc', - 'arcfour', - 'aes192-cbc', - 'aes256-cbc', - ], - :ssh_config_kexalgorithms => [ 'curve25519-sha256@libssh.org', - 'ecdh-sha2-nistp256', - 'ecdh-sha2-nistp384', - 'ecdh-sha2-nistp521', - 'diffie-hellman-group-exchange-sha256', - 'diffie-hellman-group-exchange-sha1', - 'diffie-hellman-group14-sha1', - 'diffie-hellman-group1-sha1', - ], - :ssh_config_macs => [ 'hmac-md5-etm@openssh.com', - 'hmac-sha1-etm@openssh.com', - ], - :ssh_config_proxy_command => 'ssh -W %h:%p firewall.example.org', - :ssh_config_global_known_hosts_file => '/etc/ssh/ssh_known_hosts2', - :ssh_config_global_known_hosts_list => [ '/etc/ssh/ssh_known_hosts3', - '/etc/ssh/ssh_known_hosts4', - ], - :ssh_config_user_known_hosts_file => [ '.ssh/known_hosts1', - '.ssh/known_hosts2', - ], - :ssh_hostbasedauthentication => 'yes', - :ssh_strict_host_key_checking => 'ask', - :ssh_enable_ssh_keysign => 'yes', - } - end - - it { should compile.with_all_deps } - - it { - should contain_file('ssh_config').with({ - 'ensure' => 'file', - 'path' => '/etc/ssh/ssh_config', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - 'require' => ['Package[openssh-server]', 'Package[openssh-clients]'], - }) - } - - it { should contain_file('ssh_config').with_content(/^# This file is being maintained by Puppet.\n# DO NOT EDIT\n\n# \$OpenBSD: ssh_config,v 1.21 2005\/12\/06 22:38:27 reyk Exp \$/) } - it { should contain_file('ssh_config').with_content(/^ Protocol 2$/) } - it { should contain_file('ssh_config').with_content(/^ HashKnownHosts yes$/) } - it { should contain_file('ssh_config').with_content(/^\s*SendEnv L.*$/) } - it { should contain_file('ssh_config').with_content(/^ ForwardAgent yes$/) } - it { should contain_file('ssh_config').with_content(/^ ForwardX11 yes$/) } - it { should contain_file('ssh_config').with_content(/^\s*GSSAPIAuthentication yes$/) } - it { should contain_file('ssh_config').with_content(/^\s*UseRoaming yes$/) } - it { should contain_file('ssh_config').with_content(/^ ServerAliveInterval 300$/) } - it { should contain_file('ssh_config').with_content(/^ SendEnv XMODIFIERS$/) } - it { should contain_file('ssh_config').with_content(/^\s*Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc$/) } - it { should contain_file('ssh_config').with_content(/^\s*KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1$/) } - it { should contain_file('ssh_config').with_content(/^\s*MACs hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com$/) } - it { should contain_file('ssh_config').with_content(/^\s*ProxyCommand ssh -W %h:%p firewall\.example\.org$/) } - it { should contain_file('ssh_config').with_content(/^\s*GlobalKnownHostsFile \/etc\/ssh\/ssh_known_hosts2 \/etc\/ssh\/ssh_known_hosts3 \/etc\/ssh\/ssh_known_hosts4$/) } - it { should contain_file('ssh_config').with_content(/^\s*UserKnownHostsFile \.ssh\/known_hosts1 \.ssh\/known_hosts2$/) } - it { should contain_file('ssh_config').with_content(/^\s*HostbasedAuthentication yes$/) } - it { should contain_file('ssh_config').with_content(/^\s*StrictHostKeyChecking ask$/) } - it { should contain_file('ssh_config').with_content(/^\s*EnableSSHKeysign yes$/) } - end - - context 'with params used in sshd_config set on valid osfamily' do - let(:params) do - { - :sshd_config_port => '22222', - :sshd_config_syslog_facility => 'DAEMON', - :sshd_config_login_grace_time => '60', - :permit_root_login => 'no', - :sshd_config_chrootdirectory => '/chrootdir', - :sshd_config_forcecommand => '/force/command --with-parameter 242', - :sshd_config_match => { 'User JohnDoe' => [ 'AllowTcpForwarding yes', ], }, - :sshd_config_challenge_resp_auth => 'no', - :sshd_config_print_motd => 'no', - :sshd_config_print_last_log => 'no', - :sshd_config_use_dns => 'no', - :sshd_config_banner => '/etc/sshd_banner', - :sshd_authorized_keys_command => '/path/to/command', - :sshd_authorized_keys_command_user => 'asdf', - :sshd_banner_content => 'textinbanner', - :sshd_config_xauth_location => '/opt/ssh/bin/xauth', - :sshd_config_subsystem_sftp => '/opt/ssh/bin/sftp', - :sshd_kerberos_authentication => 'no', - :sshd_password_authentication => 'no', - :sshd_config_permitemptypasswords => 'no', - :sshd_config_permituserenvironment => 'no', - :sshd_config_compression => 'no', - :sshd_pubkeyacceptedkeytypes => [ 'ecdsa-sha2-nistp256', - 'ecdsa-sha2-nistp384', - 'ecdsa-sha2-nistp521', - 'ssh-ed25519', - 'ssh-rsa', - ], - :sshd_config_authenticationmethods => [ 'publickey', - 'keyboard-interactive', - ], - :sshd_pubkeyauthentication => 'no', - :sshd_allow_tcp_forwarding => 'no', - :sshd_x11_forwarding => 'no', - :sshd_x11_use_localhost => 'no', - :sshd_use_pam => 'no', - :sshd_client_alive_interval => '242', - :sshd_config_serverkeybits => '1024', - :sshd_client_alive_count_max => '0', - :sshd_config_authkey_location => '.ssh/authorized_keys', - :sshd_config_hostkey => [ '/etc/ssh/ssh_host_rsa_key', - '/etc/ssh/ssh_host_dsa_key', - ], - :sshd_config_strictmodes => 'yes', - :sshd_config_ciphers => [ 'aes128-cbc', - '3des-cbc', - 'blowfish-cbc', - 'cast128-cbc', - 'arcfour', - 'aes192-cbc', - 'aes256-cbc', - ], - :sshd_config_kexalgorithms => [ 'curve25519-sha256@libssh.org', - 'ecdh-sha2-nistp256', - 'ecdh-sha2-nistp384', - 'ecdh-sha2-nistp521', - 'diffie-hellman-group-exchange-sha256', - 'diffie-hellman-group-exchange-sha1', - 'diffie-hellman-group14-sha1', - 'diffie-hellman-group1-sha1', - ], - :sshd_config_macs => [ 'hmac-md5-etm@openssh.com', - 'hmac-sha1-etm@openssh.com', - ], - :sshd_config_denyusers => [ 'root', - 'lusers', - ], - :sshd_config_denygroups => [ 'nossh', - 'wheel', - ], - :sshd_config_allowusers => [ 'foo', - 'bar', - ], - :sshd_config_allowgroups => [ 'ssh', - 'security', - ], - :sshd_listen_address => [ '192.168.1.1', - '2001:db8::dead:f00d', - ], - :sshd_config_tcp_keepalive => 'yes', - :sshd_config_use_privilege_separation => 'no', - :sshd_config_permittunnel => 'no', - :sshd_config_allowagentforwarding => 'no', - :sshd_config_key_revocation_list => '/path/to/revocation_list', - } - end - - it { should compile.with_all_deps } - - it { - should contain_file('sshd_config').with({ - 'ensure' => 'file', - 'path' => '/etc/ssh/sshd_config', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0600', - 'require' => ['Package[openssh-server]', 'Package[openssh-clients]'], - }) - } - - it { should contain_file('sshd_config').with_content(/^Port 22222$/) } - it { should contain_file('sshd_config').with_content(/^SyslogFacility DAEMON$/) } - it { should contain_file('sshd_config').with_content(/^LogLevel INFO$/) } - it { should contain_file('sshd_config').with_content(/^LoginGraceTime 60$/) } - it { should contain_file('sshd_config').with_content(/^PermitRootLogin no$/) } - it { should contain_file('sshd_config').with_content(/^ChallengeResponseAuthentication no$/) } - it { should contain_file('sshd_config').with_content(/^PrintMotd no$/) } - it { should contain_file('sshd_config').with_content(/^PrintLastLog no$/) } - it { should contain_file('sshd_config').with_content(/^UseDNS no$/) } - it { should contain_file('sshd_config').with_content(/^Banner \/etc\/sshd_banner$/) } - it { should contain_file('sshd_config').with_content(/^XAuthLocation \/opt\/ssh\/bin\/xauth$/) } - it { should contain_file('sshd_config').with_content(/^Subsystem sftp \/opt\/ssh\/bin\/sftp$/) } - it { should contain_file('sshd_config').with_content(/^PasswordAuthentication no$/) } - it { should contain_file('sshd_config').with_content(/^KerberosAuthentication no$/) } - it { should contain_file('sshd_config').with_content(/^AllowTcpForwarding no$/) } - it { should contain_file('sshd_config').with_content(/^X11Forwarding no$/) } - it { should contain_file('sshd_config').with_content(/^X11UseLocalhost no$/) } - it { should contain_file('sshd_config').with_content(/^UsePAM no$/) } - it { should contain_file('sshd_config').with_content(/^ClientAliveInterval 242$/) } - it { should contain_file('sshd_config').with_content(/^ServerKeyBits 1024$/) } - it { should contain_file('sshd_config').with_content(/^ClientAliveCountMax 0$/) } - it { should contain_file('sshd_config').with_content(/^GSSAPIAuthentication yes$/) } - it { should contain_file('sshd_config').with_content(/^GSSAPICleanupCredentials yes$/) } - it { should_not contain_file('sshd_config').with_content(/^\s*PAMAuthenticationViaKBDInt yes$/) } - it { should_not contain_file('sshd_config').with_content(/^\s*GSSAPIKeyExchange yes$/) } - it { should contain_file('sshd_config').with_content(/^AcceptEnv L.*$/) } - it { should contain_file('sshd_config').with_content(/^AuthorizedKeysFile .ssh\/authorized_keys/) } - it { should contain_file('sshd_config').with_content(/^HostKey \/etc\/ssh\/ssh_host_rsa_key/) } - it { should contain_file('sshd_config').with_content(/^HostKey \/etc\/ssh\/ssh_host_dsa_key/) } - it { should contain_file('sshd_config').with_content(/^StrictModes yes$/) } - it { should contain_file('sshd_config').with_content(/^PermitUserEnvironment no/) } - it { should contain_file('sshd_config').with_content(/^Compression no$/) } - it { should contain_file('sshd_config').with_content(/^PermitEmptyPasswords no/) } - it { should_not contain_file('sshd_config').with_content(/^MaxAuthTries/) } - it { should_not contain_file('sshd_config').with_content(/^MaxStartups/) } - it { should_not contain_file('sshd_config').with_content(/^MaxSessions/) } - it { should contain_file('sshd_config').with_content(/^AuthorizedKeysCommand \/path\/to\/command$/) } - it { should contain_file('sshd_config').with_content(/^AuthorizedKeysCommandUser asdf$/) } - it { should contain_file('sshd_config').with_content(/^HostbasedAuthentication no$/) } - it { should contain_file('sshd_config').with_content(/^PubkeyAcceptedKeyTypes ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,ssh-rsa$/) } - it { should contain_file('sshd_config').with_content(/^AuthenticationMethods publickey,keyboard-interactive$/) } - it { should contain_file('sshd_config').with_content(/^PubkeyAuthentication no$/) } - it { should contain_file('sshd_config').with_content(/^IgnoreUserKnownHosts no$/) } - it { should contain_file('sshd_config').with_content(/^IgnoreRhosts yes$/) } - it { should contain_file('sshd_config').with_content(/^ChrootDirectory \/chrootdir$/) } - it { should contain_file('sshd_config').with_content(/^ForceCommand \/force\/command --with-parameter 242$/) } - it { should contain_file('sshd_config').with_content(/^Match User JohnDoe\n AllowTcpForwarding yes\Z/) } - it { should contain_file('sshd_config').with_content(/^\s*Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc$/) } - it { should contain_file('sshd_config').with_content(/^\s*KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1$/) } - it { should contain_file('sshd_config').with_content(/^\s*MACs hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com$/) } - it { should contain_file('sshd_config').with_content(/^\s*DenyUsers root lusers$/) } - it { should contain_file('sshd_config').with_content(/^\s*DenyGroups nossh wheel$/) } - it { should contain_file('sshd_config').with_content(/^\s*AllowUsers foo bar$/) } - it { should contain_file('sshd_config').with_content(/^\s*AllowGroups ssh security$/) } - it { should contain_file('sshd_config').with_content(/^ListenAddress 192.168.1.1\nListenAddress 2001:db8::dead:f00d$/) } - it { should contain_file('sshd_config').with_content(/^TCPKeepAlive yes$/) } - it { should contain_file('sshd_config').with_content(/^UsePrivilegeSeparation no$/) } - it { should contain_file('sshd_config').with_content(/^PermitTunnel no$/) } - it { should contain_file('sshd_config').with_content(/^RevokedKeys \/path\/to\/revocation_list$/) } - - it { - should contain_file('sshd_banner').with({ - 'ensure' => 'file', - 'path' => '/etc/sshd_banner', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - 'content' => 'textinbanner', - 'require' => ['Package[openssh-server]', 'Package[openssh-clients]'], - }) - } - end - - describe 'sshd_config_chrootdirectory param' do - ['/chrootdir/subdir','/baby/one/more/test',].each do |value| - context "set to valid #{value} (as #{value.class})" do - let(:params) { {'sshd_config_chrootdirectory' => value } } - - it { should contain_file('sshd_config').with_content(/^ChrootDirectory #{value}$/) } - end - end - - [true,'invalid','invalid/path/',3,2.42,['array'],a = { 'ha' => 'sh' }].each do |value| - context "set to invalid #{value} (as #{value.class})" do - let(:params) { {'sshd_config_chrootdirectory' => value } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error, /is not an absolute path/) - end - end - end - - end - - describe 'sshd_config_forcecommand param' do - ['/bin/command','/bin/command -parameters','/bin/command --parameters','/bin/command /parameters'].each do |value| - context "set to valid #{value} (as #{value.class})" do - let(:params) { {'sshd_config_forcecommand' => value } } - - it { should contain_file('sshd_config').with_content(/^ForceCommand #{value}$/) } - end - end - - [true,['array'],a = { 'ha' => 'sh' }].each do |value| - context "set to invalid #{value} (as #{value.class})" do - let(:params) { {'sshd_config_forcecommand' => value } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error, /is not a string/) - end - end - end - - end - - describe 'sshd_config_match param' do - # match and rules get alphabetically sorted by template, matches should be the last options in sshd_config (regex verify with= \Z) - context 'set to valid hash containing nested arrays' do - let(:params) do - { :sshd_config_match => { - 'User JohnDoe' => [ 'AllowTcpForwarding yes', ], - 'Addresss 2.4.2.0' => [ 'X11Forwarding yes', 'PasswordAuthentication no', ], - }, - } - end - - it { should contain_file('sshd_config').with_content(/^Match Addresss 2.4.2.0\n PasswordAuthentication no\n X11Forwarding yes\nMatch User JohnDoe\n AllowTcpForwarding yes\Z/) } - end - - [true,'string',3,2.42,['array']].each do |value| - context "set to invalid #{value} (as #{value.class})" do - let(:params) { {'sshd_config_match' => value } } - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error, /is not a Hash/) - end - end - end - - end - -describe 'sshd_config_print_last_log param' do - ['yes','no'].each do |value| - context "set to #{value}" do - let (:params) { { :sshd_config_print_last_log => value } } - - it { should contain_file('sshd_config').with_content(/^PrintLastLog #{value}$/) } - end - end - - context 'when set to an invalid value' do - let (:params) { { :sshd_config_print_last_log => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_print_last_log may be either \'yes\' or \'no\' and is set to <invalid>\./) - end - end - end - - describe 'sshd_listen_address param' do - context 'when set to an array' do - let(:params) { {'sshd_listen_address' => ['192.168.1.1','2001:db8::dead:f00d'] } } - - it { should contain_file('sshd_config').with_content(/^ListenAddress 192.168.1.1\nListenAddress 2001:db8::dead:f00d$/) } - end - - context 'when set to a string' do - let(:params) { {'sshd_listen_address' => ['192.168.1.1'] } } - - it { should contain_file('sshd_config').with_content(/^ListenAddress 192.168.1.1$/) } - end - - context 'when not set' do - it { should_not contain_file('sshd_config').with_content(/^\s*ListenAddress/) } - end - - - context 'when set to an invalid type (not string or array)' do - let(:params) { {'sshd_listen_address' => true } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - end - - describe 'sshd_loglevel param' do - context 'when set to an invalid value' do - let(:params) { {'sshd_config_loglevel' => 'BOGON'} } - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error, /"BOGON" does not match/) - end - end - ['QUIET', 'FATAL', 'ERROR', 'INFO', 'VERBOSE'].each do |supported_val| - context "when set to #{supported_val}" do - let(:params) { { 'sshd_config_loglevel' => supported_val} } - it { should contain_file('sshd_config').with_content(/^LogLevel #{supported_val}$/) } - end - end - end - - describe 'with sshd_kerberos_authentication' do - ['yes','no'].each do |value| - context "set to #{value}" do - let(:params) { { 'sshd_kerberos_authentication' => value } } - - it { should contain_file('sshd_config').with_content(/^KerberosAuthentication #{value}$/) } - end - end - - context 'set to invalid value on valid osfamily' do - let(:params) { { :sshd_kerberos_authentication => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_kerberos_authentication may be either \'yes\' or \'no\' and is set to <invalid>\./) - end - end - end - - context 'when ssh_config_template has a nonstandard value' do - context 'and that value is not valid' do - let(:params) { {'ssh_config_template' => false} } - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error, /is not a string/) - end - end - context 'and that value is valid' do - let(:params) { {'ssh_config_template' => 'ssh/sshd_config.erb'} } - it 'should lay down the ssh_config file from the specified template' do - should contain_file('ssh_config').with_content(/OpenBSD: sshd_config/) - end - end - end - - context 'when sshd_config_template has a nonstandard value' do - context 'and that value is not valid' do - let(:params) { {'sshd_config_template' => false} } - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error, /is not a string/) - end - end - context 'and that value is valid' do - let(:params) { {'sshd_config_template' => 'ssh/ssh_config.erb'} } - it 'should lay down the sshd_config file from the specified template' do - should contain_file('sshd_config').with_content(/OpenBSD: ssh_config/) - end - end - end - - ['true',true].each do |value| - context "with manage_root_ssh_config set to #{value} on valid osfamily" do - let(:params) { { :manage_root_ssh_config => value } } - - it { should compile.with_all_deps } - - it { should contain_class('ssh')} - - it { should contain_class('common')} - - it { - should contain_file('root_ssh_dir').with({ - 'ensure' => 'directory', - 'path' => '/root/.ssh', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0700', - 'require' => 'Common::Mkdir_p[/root/.ssh]', - }) - } - - it { - should contain_file('root_ssh_config').with({ - 'ensure' => 'file', - 'path' => '/root/.ssh/config', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0600', - }) - } - end - end - - ['false',false].each do |value| - context "with manage_root_ssh_config set to #{value} on valid osfamily" do - let(:params) { { :manage_root_ssh_config => value } } - - it { should compile.with_all_deps } - - it { should contain_class('ssh')} - - it { should_not contain_class('common')} - - it { should_not contain_file('root_ssh_dir') } - - it { should_not contain_file('root_ssh_config') } - end - end - - [true,'invalid'].each do |ciphers| - context "with ssh_config_ciphers set to invalid value #{ciphers}" do - let(:params) { { :ssh_config_ciphers => ciphers } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - end - - [true,'invalid'].each do |kexalgorithms| - context "with ssh_config_kexalgorithms set to invalid value #{kexalgorithms}" do - let(:params) { { :ssh_config_kexalgorithms => kexalgorithms } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - end - - [true,'invalid'].each do |macs| - context "with ssh_config_macs set to invalid value #{macs}" do - let(:params) { { :ssh_config_macs => macs } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - end - - [true, ['not','a','string']].each do |proxy_command| - context "with ssh_config_proxy_command set to invalid value #{proxy_command}" do - let(:params) { { :ssh_config_proxy_command => proxy_command } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - end - - describe 'with ssh_config_hash_known_hosts param' do - ['yes','no','unset'].each do |value| - context "set to #{value}" do - let (:params) { { :ssh_config_hash_known_hosts => value } } - - if value == 'unset' - it { should contain_file('ssh_config').without_content(/^\s*HashKnownHosts/) } - else - it { should contain_file('ssh_config').with_content(/^\s*HashKnownHosts #{value}$/) } - end - end - end - - context 'when set to an invalid value' do - let (:params) { { :ssh_config_hash_known_hosts => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::ssh_config_hash_known_hosts may be either \'yes\', \'no\' or \'unset\' and is set to <invalid>\./) - end - end - end - - [true,'invalid'].each do |ciphers| - context "with sshd_config_ciphers set to invalid value #{ciphers}" do - let(:params) { { :sshd_config_ciphers => ciphers } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - end - - [true,'invalid'].each do |kexalgorithms| - context "with sshd_config_kexalgorithms set to invalid value #{kexalgorithms}" do - let(:params) { { :sshd_config_kexalgorithms => kexalgorithms } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - end - - [true,'invalid'].each do |denyusers| - context "with sshd_config_denyusers set to invalid value #{denyusers}" do - let(:params) { { :sshd_config_denyusers => denyusers } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not an Array/) - end - end - end - - [true,'invalid'].each do |denygroups| - context "with sshd_config_denygroups set to invalid value #{denygroups}" do - let(:params) { { :sshd_config_denygroups => denygroups } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not an Array/) - end - end - end - - [true,'invalid'].each do |allowusers| - context "with sshd_config_allowusers set to invalid value #{allowusers}" do - let(:params) { { :sshd_config_allowusers => allowusers } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not an Array/) - end - end - end - - [true,'invalid'].each do |allowgroups| - context "with sshd_config_allowgroups set to invalid value #{allowgroups}" do - let(:params) { { :sshd_config_allowgroups => allowgroups } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not an Array/) - end - end - end - - [true,'invalid'].each do |macs| - context "with sshd_config_macs set to invalid value #{macs}" do - let(:params) { { :sshd_config_macs => macs } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - end - - describe 'with sshd_config_permitemptypasswords' do - ['yes','no'].each do |value| - context "set to #{value}" do - let(:params) { { 'sshd_config_permitemptypasswords' => value } } - - it { should contain_file('sshd_config').with_content(/^PermitEmptyPasswords #{value}$/) } - end - end - - context 'set to invalid value on valid osfamily' do - let(:params) { { :sshd_config_permitemptypasswords => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_permitemptypasswords may be either \'yes\' or \'no\' and is set to <invalid>\./) - end - end - end - - describe 'with sshd_config_permituserenvironment' do - ['yes','no'].each do |value| - context "set to #{value}" do - let(:params) { { 'sshd_config_permituserenvironment' => value } } - - it { should contain_file('sshd_config').with_content(/^PermitUserEnvironment #{value}$/) } - end - end - - context 'set to invalid value on valid osfamily' do - let(:params) { { :sshd_config_permituserenvironment => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_permituserenvironment may be either \'yes\' or \'no\' and is set to <invalid>\./) - end - end - end - - describe 'sshd_config_compression param' do - ['yes','no','delayed'].each do |value| - context "set to #{value}" do - let (:params) { { :sshd_config_compression => value } } - - it { should contain_file('sshd_config').with_content(/^Compression #{value}$/) } - end - end - - context 'when set to an invalid value' do - let (:params) { { :sshd_config_compression => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_compression may be either \'yes\', \'no\' or \'delayed\' and is set to <invalid>\./) - end - end - end - - describe 'sshd_config_port param' do - context 'when set to an array' do - let(:params) { {'sshd_config_port' => ['22222', '22223'] } } - - it { should contain_file('sshd_config').with_content(/^Port 22222\nPort 22223$/) } - end - - context 'when set to a string' do - let(:params) { {'sshd_config_port' => '22222' } } - - it { should contain_file('sshd_config').with_content(/^Port 22222$/) } - end - - context 'when set to an integer' do - let(:params) { {'sshd_config_port' => 22222 } } - - it { should contain_file('sshd_config').with_content(/^Port 22222$/) } - end - - context 'when not set to a valid number' do - let(:params) { {'sshd_config_port' => '22invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_port must be a valid number and is set to <22invalid>\./) - end - end - end - - describe 'sshd_config_permittunnel param' do - ['yes','point-to-point','ethernet','no','unset'].each do |value| - context "set to #{value}" do - let (:params) { { :sshd_config_permittunnel => value } } - - if value == 'unset' - it { should contain_file('sshd_config').without_content(/^\s*PermitTunnel/) } - else - it { should contain_file('sshd_config').with_content(/^PermitTunnel #{value}$/) } - end - end - end - - context 'when set to an invalid value' do - let (:params) { { :sshd_config_permittunnel => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_permittunnel may be either \'yes\', \'point-to-point\', \'ethernet\', \'no\' or \'unset\' and is set to <invalid>\./) - end - end - end - - describe 'sshd_config_key_revocation_list param' do - ['/path/to','unset'].each do |value| - context "set to #{value}" do - let (:params) { { :sshd_config_key_revocation_list => value } } - - if value == 'unset' - it { should contain_file('sshd_config').without_content(/^\s*RevokedKeys/) } - else - it { should contain_file('sshd_config').with_content(/^RevokedKeys #{value}$/) } - end - end - end - - context 'when set to an invalid value' do - let (:params) { { :sshd_config_key_revocation_list => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/while evaluating a Function Call|is not an absolute path/) - end - end - end - - describe 'sshd_config_hostcertificate param' do - context 'unset value' do - let(:params) { { :sshd_config_hostcertificate => 'unset' } } - - it { should contain_file('sshd_config').without_content(/^\s*HostCertificate/) } - end - - context 'with a certificate' do - let(:params) { { :sshd_config_hostcertificate => '/etc/ssh/ssh_host_key-cert.pub' } } - - it { should contain_file('sshd_config').with_content(/^HostCertificate \/etc\/ssh\/ssh_host_key-cert\.pub/) } - end - - context 'with multiple certs' do - let(:params) { { :sshd_config_hostcertificate => [ '/etc/ssh/ssh_host_key-cert.pub', '/etc/ssh/ssh_host_key-cert2.pub'] } } - - it { should contain_file('sshd_config').with_content(/^HostCertificate \/etc\/ssh\/ssh_host_key-cert\.pub\nHostCertificate \/etc\/ssh\/ssh_host_key-cert2\.pub/)} - end - end - - context 'with sshd_config_hostcertificate set to invalid value on valid osfamily' do - context 'with string' do - let(:params) { { :sshd_config_hostcertificate => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/"invalid" is not an absolute path/) - end - end - end - - context 'with sshd_config_authorized_principals_file param' do - ['unset', '.ssh/authorized_principals'].each do |value| - context "set to #{value}" do - let (:params) { { :sshd_config_authorized_principals_file => value } } - - if value == 'unset' - it { should contain_file('sshd_config').without_content(/^\s*AuthorizedPrincipalsFile/)} - else - it { should contain_file('sshd_config').with_content(/^AuthorizedPrincipalsFile \.ssh\/authorized_principals/)} - end - end - end - end - - describe 'sshd_config_trustedusercakeys param' do - ['unset', '/etc/ssh/authorized_users_ca.pub', 'none'].each do |value| - context "set to #{value}" do - let (:params) { { :sshd_config_trustedusercakeys => value } } - - if value == 'unset' - it { should contain_file('sshd_config').without_content(/^\s*TrustedUserCAKeys/) } - else - it { should contain_file('sshd_config').with_content(/^TrustedUserCAKeys #{value}/) } - end - end - end - end - - context 'with sshd_config_trustedusercakeys set to invalid value on valid osfamily' do - let(:params) { { :sshd_config_trustedusercakeys => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/"invalid" is not an absolute path/) - end - end - - context 'with manage_root_ssh_config set to invalid value on valid osfamily' do - let(:params) { { :manage_root_ssh_config => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/Unknown type of boolean/) - end - end - - context 'with sshd_password_authentication set to invalid value on valid osfamily' do - let(:params) { { :sshd_password_authentication => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_password_authentication may be either \'yes\' or \'no\' and is set to <invalid>\./) - end - end - - context 'with sshd_allow_tcp_forwarding set to invalid value on valid osfamily' do - let(:params) { { :sshd_allow_tcp_forwarding => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_allow_tcp_forwarding may be either \'yes\' or \'no\' and is set to <invalid>\./) - end - end - - context 'with sshd_x11_forwarding set to invalid value on valid osfamily' do - let(:params) { { :sshd_x11_forwarding => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_x11_forwarding may be either \'yes\' or \'no\' and is set to <invalid>\./) - end - end - - context 'with sshd_x11_use_localhost set to invalid value on valid osfamily' do - let(:params) { { :sshd_x11_use_localhost => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_x11_use_localhost may be either \'yes\' or \'no\' and is set to <invalid>\./) - end - end - - context 'with sshd_use_pam set to invalid value on valid osfamily' do - let(:params) { { :sshd_use_pam => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_use_pam may be either \'yes\' or \'no\' and is set to <invalid>\./) - end - end - - context 'with sshd_config_serverkeybits set to invalid value on valid osfamily' do - let(:params) { { :sshd_config_serverkeybits => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_serverkeybits must be an integer and is set to <invalid>\./) - end - end - - context 'with sshd_client_alive_interval set to invalid value on valid osfamily' do - let(:params) { { :sshd_client_alive_interval => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_client_alive_interval must be an integer and is set to <invalid>\./) - end - end - - context 'with sshd_client_alive_count_max set to invalid value on valid osfamily' do - let(:params) { { :sshd_client_alive_count_max => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_client_alive_count_max must be an integer and is set to <invalid>\./) - end - end - - context 'with sshd_config_banner set to invalid value on valid osfamily' do - let(:params) { { :sshd_config_banner => 'invalid/path' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not an absolute path/) - end - end - - context 'with sshd_config_authkey_location set to invalid value on valid osfamily' do - let(:params) { { :sshd_config_authkey_location => false } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not a string/) - end - end - - context 'with sshd_config_hostkey set to invalid value on valid osfamily' do - let(:params) { { :sshd_config_hostkey => false } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not an Array/) - end - end - - context 'with sshd_config_hostkey set to invalid path on valid osfamily' do - let(:params) { { :sshd_config_hostkey => ['not_a_path'] } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not an absolute path./) - end - end - - describe 'with sshd_config_allowagentforwarding' do - ['yes','no'].each do |value| - context "set to #{value}" do - let(:params) { { 'sshd_config_allowagentforwarding' => value } } - - it { should contain_file('sshd_config').with_content(/^AllowAgentForwarding #{value}$/) } - end - end - - context 'set to invalid value on valid osfamily' do - let(:params) { { :sshd_config_allowagentforwarding => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_allowagentforwarding may be either \'yes\' or \'no\' and is set to <invalid>\./) - end - end - end - - - context 'with sshd_config_strictmodes set to invalid value on valid osfamily' do - let(:params) { { :sshd_config_strictmodes => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_strictmodes may be either \'yes\' or \'no\' and is set to <invalid>\./) - end - end - - context 'with sshd_authorized_keys_command specified with an invalid path' do - let(:params) { { :sshd_authorized_keys_command => 'invalid/path' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/"invalid\/path" is not an absolute path/) - end - end - - context 'with sshd_authorized_keys_command_user specified with an invalid type (non-string)' do - let(:params) { { :sshd_authorized_keys_command_user => ['invalid','type'] } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/\["invalid", "type"\] is not a string/) - end - end - - context 'with sshd_banner_content set and with default value on sshd_config_banner on valid osfamily' do - let(:params) { { :sshd_banner_content => 'textinbanner' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_banner must be set to be able to use sshd_banner_content\./) - end - end - - - context 'with ssh_config_sendenv_xmodifiers set to invalid type, array' do - let(:params) { { :ssh_config_sendenv_xmodifiers => ['invalid','type'] } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::ssh_config_sendenv_xmodifiers type must be true or false\./) - end - end - - context 'with ssh_config_sendenv_xmodifiers set to stringified \'true\'' do - let(:params) { { :ssh_config_sendenv_xmodifiers => 'true' } } - - it { should compile.with_all_deps } - - it { should contain_file('ssh_config').with_content(/^ SendEnv XMODIFIERS$/) } - end - - context 'with manage_firewall set to true on valid osfamily' do - let(:params) { { :manage_firewall => true } } - - it { should compile.with_all_deps } - - it { should contain_class('ssh')} - - it { should_not contain_class('common')} - - it { - should contain_firewall('22 open port 22 for SSH').with({ - 'action' => 'accept', - 'dport' => '22', - 'proto' => 'tcp', - }) - } - end - - context 'with config_entries defined on valid osfamily' do + context 'with config_entries defined' do let(:params) do { :config_entries => { @@ -1492,8 +347,8 @@ 'group' => 'group', 'path' => '/home/user/.ssh/config', 'host' => 'test_host2', - 'order' => '242', - 'lines' => [ 'ForwardX11 no', 'StrictHostKeyChecking no' ], + 'order' => 242, + 'lines' => ['ForwardX11 no', 'StrictHostKeyChecking no'], }, } } @@ -1515,53 +370,36 @@ 'group' => 'group', 'path' => '/home/user/.ssh/config', 'host' => 'test_host2', - 'order' => '242', - 'lines' => [ 'ForwardX11 no', 'StrictHostKeyChecking no' ], + 'order' => 242, + 'lines' => ['ForwardX11 no', 'StrictHostKeyChecking no'], }) end end - describe 'with hiera providing data from multiple levels' do - let(:facts) do - default_facts.merge({ - :fqdn => 'hieramerge.example.com', - :specific => 'test_hiera_merge', - }) - end - - context 'with defaults for all parameters' do - it { should have_ssh__config_entry_resource_count(1) } - it { should contain_ssh__config_entry('user_from_fqdn') } - end - - context 'with hiera_merge set to valid <true>' do - let(:params) { { :hiera_merge => true } } - it { should have_ssh__config_entry_resource_count(2) } - it { should contain_ssh__config_entry('user_from_fqdn') } - it { should contain_ssh__config_entry('user_from_fact') } - end - end - - context 'with keys defined on valid osfamily' do - let(:params) { { :keys => { - 'root_for_userX' => { - 'ensure' => 'present', - 'user' => 'root', - 'type' => 'dsa', - 'key' => 'AAAA==', - }, - 'apache_hup' => { - 'ensure' => 'present', - 'user' => 'apachehup', - 'type' => 'dsa', - 'key' => 'AAAA==', - 'options' => 'command="/sbin/service httpd restart"', - }, - 'root_for_userY' => { - 'ensure' => 'absent', - 'user' => 'root', + context 'with keys defined' do + let(:params) do + { + :keys => { + 'root_for_userX' => { + 'ensure' => 'present', + 'user' => 'root', + 'type' => 'dsa', + 'key' => 'AAAA==', + }, + 'apache_hup' => { + 'ensure' => 'present', + 'user' => 'apachehup', + 'type' => 'dsa', + 'key' => 'AAAA==', + 'options' => 'command="/sbin/service httpd restart"', + }, + 'root_for_userY' => { + 'ensure' => 'absent', + 'user' => 'root', + } + } } - } } } + end it { should compile.with_all_deps } @@ -1592,1171 +430,18 @@ } end - context 'with keys specified as not of type hash' do - let(:params) { { :keys => [ 'not', 'a', 'hash' ] } } + describe 'with ssh_key_import parameter set to' do +# TODO: FIXME: problem related to other commented out block. See 'with exported sshkey resources' +# context 'as true' do +# let(:params) { { :ssh_key_import => true } } +# +# it { should have_sshkey_resource_count(1) } +# end - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) + context 'as false' do + let(:params) { { :ssh_key_import => false } } + + it { should have_sshkey_resource_count(0) } end end - - describe 'with hiera_merge parameter specified' do - context 'as a non-boolean or non-string' do - let(:facts) { default_facts.merge( { :fqdn => 'hieramerge.example.com'} )} - let(:params) { { :hiera_merge => ['not_a_boolean','or_a_string'] } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - - context 'as an invalid string' do - let(:params) { { :hiera_merge => 'invalid_string' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::hiera_merge may be either 'true' or 'false' and is set to <invalid_string>./) - end - end - - ['true',true].each do |value| - context "as #{value} with hiera data getting collected" do - let(:facts) { default_facts.merge( { :fqdn => 'hieramerge.example.com'} )} - let(:params) { { :hiera_merge => value } } - - it { should compile.with_all_deps } - - it { should contain_class('ssh') } - - it { should contain_file('sshd_config').with_content(/^\s*DenyUsers denyuser_from_fqdn/) } - it { should contain_file('sshd_config').with_content(/^\s*DenyGroups denygroup_from_fqdn/) } - it { should contain_file('sshd_config').with_content(/^\s*AllowUsers allowuser_from_fqdn/) } - it { should contain_file('sshd_config').with_content(/^\s*AllowGroups allowgroup_from_fqdn/) } - - end - end - - context "as true with with hiera data getting merged through levels" do - let(:facts) do - default_facts.merge( - { - :fqdn => 'hieramerge.example.com', - :specific => 'test_hiera_merge', - } - ) - end - let(:params) { { :hiera_merge => true } } - - it { should compile.with_all_deps } - - it { should contain_class('ssh') } - - it { should contain_file('sshd_config').with_content(/^\s*DenyUsers denyuser_from_fqdn denyuser_from_fact/) } - it { should contain_file('sshd_config').with_content(/^\s*DenyGroups denygroup_from_fqdn denygroup_from_fact/) } - it { should contain_file('sshd_config').with_content(/^\s*AllowUsers allowuser_from_fqdn allowuser_from_fact/) } - it { should contain_file('sshd_config').with_content(/^\s*AllowGroups allowgroup_from_fqdn allowgroup_from_fact/) } - - end - - context "as true with no hiera data provided" do - let(:facts) do - default_facts.merge( - { - :osfamily => 'Suse', - :operatingsystem => 'SLES', - :operatingsystemrelease => '11.4', - :architecture => 'x86_64', - } - ) - end - let(:params) { { :hiera_merge => true } } - - it { should compile.with_all_deps } - - it { should contain_class('ssh') } - - it { should contain_file('sshd_config').without_content(/^\s*DenyUsers/) } - it { should contain_file('sshd_config').without_content(/^\s*DenyGroups/) } - it { should contain_file('sshd_config').without_content(/^\s*AllowUsers/) } - it { should contain_file('sshd_config').without_content(/^\s*AllowGroups/) } - - end - - ['false',false].each do |value| - context "as #{value}" do - let(:params) { { :hiera_merge => value } } - - it { should compile.with_all_deps } - - it { should contain_class('ssh') } - end - end - end - - describe 'with ssh_package_adminfile parameter specified' do - context 'as a valid path' do - let(:facts) { default_solaris_facts } - let(:params) { { :ssh_package_adminfile => '/var/tmp/admin' } } - - ['SUNWsshcu','SUNWsshdr','SUNWsshdu','SUNWsshr','SUNWsshu'].each do |pkg| - it { - should contain_package(pkg).with({ - 'ensure' => 'installed', - 'source' => '/var/spool/pkg', - 'adminfile' => '/var/tmp/admin', - }) - } - end - end - - context 'as an invalid path' do - let(:facts) { default_solaris_facts } - let(:params) { { :ssh_package_adminfile => 'invalid/path' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not an absolute path/) - end - end - end - - describe 'with sshd_config_xauth_location parameter specified' do - context 'as a valid path' do - let(:params) { { :sshd_config_xauth_location => '/opt/ssh/bin/xauth' } } - - it { should contain_file('sshd_config').with_content(/^XAuthLocation \/opt\/ssh\/bin\/xauth$/) } - end - - context 'as an invalid path' do - let(:params) { { :sshd_config_xauth_location => 'invalid/path' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not an absolute path/) - end - end - - context 'as an invalid type' do - let(:params) { { :sshd_config_xauth_location => true } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - end - - describe 'with ssh_package_source parameter specified' do - let(:facts) { default_solaris_facts } - context 'as a valid path' do - let(:params) { { :ssh_package_source => '/mnt/packages' } } - - ['SUNWsshcu','SUNWsshdr','SUNWsshdu','SUNWsshr','SUNWsshu'].each do |pkg| - it { - should contain_package(pkg).with({ - 'ensure' => 'installed', - 'source' => '/mnt/packages', - 'adminfile' => nil, - }) - } - end - end - - context 'as an invalid path' do - let(:params) { { :ssh_package_source => 'invalid/path' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not an absolute path/) - end - end - - context 'as an invalid type' do - let(:params) { { :ssh_package_source => true } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - end - - describe 'with parameter ssh_config_forward_x11_trusted' do - ['yes','no'].each do |value| - context "specified as #{value}" do - let(:params) { { :ssh_config_forward_x11_trusted => value } } - - it { should contain_file('ssh_config').with_content(/^\s*ForwardX11Trusted #{value}$/) } - end - end - - context 'not specified' do - let(:facts) { default_solaris_facts } - it { should_not contain_file('ssh_config').with_content(/^\s*ForwardX11Trusted/) } - end - - ['YES',true].each do |value| - context "specified an invalid value #{value}" do - let(:params) { { :ssh_config_forward_x11_trusted => value } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::ssh_config_forward_x11_trusted may be either 'yes' or 'no' and is set to <#{value}>\./) - end - end - end - end - - describe 'with parameter ssh_gssapidelegatecredentials' do - ['yes','no'].each do |value| - context "specified as #{value}" do - let(:facts) { default_solaris_facts } - let(:params) { { :ssh_gssapidelegatecredentials => value } } - - it { should contain_file('ssh_config').with_content(/^GSSAPIDelegateCredentials #{value}$/) } - end - end - - ['YES',true].each do |value| - context "specified an invalid value #{value}" do - let(:params) { { :ssh_gssapidelegatecredentials => value } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::ssh_gssapidelegatecredentials may be either 'yes' or 'no' and is set to <#{value}>\./) - end - end - end - end - - describe 'with parameter ssh_gssapiauthentication' do - ['yes','no'].each do |value| - context "specified as valid #{value} (as #{value.class})" do - let(:params) { { :ssh_gssapiauthentication => value } } - - it { should contain_file('ssh_config').with_content(/^\s*GSSAPIAuthentication #{value}$/) } - end - end - - ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value| - context "specified as invalid value #{value} (as #{value.class})" do - let(:params) { { :ssh_gssapiauthentication => value } } - - if value.is_a?(Array) - value = value.join - elsif value.is_a?(Hash) - value = '{ha => sh}' - end - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::ssh_gssapiauthentication may be either 'yes' or 'no' and is set to <#{Regexp.escape(value.to_s)}>\./) - end - end - end - end - - describe 'with parameter ssh_hostbasedauthentication' do - ['yes','no'].each do |value| - context "specified as valid #{value} (as #{value.class})" do - let(:params) { { :ssh_hostbasedauthentication => value } } - - it { should contain_file('ssh_config').with_content(/^\s*HostbasedAuthentication #{value}$/) } - end - end - - ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value| - context "specified as invalid value #{value} (as #{value.class})" do - let(:params) { { :ssh_hostbasedauthentication => value } } - - if value.is_a?(Array) - value = value.join - elsif value.is_a?(Hash) - value = '{ha => sh}' - end - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::ssh_hostbasedauthentication may be either 'yes' or 'no' and is set to <#{Regexp.escape(value.to_s)}>\./) - end - end - end - end - - describe 'with parameter ssh_strict_host_key_checking' do - ['yes','no', 'ask'].each do |value| - context "specified as valid #{value} (as #{value.class})" do - let(:params) { { :ssh_strict_host_key_checking => value } } - - it { should contain_file('ssh_config').with_content(/^\s*StrictHostKeyChecking #{value}$/) } - end - end - - ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value| - context "specified as invalid value #{value} (as #{value.class})" do - let(:params) { { :ssh_strict_host_key_checking => value } } - - if value.is_a?(Array) - value = value.join - elsif value.is_a?(Hash) - value = '{ha => sh}' - end - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::ssh_strict_host_key_checking may be 'yes', 'no' or 'ask' and is set to <#{Regexp.escape(value.to_s)}>\./) - end - end - end - end - - describe 'with parameter ssh_enable_ssh_keysign' do - ['yes','no'].each do |value| - context "specified as valid #{value} (as #{value.class})" do - let(:params) { { :ssh_enable_ssh_keysign => value } } - - it { should contain_file('ssh_config').with_content(/^\s*EnableSSHKeysign #{value}$/) } - end - end - - ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value| - context "specified as invalid value #{value} (as #{value.class})" do - let(:params) { { :ssh_enable_ssh_keysign => value } } - - if value.is_a?(Array) - value = value.join - elsif value.is_a?(Hash) - value = '{ha => sh}' - end - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::ssh_enable_ssh_keysign may be either 'yes' or 'no' and is set to <#{Regexp.escape(value.to_s)}>\./) - end - end - end - end - - describe 'with parameter sshd_gssapiauthentication' do - ['yes','no'].each do |value| - context "specified as valid #{value} (as #{value.class})" do - let(:params) { { :sshd_gssapiauthentication => value } } - - it { should contain_file('sshd_config').with_content(/^GSSAPIAuthentication #{value}$/) } - end - end - - ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value| - context "specified as invalid value #{value} (as #{value.class})" do - let(:params) { { :sshd_gssapiauthentication => value } } - - if value.is_a?(Array) - value = value.join - elsif value.is_a?(Hash) - value = '{ha => sh}' - end - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_gssapiauthentication may be either 'yes' or 'no' and is set to <#{Regexp.escape(value.to_s)}>\./) - end - end - end - end - - describe 'with parameter sshd_gssapikeyexchange' do - ['yes','no'].each do |value| - context "specified as #{value}" do - let(:params) { { :sshd_gssapikeyexchange => value } } - - it { should contain_file('sshd_config').with_content(/^GSSAPIKeyExchange #{value}$/) } - end - end - - context 'not specified' do - - it { should_not contain_file('sshd_config').with_content(/^\s*GSSAPIKeyExchange/) } - end - - ['YES',true].each do |value| - context "specified an invalid value #{value}" do - let(:params) { { :sshd_gssapikeyexchange => value } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_gssapikeyexchange may be either 'yes' or 'no' and is set to <#{value}>\./) - end - end - end - end - - describe 'with parameter sshd_pamauthenticationviakbdint' do - ['yes','no'].each do |value| - context "specified as #{value}" do - let(:params) { { :sshd_pamauthenticationviakbdint => value } } - - it { should contain_file('sshd_config').with_content(/^PAMAuthenticationViaKBDInt #{value}$/) } - end - end - - context 'not specified' do - - it { should_not contain_file('sshd_config').with_content(/^\s*PAMAuthenticationViaKBDInt/) } - end - - ['YES',true].each do |value| - context "specified an invalid value #{value}" do - let(:params) { { :sshd_pamauthenticationviakbdint => value } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_pamauthenticationviakbdint may be either 'yes' or 'no' and is set to <#{value}>\./) - end - end - end - end - - describe 'with parameter sshd_gssapicleanupcredentials' do - ['yes','no'].each do |value| - context "specified as #{value}" do - let(:params) { { :sshd_gssapicleanupcredentials => value } } - - it { should contain_file('sshd_config').with_content(/^GSSAPICleanupCredentials #{value}$/) } - end - end - - context 'not specified' do - let(:facts) { default_solaris_facts } - - it { should_not contain_file('sshd_config').with_content(/^\s*GSSAPICleanupCredentials/) } - end - - ['YES',true].each do |value| - context "specified an invalid value #{value}" do - let(:params) { { :sshd_gssapicleanupcredentials => value } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_gssapicleanupcredentials may be either 'yes' or 'no' and is set to <#{value}>\./) - end - end - end - end - - - describe 'with parameter ssh_sendenv specified' do - ['true',true].each do |value| - context "as #{value}" do - let(:params) { { :ssh_sendenv => value } } - - it { should contain_file('ssh_config').with_content(/^\s*SendEnv/) } - end - end - - ['false',false].each do |value| - context "as #{value}" do - let(:params) { { :ssh_sendenv => value } } - - it { should_not contain_file('ssh_config').with_content(/^\s*SendEnv/) } - end - end - - context 'as an invalid string' do - let(:params) { { :ssh_sendenv => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::ssh_sendenv may be either 'true' or 'false' and is set to <invalid>\./) - end - end - - context 'as an invalid type' do - let(:params) { { :ssh_sendenv => ['invalid','type'] } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::ssh_sendenv type must be true or false\./) - end - end - end - - describe 'with paramter sshd_config_maxauthtries specified' do - context 'as a valid integer' do - let(:params) { { :sshd_config_maxauthtries => 6}} - it { should contain_file('sshd_config').with_content(/^MaxAuthTries 6$/)} - end - context 'as an invalid type' do - let(:params) { { :sshd_config_maxauthtries => 'BOGUS'} } - it 'should fail' do - expect{ - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_maxauthtries must be a valid number and is set to <BOGUS>\./) - end - end - end - - describe 'with parameter sshd_config_maxstartups specified' do - ['10','10:30:100'].each do |value| - context "as a valid string - #{value}" do - let(:params) { { :sshd_config_maxstartups => value } } - - it { should contain_file('sshd_config').with_content(/^MaxStartups #{value}$/) } - end - end - - ['10a',true,'10:30:1a'].each do |value| - context "as an invalid string - #{value}" do - let(:params) { { :sshd_config_maxstartups => value } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_maxstartups may be either an integer or three integers separated with colons, such as 10:30:100\. Detected value is <#{value}>\./) - end - end - end - - context 'as an invalid type' do - let(:params) { { :sshd_config_maxstartups => true } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - end - - describe 'with parameter sshd_config_maxsessions specified' do - context 'as a valid integer' do - let(:params) { { :sshd_config_maxsessions => 10 } } - - it { should contain_file('sshd_config').with_content(/^MaxSessions 10$/) } - end - - context 'as a valid string <unset>' do - let(:params) { { :sshd_config_maxsessions => 'unset' } } - - it { should contain_file('sshd_config').without_content(/^\s*MaxSessions/) } - end - - context 'as an invalid type' do - let(:params) { { :sshd_config_maxsessions => 'BOGUS' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - end - - describe 'with parameter sshd_acceptenv specified' do - ['true',true].each do |value| - context "as #{value}" do - let(:params) { { :sshd_acceptenv => value } } - - it { should contain_file('sshd_config').with_content(/^\s*AcceptEnv/) } - end - end - - ['false',false].each do |value| - context "as #{value}" do - let(:params) { { :sshd_acceptenv => value } } - - it { should_not contain_file('sshd_config').with_content(/^\s*AcceptEnv/) } - end - end - - context 'as an invalid string' do - let(:params) { { :sshd_acceptenv => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_acceptenv may be either 'true' or 'false' and is set to <invalid>\./) - end - end - - context 'as an invalid type' do - let(:params) { { :sshd_acceptenv => ['invalid','type'] } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_acceptenv type must be true or false\./) - end - end - end - - describe 'with parameter service_hasstatus' do - ['true',true,'false',false].each do |value| - context "specified as #{value}" do - let(:params) { { :service_hasstatus => value } } - - it { - should contain_service('sshd_service').with({ - 'ensure' => 'running', - 'name' => 'sshd', - 'enable' => 'true', - 'hasrestart' => 'true', - 'hasstatus' => value, - 'subscribe' => 'File[sshd_config]', - }) - } - end - end - - context 'specified as an invalid string' do - let(:params) { { :service_hasstatus => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::service_hasstatus must be 'true' or 'false' and is set to <invalid>\./) - end - end - - context 'specified as an invalid type' do - let(:params) { { :service_hasstatus => ['invalid','type'] } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::service_hasstatus must be true or false\./) - end - end - end - - describe 'with parameter ssh_config_global_known_hosts_file' do - context 'specified as a valid path' do - let(:params) { { :ssh_config_global_known_hosts_file => '/valid/path' } } - - it { - should contain_file('ssh_known_hosts').with({ - 'ensure' => 'file', - 'path' => '/valid/path', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - 'require' => ['Package[openssh-server]', 'Package[openssh-clients]'], - }) - } - - it { should contain_file('ssh_config').with_content(/^\s*GlobalKnownHostsFile \/valid\/path$/) } - end - - context 'specified as an invalid path' do - let(:params) { { :ssh_config_global_known_hosts_file => 'invalid/path' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/\"invalid\/path\" is not an absolute path\./) - end - end - - context 'specified as an invalid type' do - let(:params) { { :ssh_config_global_known_hosts_file => { 'invalid' => 'type'} } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not an absolute path/) - end - end - end - - describe 'with parameter ssh_config_global_known_hosts_list' do - context 'when set to an array of valid absolute paths' do - let(:params) { {'ssh_config_global_known_hosts_list' => ['/valid/path1','/valid/path2'] } } - - it { should contain_file('ssh_config').with_content(/^\s*GlobalKnownHostsFile.*\/valid\/path1 \/valid\/path2$/) } - end - - context 'specified as an invalid path' do - let(:params) { { :ssh_config_global_known_hosts_list => ['/valid/path','invalid/path'] } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/\"invalid\/path\" is not an absolute path\./) - end - end - - ['YES',true,2.42,a = { 'ha' => 'sh' }].each do |value| - context "specified as invalid value #{value} (as #{value.class})" do - let(:params) { { :ssh_config_global_known_hosts_list => value } } - - if value.is_a?(Hash) - value = '{ha => sh}' - end - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error, /is not an Array/) - end - end - end - end - - describe 'with parameter ssh_config_user_known_hosts_file' do - context 'when set to an array of paths' do - let(:params) { {'ssh_config_user_known_hosts_file' => ['valid/path1','/valid/path2'] } } - - it { should contain_file('ssh_config').with_content(/^\s*UserKnownHostsFile valid\/path1 \/valid\/path2$/) } - end - - ['YES',true,2.42,a = { 'ha' => 'sh' }].each do |value| - context "specified as invalid value #{value} (as #{value.class})" do - let(:params) { { :ssh_config_user_known_hosts_file => value } } - - if value.is_a?(Hash) - value = '{ha => sh}' - end - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error, /is not an Array/) - end - end - end - end - - describe 'with parameter ssh_config_global_known_hosts_owner' do - context 'specified as a valid string' do - let(:params) { { :ssh_config_global_known_hosts_owner => 'gh' } } - - it { - should contain_file('ssh_known_hosts').with({ - 'ensure' => 'file', - 'path' => '/etc/ssh/ssh_known_hosts', - 'owner' => 'gh', - 'group' => 'root', - 'mode' => '0644', - 'require' => ['Package[openssh-server]', 'Package[openssh-clients]'], - }) - } - end - - context 'specified as an invalid type [non-string]' do - let(:params) { { :ssh_config_global_known_hosts_owner => ['invalid','type'] } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/\[\"invalid\", \"type\"\] is not a string\. It looks to be a Array/) - end - end - end - - describe 'with parameter ssh_config_global_known_hosts_group' do - context 'specified as a valid string' do - let(:params) { { :ssh_config_global_known_hosts_group => 'gh' } } - - it { - should contain_file('ssh_known_hosts').with({ - 'ensure' => 'file', - 'path' => '/etc/ssh/ssh_known_hosts', - 'owner' => 'root', - 'group' => 'gh', - 'mode' => '0644', - 'require' => ['Package[openssh-server]', 'Package[openssh-clients]'], - }) - } - end - - context 'specified as an invalid type [non-string]' do - let(:params) { { :ssh_config_global_known_hosts_group => ['invalid','type'] } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/\[\"invalid\", \"type\"\] is not a string\. It looks to be a Array/) - end - end - end - - describe 'with parameter ssh_config_global_known_hosts_mode' do - context 'specified as a valid mode' do - let(:params) { { :ssh_config_global_known_hosts_mode => '0666' } } - - it { - should contain_file('ssh_known_hosts').with({ - 'ensure' => 'file', - 'path' => '/etc/ssh/ssh_known_hosts', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0666', - 'require' => ['Package[openssh-server]', 'Package[openssh-clients]'], - }) - } - end - - ['666','0842','06666'].each do |value| - context "specified as invalid mode - #{value}" do - let(:params) { { :ssh_config_global_known_hosts_mode => value } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::ssh_config_global_known_hosts_mode must be a valid 4 digit mode in octal notation\. Detected value is <#{value}>\./) - end - end - end - - context 'specified as an invalid type [non-string]' do - let(:params) { { :ssh_config_global_known_hosts_mode => ['invalid','type'] } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::ssh_config_global_known_hosts_mode must be a valid 4 digit mode in octal notation\. Detected value is <[\[]?invalid.*type[\]]?/) - end - end - end - - describe 'with ssh_key_import parameter specified' do - context 'as a non-boolean or non-string' do - let(:params) { { :ssh_key_import => ['not_a_boolean','or_a_string'] } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error) - end - end - - context 'as an invalid string' do - let(:params) { { :ssh_key_import => 'invalid_string' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::ssh_key_import may be either 'true' or 'false' and is set to <invalid_string>\./) - end - end - - ['true',true].each do |value| - context "as #{value}" do - let(:params) { { :ssh_key_import => value } } - - it { should compile.with_all_deps } - - it { should contain_class('ssh') } - - it { - should contain_file('ssh_known_hosts').with({ - 'ensure' => 'file', - 'path' => '/etc/ssh/ssh_known_hosts', - 'owner' => 'root', - 'group' => 'root', - 'mode' => '0644', - 'require' => ['Package[openssh-server]', 'Package[openssh-clients]'], - }) - } - end - end - - ['false',false].each do |value| - context "as #{value}" do - let(:params) { { :ssh_key_import => value } } - - it { should compile.with_all_deps } - - it { should contain_class('ssh') } - end - end - end - - describe 'with parameter sshd_hostbasedauthentication' do - ['yes','no'].each do |value| - context "specified as valid #{value} (as #{value.class})" do - let(:params) { { :sshd_hostbasedauthentication => value } } - - it { should contain_file('sshd_config').with_content(/^HostbasedAuthentication #{value}$/) } - end - end - - ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value| - context "specified as invalid value #{value} (as #{value.class})" do - let(:params) { { :sshd_hostbasedauthentication => value } } - - if value.is_a?(Array) - value = value.join - end - - it do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_hostbasedauthentication may be either 'yes' or 'no' and is set to/) - end - end - end - end - - [true,'invalid'].each do |pubkeyacceptedkeytypes| - context "with sshd_pubkeyacceptedkeytypes set to invalid value #{pubkeyacceptedkeytypes}" do - let(:params) { { :sshd_pubkeyacceptedkeytypes => pubkeyacceptedkeytypes } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not/) - end - end - end - - [true,'invalid'].each do |authenticationmethods| - context "with sshd_config_authenticationmethods set to invalid value #{authenticationmethods}" do - let(:params) { { :sshd_config_authenticationmethods => authenticationmethods } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/is not/) - end - end - end - - describe 'with parameter sshd_pubkeyauthentication' do - ['yes','no'].each do |value| - context "specified as valid #{value} (as #{value.class})" do - let(:params) { { :sshd_pubkeyauthentication => value } } - - it { should contain_file('sshd_config').with_content(/^PubkeyAuthentication #{value}$/) } - end - end - - ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value| - context "specified as invalid value #{value} (as #{value.class})" do - let(:params) { { :sshd_pubkeyauthentication => value } } - if value.is_a?(Array) - value = value.join - end - - it do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_pubkeyauthentication may be either 'yes' or 'no' and is set to/) - end - end - end - end - - describe 'with parameter sshd_ignoreuserknownhosts' do - ['yes','no'].each do |value| - context "specified as valid #{value} (as #{value.class})" do - let(:params) { { :sshd_ignoreuserknownhosts => value } } - - it { should contain_file('sshd_config').with_content(/^IgnoreUserKnownHosts #{value}$/) } - end - end - - ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value| - context "specified as invalid value #{value} (as #{value.class})" do - let(:params) { { :sshd_ignoreuserknownhosts => value } } - if value.is_a?(Array) - value = value.join - end - - it do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_ignoreuserknownhosts may be either 'yes' or 'no' and is set to/) - end - end - end - end - - describe 'with parameter sshd_ignorerhosts' do - ['yes','no'].each do |value| - context "specified as valid #{value} (as #{value.class})" do - let(:params) { { :sshd_ignorerhosts => value } } - - it { should contain_file('sshd_config').with_content(/^IgnoreRhosts #{value}$/) } - end - end - - ['YES',true,2.42,['array'],a = { 'ha' => 'sh' }].each do |value| - context "specified as invalid value #{value} (as #{value.class})" do - let(:params) { { :sshd_ignorerhosts => value } } - if value.is_a?(Array) - value = value.join - end - - it do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_ignorerhosts may be either 'yes' or 'no' and is set to/) - end - end - end - end - - describe 'with parameter manage_service' do - ['YES','badvalue',2.42,['array'],a = { 'ha' => 'sh' }].each do |value| - context "specified as invalid value #{value} (as #{value.class})" do - let(:params) { { :manage_service => value } } - it do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/(is not a boolean|Unknown type of boolean)/) - end - end - end - - ['true', true].each do |value| - context "specified as valid true value #{value} (as #{value.class})" do - let(:params) { { :manage_service => value } } - it { should contain_service('sshd_service') } - end - end - - ['false', false].each do |value| - context "specified as valid false value #{value} (as #{value.class})" do - let(:params) { { :manage_service => value } } - it { should_not contain_service('sshd_service') } - end - end - end - - describe 'sshd_config_tcp_keepalive param' do - ['yes','no','unset'].each do |value| - context "set to #{value}" do - let (:params) { { :sshd_config_tcp_keepalive => value } } - - if value == 'unset' - it { should contain_file('sshd_config').without_content(/^\s*TCPKeepAlive/) } - else - it { should contain_file('sshd_config').with_content(/^TCPKeepAlive #{value}$/) } - end - end - end - - context 'when set to an invalid value' do - let (:params) { { :sshd_config_tcp_keepalive => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_tcp_keepalive may be either \'yes\', \'no\' or \'unset\' and is set to <invalid>\./) - end - end - end - - describe 'sshd_config_use_privilege_separation param' do - ['yes','no','sandbox'].each do |value| - context "set to #{value}" do - let (:params) { { :sshd_config_use_privilege_separation => value } } - - it { should contain_file('sshd_config').with_content(/^UsePrivilegeSeparation #{value}$/) } - end - end - - context 'when set to an invalid value' do - let (:params) { { :sshd_config_use_privilege_separation => 'invalid' } } - - it 'should fail' do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_config_use_privilege_separation may be either \'yes\', \'no\' or \'sandbox\' and is set to <invalid>\./) - end - end - end - - describe 'with parameter sshd_addressfamily' do - ['any','inet','inet6'].each do |value| - context "set to a valid entry of #{value}" do - let(:params) { { :sshd_addressfamily => value } } - it { should contain_file('sshd_config').with_content(/^AddressFamily #{value}$/) } - end - end - - ['foo','bar',123].each do |value| - context "specified as invalid value #{value}" do - let(:params) { { :sshd_addressfamily => value } } - it do - expect { - should contain_class('ssh') - }.to raise_error(Puppet::Error,/ssh::sshd_addressfamily can be undef, 'any', 'inet' or 'inet6' and is set to/) - end - end - end - end - - describe 'with parameter ssh_config_use_roaming' do - ['yes','no','unset'].each do |value| - context "set to valid value #{value}" do - let(:params) { { :ssh_config_use_roaming => value } } - if value == 'unset' - it { should contain_file('ssh_config').without_content(/^\s*UseRoaming/) } - else - it { should contain_file('ssh_config').with_content(/^\s*UseRoaming #{value}$/) } - end - end - end - end - - describe 'variable type and content validations' do - mandatory_params = {} if mandatory_params.nil? - - validations = { - 'hash' => { - :name => %w[config_entries], - :valid => [], # valid hashes are to complex to block test them here. types::mount should have its own spec tests anyway. - :invalid => ['string', %w[array], 3, 2.42, true], - :message => 'is not a Hash', - }, - 'regex (yes|no|unset)' => { - :name => %w(ssh_config_use_roaming), - :valid => ['yes', 'no', 'unset'], - :invalid => ['string', %w(array), { 'ha' => 'sh' }, 3, 2.42, true, false, nil], - :message => 'may be either \'yes\', \'no\' or \'unset\'', - }, - } - - validations.sort.each do |type, var| - var[:name].each do |var_name| - var[:params] = {} if var[:params].nil? - var[:valid].each do |valid| - context "when #{var_name} (#{type}) is set to valid #{valid} (as #{valid.class})" do - let(:params) { [mandatory_params, var[:params], { :"#{var_name}" => valid, }].reduce(:merge) } - it { should compile } - end - end - - var[:invalid].each do |invalid| - context "when #{var_name} (#{type}) is set to invalid #{invalid} (as #{invalid.class})" do - let(:params) { [mandatory_params, var[:params], { :"#{var_name}" => invalid, }].reduce(:merge) } - it { is_expected.to compile.and_raise_error(/#{var[:message]}/) } - end - end - end # var[:name].each - end # validations.sort.each - end # describe 'variable type and content validations' end
diff --git a/spec/classes/server_spec.rb b/spec/classes/server_spec.rb new file mode 100644 index 0000000..89ea304 --- /dev/null +++ b/spec/classes/server_spec.rb
@@ -0,0 +1,1321 @@ +require 'spec_helper' + +describe 'ssh::server' do + + osfamily_matrix = { +# 'Debian-7' => { +# :architecture => 'x86_64', +# :osfamily => 'Debian', +# :operatingsystemrelease => '7', +# :ssh_version => 'OpenSSH_6.0p1', +# :ssh_version_numeric => '6.0', +# :sshd_packages => ['openssh-server', 'openssh-client'], +# :sshd_config_mode => '0600', +# :sshd_service_name => 'ssh', +# :sshd_service_hasstatus => true, +# :sshd_config_fixture => 'sshd_config_debian', +# :ssh_config_fixture => 'ssh_config_debian', +# }, + 'RedHat-5' => { + :architecture => 'x86_64', + :os => { + :family => 'RedHat', + :release => { + :major => '5', + }, + }, + :ssh_version => 'OpenSSH_4.3p2', + :ssh_version_numeric => '4.3', + :sshd_packages => ['openssh-server'], + :sshd_config_mode => '0600', + :sshd_service_name => 'sshd', + :sshd_service_hasstatus => true, + :sshd_config_fixture => 'sshd_config_el5', + }, + 'EL-6' => { + :architecture => 'x86_64', + :os => { + :family => 'RedHat', + :release => { + :major => '6', + }, + }, + :ssh_version => 'OpenSSH_5.3p1', + :ssh_version_numeric => '5.3', + :sshd_packages => ['openssh-server'], + :sshd_config_mode => '0600', + :sshd_service_name => 'sshd', + :sshd_service_hasstatus => true, + :sshd_config_fixture => 'sshd_config_el6', + }, + 'EL-7' => { + :architecture => 'x86_64', + :os => { + :family => 'RedHat', + :release => { + :major => '7', + }, + }, + :ssh_version => 'OpenSSH_7.4p1', + :ssh_version_numeric => '7.4', + :sshd_config_mode => '0600', + :sshd_service_name => 'sshd', + :sshd_service_hasstatus => true, + :sshd_packages => ['openssh-server'], + :sshd_config_fixture => 'sshd_config_el7', + }, +# 'Suse-10-x86_64' => { +# :architecture => 'x86_64', +# :osfamily => 'Suse', +# :operatingsystem => 'SLES', +# :operatingsystemrelease => '10.4', +# :ssh_version => 'OpenSSH_5.1p1', +# :ssh_version_numeric => '5.1', +# :sshd_packages => ['openssh'], +# :sshd_config_mode => '0600', +# :sshd_service_name => 'sshd', +# :sshd_service_hasstatus => true, +# :sshd_config_fixture => 'sshd_config_suse_x86_64', +# :ssh_config_fixture => 'ssh_config_suse_old', +# }, +# 'Suse-10-i386' => { +# :architecture => 'i386', +# :osfamily => 'Suse', +# :operatingsystem => 'SLES', +# :operatingsystemrelease => '10.4', +# :ssh_version => 'OpenSSH_5.1p1', +# :ssh_version_numeric => '5.1', +# :sshd_packages => ['openssh'], +# :sshd_config_mode => '0600', +# :sshd_service_name => 'sshd', +# :sshd_service_hasstatus => true, +# :sshd_config_fixture => 'sshd_config_suse_i386', +# :ssh_config_fixture => 'ssh_config_suse_old', +# }, +# 'Suse-11-x86_64' => { +# :architecture => 'x86_64', +# :osfamily => 'Suse', +# :operatingsystem => 'SLES', +# :operatingsystemrelease => '11.4', +# :ssh_version => 'OpenSSH_6.6.1p1', +# :ssh_version_numeric => '6.6', +# :sshd_packages => ['openssh'], +# :sshd_config_mode => '0600', +# :sshd_service_name => 'sshd', +# :sshd_service_hasstatus => true, +# :sshd_config_fixture => 'sshd_config_suse_x86_64', +# :ssh_config_fixture => 'ssh_config_suse', +# }, +# 'Suse-11-i386' => { +# :architecture => 'i386', +# :osfamily => 'Suse', +# :operatingsystem => 'SLES', +# :operatingsystemrelease => '11.4', +# :ssh_version => 'OpenSSH_6.6.1p1', +# :ssh_version_numeric => '6.6', +# :sshd_packages => ['openssh'], +# :sshd_config_mode => '0600', +# :sshd_service_name => 'sshd', +# :sshd_service_hasstatus => true, +# :sshd_config_fixture => 'sshd_config_suse_i386', +# :ssh_config_fixture => 'ssh_config_suse', +# }, +# 'Suse-12-x86_64' => { +# :architecture => 'x86_64', +# :osfamily => 'Suse', +# :operatingsystem => 'SLES', +# :operatingsystemrelease => '12.0', +# :ssh_version => 'OpenSSH_6.6.1p1', +# :ssh_version_numeric => '6.6', +# :sshd_packages => ['openssh'], +# :sshd_config_mode => '0600', +# :sshd_service_name => 'sshd', +# :sshd_service_hasstatus => true, +# :sshd_config_fixture => 'sshd_config_sles_12_x86_64', +# :ssh_config_fixture => 'ssh_config_suse', +# }, +# 'Solaris-5.11' => { +# :architecture => 'i86pc', +# :osfamily => 'Solaris', +# :kernelrelease => '5.11', +# :ssh_version => 'Sun_SSH_2.2', +# :ssh_version_numeric => '2.2', +# :sshd_packages => ['network/ssh', 'network/ssh/ssh-key', 'service/network/ssh'], +# :sshd_config_mode => '0644', +# :sshd_service_name => 'ssh', +# :sshd_service_hasstatus => true, +# :sshd_config_fixture => 'sshd_config_solaris', +# :ssh_config_fixture => 'ssh_config_solaris', +# }, +# 'Solaris-5.10' => { +# :architecture => 'i86pc', +# :osfamily => 'Solaris', +# :kernelrelease => '5.10', +# :ssh_version => 'Sun_SSH_2.2', +# :ssh_version_numeric => '2.2', +# :sshd_packages => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'], +# :sshd_config_mode => '0644', +# :sshd_service_name => 'ssh', +# :sshd_service_hasstatus => true, +# :sshd_config_fixture => 'sshd_config_solaris', +# :ssh_config_fixture => 'ssh_config_solaris', +# }, +# 'Solaris-5.9' => { +# :architecture => 'i86pc', +# :osfamily => 'Solaris', +# :kernelrelease => '5.9', +# :ssh_version => 'Sun_SSH_2.2', +# :ssh_version_numeric => '2.2', +# :sshd_packages => ['SUNWsshcu', 'SUNWsshdr', 'SUNWsshdu', 'SUNWsshr', 'SUNWsshu'], +# :sshd_config_mode => '0644', +# :sshd_service_name => 'sshd', +# :sshd_service_hasstatus => false, +# :sshd_config_fixture => 'sshd_config_solaris', +# :ssh_config_fixture => 'ssh_config_solaris', +# }, +# 'Ubuntu-1604' => { +# :architecture => 'x86_64', +# :osfamily => 'Debian', +# :operatingsystemrelease => '16.04', +# :ssh_version => 'OpenSSH_7.2p2', +# :ssh_version_numeric => '7.2', +# :sshd_packages => ['openssh-server', 'openssh-client'], +# :sshd_config_mode => '0600', +# :sshd_service_name => 'ssh', +# :sshd_service_hasstatus => true, +# :sshd_config_fixture => 'sshd_config_ubuntu1604', +# :ssh_config_fixture => 'ssh_config_ubuntu1604', +# }, + } + + defaults = { + :fqdn => 'monkey.example.com', + :hostname => 'monkey', + :ipaddress => '127.0.0.1', + :root_home => '/root', + :specific => 'dummy', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==', + } + + defaults_solaris = { + :fqdn => 'monkey.example.com', + :hostname => 'monkey', + :ipaddress => '127.0.0.1', + :kernelrelease => '5.10', + :osfamily => 'Solaris', + :root_home => '/root', + :specific => 'dummy', + :ssh_version => 'Sun_SSH_2.2', + :ssh_version_numeric => '2.2', + :sshrsakey => 'AAAAB3NzaC1yc2EAAAABIwAAAQEArGElx46pD6NNnlxVaTbp0ZJMgBKCmbTCT3RaeCk0ZUJtQ8wkcwTtqIXmmiuFsynUT0DFSd8UIodnBOPqitimmooAVAiAi30TtJVzADfPScMiUnBJKZajIBkEMkwUcqsfh630jyBvLPE/kyQcxbEeGtbu1DG3monkeymanOBW1AKc5o+cJLXcInLnbowMG7NXzujT3BRYn/9s5vtT1V9cuZJs4XLRXQ50NluxJI7sVfRPVvQI9EMbTS4AFBXUej3yfgaLSV+nPZC/lmJ2gR4t/tKvMFF9m16f8IcZKK7o0rK7v81G/tREbOT5YhcKLK+0wBfR6RsmHzwy4EddZloyLQ==', + } + + default_facts = osfamily_matrix['EL-7'].merge(defaults) + + let(:facts) { default_facts } + + osfamily_matrix.each do |os, facts| + context "with default params on osfamily #{os}" do + let(:facts) { defaults.merge(facts)} + + # FIXME - first one fails. If you remove the duplicate, the first compile + # fails, if you remove both compile lines, then contain class fails and so on. Get this error + # + # Evaluation Error: Error while evaluating a Resource Statement, Could not autoload puppet/type/service: Could not autoload puppet/provider/service/upstart: Could not autoload puppet/provider/service/debian: Could not autoload puppet/provider/service/init: undefined method `downcase' for nil:NilClass (file: /Users/gh/git/puppet-module-ssh/spec/fixtures/modules/ssh/manifests/server.pp, line: 332, column: 5) + it { should compile.with_all_deps } + it { should compile.with_all_deps } + + it { should contain_class('ssh::server')} + + facts[:sshd_packages].each do |pkg| + it { + should contain_package(pkg).with({ + 'ensure' => 'installed', + }) + } + end + + it { + should contain_file('sshd_config').with({ + 'ensure' => 'file', + 'path' => '/etc/ssh/sshd_config', + 'owner' => 'root', + 'group' => 'root', + 'mode' => facts[:sshd_config_mode], + }) + } + + facts[:sshd_packages].each do |pkg| + it { + should contain_file('sshd_config').that_requires("Package[#{pkg}]") + } + end + + sshd_config_fixture = File.read(fixtures("#{facts[:sshd_config_fixture]}_sorted")) + it { should contain_file('sshd_config').with_content(sshd_config_fixture) } + + it { should_not contain_file('sshd_banner') } + + it { + should contain_service('sshd_service').with({ + 'ensure' => 'running', + 'name' => facts[:sshd_service_name], + 'enable' => 'true', + 'hasrestart' => 'true', + 'hasstatus' => facts[:sshd_service_hasstatus], + 'subscribe' => 'File[sshd_config]', + }) + } + end + end + +# TODO: test failure on unsupported platforms +# context 'with default params on invalid osfamily' do +# let(:facts) { default_facts.merge({ :osfamily => 'C64' }) } +# +# it 'should fail' do +# expect { +# should contain_class('ssh') +# }.to raise_error(Puppet::Error,/ssh supports osfamilies RedHat, Suse, Debian and Solaris\. Detected osfamily is <C64>\./) +# end +# end +# + + # TODO: test each param here + # + describe 'with parameter' do + + context 'syslog_facility' do + context "set to a valid facility" do + let(:params) do { :syslog_facility => 'LOCAL1' } end + + it { should contain_file('sshd_config').with_content(/^SyslogFacility LOCAL1$/) } + end + end + + context 'stream_local_bind_mask' do + context "set to a valid umask" do + let(:params) do { :stream_local_bind_mask => '0022' } end + + it { should contain_file('sshd_config').with_content(/^StreamLocalBindMask 0022$/) } + end + end + + context 'client_alive_count_max' do + context "set to a valid Integer" do + let(:params) do { :client_alive_count_max => 23 } end + + it { should contain_file('sshd_config').with_content(/^ClientAliveCountMax 23$/) } + end + end + + context 'client_alive_interval' do + context "set to a valid Integer" do + let(:params) do { :client_alive_interval => 23 } end + + it { should contain_file('sshd_config').with_content(/^ClientAliveInterval 23$/) } + end + end + + context 'login_grace_time' do + context "set to a valid Integer" do + let(:params) do { :login_grace_time => 23 } end + + it { should contain_file('sshd_config').with_content(/^LoginGraceTime 23$/) } + end + end + + context 'max_auth_tries' do + context "set to a valid Integer" do + let(:params) do { :max_auth_tries => 23 } end + + it { should contain_file('sshd_config').with_content(/^MaxAuthTries 23$/) } + end + end + + context 'max_sessions' do + context "set to a valid Integer" do + let(:params) do { :max_sessions => 23 } end + + it { should contain_file('sshd_config').with_content(/^MaxSessions 23$/) } + end + end + + context 'x11_display_offset' do + context "set to a valid Integer" do + let(:params) do { :x11_display_offset => 23 } end + + it { should contain_file('sshd_config').with_content(/^X11DisplayOffset 23$/) } + end + end + + context 'authorized_keys_command' do + context "set to valid string 'test'" do + let(:params) do { :authorized_keys_command => 'test' } end + + it { should contain_file('sshd_config').with_content(/^AuthorizedKeysCommand test$/) } + end + end + + context 'authorized_keys_command_user' do + context "set to valid string 'test'" do + let(:params) do { :authorized_keys_command_user => 'test' } end + + it { should contain_file('sshd_config').with_content(/^AuthorizedKeysCommandUser test$/) } + end + end + + context 'authorized_principals_command' do + context "set to valid string 'test'" do + let(:params) do { :authorized_principals_command => 'test' } end + + it { should contain_file('sshd_config').with_content(/^AuthorizedPrincipalsCommand test$/) } + end + end + + context 'authorized_principals_command_user' do + context "set to valid string 'test'" do + let(:params) do { :authorized_principals_command_user => 'test' } end + + it { should contain_file('sshd_config').with_content(/^AuthorizedPrincipalsCommandUser test$/) } + end + end + + context 'authorized_principals_file' do + context "set to valid string 'test'" do + let(:params) do { :authorized_principals_file => 'test' } end + + it { should contain_file('sshd_config').with_content(/^AuthorizedPrincipalsFile test$/) } + end + end + + context 'banner' do + context "set to valid string 'test'" do + let(:params) do { :banner => 'test' } end + + it { should contain_file('sshd_config').with_content(/^Banner test$/) } + end + end + + context 'challenge_response_authentication' do + context "set to valid string 'test'" do + let(:params) do { :challenge_response_authentication => 'test' } end + + it { should contain_file('sshd_config').with_content(/^ChallengeResponseAuthentication test$/) } + end + end + + context 'chroot_directory' do + context "set to valid string 'test'" do + let(:params) do { :chroot_directory => 'test' } end + + it { should contain_file('sshd_config').with_content(/^ChrootDirectory test$/) } + end + end + + context 'force_command' do + context "set to valid string 'test'" do + let(:params) do { :force_command => 'test' } end + + it { should contain_file('sshd_config').with_content(/^ForceCommand test$/) } + end + end + + context 'host_certificate' do + context "set to valid string 'test'" do + let(:params) do { :host_certificate => 'test' } end + + it { should contain_file('sshd_config').with_content(/^HostCertificate test$/) } + end + end + + context 'host_key_agent' do + context "set to valid string 'test'" do + let(:params) do { :host_key_agent => 'test' } end + + it { should contain_file('sshd_config').with_content(/^HostKeyAgent test$/) } + end + end + + context 'ip_qos' do + context "set to valid string 'test'" do + let(:params) do { :ip_qos => 'test' } end + + it { should contain_file('sshd_config').with_content(/^IPQoS test$/) } + end + end + + context 'log_level' do + context "set to valid string 'DEBUG1'" do + let(:params) do { :log_level => 'DEBUG1' } end + + it { should contain_file('sshd_config').with_content(/^LogLevel DEBUG1$/) } + end + end + + context 'max_startups' do + context "set to valid string 'test'" do + let(:params) do { :max_startups => 'test' } end + + it { should contain_file('sshd_config').with_content(/^MaxStartups test$/) } + end + end + + context 'permit_user_environment' do + context "set to valid string 'test'" do + let(:params) do { :permit_user_environment => 'test' } end + + it { should contain_file('sshd_config').with_content(/^PermitUserEnvironment test$/) } + end + end + + context 'pid_file' do + context "set to valid string 'test'" do + let(:params) do { :pid_file => 'test' } end + + it { should contain_file('sshd_config').with_content(/^PidFile test$/) } + end + end + + context 'rekey_limit' do + context "set to valid string 'test'" do + let(:params) do { :rekey_limit => 'test' } end + + it { should contain_file('sshd_config').with_content(/^RekeyLimit test$/) } + end + end + + context 'revoked_keys' do + context "set to valid string 'test'" do + let(:params) do { :revoked_keys => 'test' } end + + it { should contain_file('sshd_config').with_content(/^RevokedKeys test$/) } + end + end + + context 'rdomain' do + context "set to valid string 'test'" do + let(:params) do { :rdomain => 'test' } end + + it { should contain_file('sshd_config').with_content(/^RDomain test$/) } + end + end + + context 'set_env' do + context "set to valid string 'test'" do + let(:params) do { :set_env => 'test' } end + + it { should contain_file('sshd_config').with_content(/^SetEnv test$/) } + end + end + + context 'subsystem' do + context "set to valid string 'test'" do + let(:params) do { :subsystem => 'test' } end + + it { should contain_file('sshd_config').with_content(/^Subsystem test$/) } + end + end + + context 'trusted_user_ca_keys' do + context "set to valid string 'test'" do + let(:params) do { :trusted_user_ca_keys => 'test' } end + + it { should contain_file('sshd_config').with_content(/^TrustedUserCAKeys test$/) } + end + end + + context 'version_addendum' do + context "set to valid string 'test'" do + let(:params) do { :version_addendum => 'test' } end + + it { should contain_file('sshd_config').with_content(/^VersionAddendum test$/) } + end + end + + context 'xauth_location' do + context "set to valid string 'test'" do + let(:params) do { :xauth_location => 'test' } end + + it { should contain_file('sshd_config').with_content(/^XAuthLocation test$/) } + end + end + + context 'custom' do + context "set to valid string 'Foo test'" do + let(:params) do { :custom => 'Foo test' } end + + it { should contain_file('sshd_config').with_content(/^Foo test$/) } + end + end + + context 'address_family' do + ['any','inet','inet6'].each do |v| + context "set to valid string #{v}" do + let(:params) do { :address_family => v } end + + it { should contain_file('sshd_config').with_content(/^AddressFamily #{v}$/) } + end + end + end + + context 'allow_stream_local_forwarding' do + ['yes','all','no','local','remote'].each do |v| + context "set to valid string #{v}" do + let(:params) do { :allow_stream_local_forwarding => v } end + + it { should contain_file('sshd_config').with_content(/^AllowStreamLocalForwarding #{v}$/) } + end + end + end + + context 'allow_tcp_forwarding' do + ['yes','no','local','remote'].each do |v| + context "set to valid string #{v}" do + let(:params) do { :allow_tcp_forwarding => v } end + + it { should contain_file('sshd_config').with_content(/^AllowTcpForwarding #{v}$/) } + end + end + end + + context 'compression' do + ['yes','delayed','no'].each do |v| + context "set to valid string #{v}" do + let(:params) do { :compression => v } end + + it { should contain_file('sshd_config').with_content(/^Compression #{v}$/) } + end + end + end + + context 'fingerprint_hash' do + ['md5','sha256'].each do |v| + context "set to valid string #{v}" do + let(:params) do { :fingerprint_hash => v } end + + it { should contain_file('sshd_config').with_content(/^FingerprintHash #{v}$/) } + end + end + end + + context 'gateway_ports' do + ['no','yes','clientspecified'].each do |v| + context "set to valid string #{v}" do + let(:params) do { :gateway_ports => v } end + + it { should contain_file('sshd_config').with_content(/^GatewayPorts #{v}$/) } + end + end + end + + context 'permit_tunnel' do + ['yes','point-to-point','ethernet','no'].each do |v| + context "set to valid string #{v}" do + let(:params) do { :permit_tunnel => v } end + + it { should contain_file('sshd_config').with_content(/^PermitTunnel #{v}$/) } + end + end + end + + context 'allow_agent_forwarding' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :allow_agent_forwarding => v } end + + it { should contain_file('sshd_config').with_content(/^AllowAgentForwarding #{v}$/) } + end + end + end + + context 'disable_forwarding' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :disable_forwarding => v } end + + it { should contain_file('sshd_config').with_content(/^DisableForwarding #{v}$/) } + end + end + end + + context 'expose_auth_info' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :expose_auth_info => v } end + + it { should contain_file('sshd_config').with_content(/^ExposeAuthInfo #{v}$/) } + end + end + end + + context 'gss_api_authentication' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :gss_api_authentication => v } end + + it { should contain_file('sshd_config').with_content(/^GSSAPIAuthentication #{v}$/) } + end + end + end + + context 'gss_api_cleanup_credentials' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :gss_api_cleanup_credentials => v } end + + it { should contain_file('sshd_config').with_content(/^GSSAPICleanupCredentials #{v}$/) } + end + end + end + + context 'gss_api_strict_acceptor_check' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :gss_api_strict_acceptor_check => v } end + + it { should contain_file('sshd_config').with_content(/^GSSAPIStrictAcceptorCheck #{v}$/) } + end + end + end + + context 'hostbased_authentication' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :hostbased_authentication => v } end + + it { should contain_file('sshd_config').with_content(/^HostbasedAuthentication #{v}$/) } + end + end + end + + context 'hostbased_uses_name_from_packet_only' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :hostbased_uses_name_from_packet_only => v } end + + it { should contain_file('sshd_config').with_content(/^HostbasedUsesNameFromPacketOnly #{v}$/) } + end + end + end + + context 'ignore_rhosts' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :ignore_rhosts => v } end + + it { should contain_file('sshd_config').with_content(/^IgnoreRhosts #{v}$/) } + end + end + end + + context 'ignore_user_known_hosts' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :ignore_user_known_hosts => v } end + + it { should contain_file('sshd_config').with_content(/^IgnoreUserKnownHosts #{v}$/) } + end + end + end + + context 'kbd_interactive_authentication' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :kbd_interactive_authentication => v } end + + it { should contain_file('sshd_config').with_content(/^KbdInteractiveAuthentication #{v}$/) } + end + end + end + + context 'kerberos_authentication' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :kerberos_authentication => v } end + + it { should contain_file('sshd_config').with_content(/^KerberosAuthentication #{v}$/) } + end + end + end + + context 'kerberos_get_afs_token' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :kerberos_get_afs_token => v } end + + it { should contain_file('sshd_config').with_content(/^KerberosGetAFSToken #{v}$/) } + end + end + end + + context 'kerberos_or_local_passwd' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :kerberos_or_local_passwd => v } end + + it { should contain_file('sshd_config').with_content(/^KerberosOrLocalPasswd #{v}$/) } + end + end + end + + context 'kerberos_ticket_cleanup' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :kerberos_ticket_cleanup => v } end + + it { should contain_file('sshd_config').with_content(/^KerberosTicketCleanup #{v}$/) } + end + end + end + + context 'password_authentication' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :password_authentication => v } end + + it { should contain_file('sshd_config').with_content(/^PasswordAuthentication #{v}$/) } + end + end + end + + context 'permit_empty_passwords' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :permit_empty_passwords => v } end + + it { should contain_file('sshd_config').with_content(/^PermitEmptyPasswords #{v}$/) } + end + end + end + + context 'permit_tty' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :permit_tty => v } end + + it { should contain_file('sshd_config').with_content(/^PermitTTY #{v}$/) } + end + end + end + + context 'permit_user_rc' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :permit_user_rc => v } end + + it { should contain_file('sshd_config').with_content(/^PermitUserRC #{v}$/) } + end + end + end + + context 'print_last_log' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :print_last_log => v } end + + it { should contain_file('sshd_config').with_content(/^PrintLastLog #{v}$/) } + end + end + end + + context 'print_motd' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :print_motd => v } end + + it { should contain_file('sshd_config').with_content(/^PrintMotd #{v}$/) } + end + end + end + + context 'pubkey_authentication' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :pubkey_authentication => v } end + + it { should contain_file('sshd_config').with_content(/^PubkeyAuthentication #{v}$/) } + end + end + end + + context 'stream_local_bind_unlink' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :stream_local_bind_unlink => v } end + + it { should contain_file('sshd_config').with_content(/^StreamLocalBindUnlink #{v}$/) } + end + end + end + + context 'strict_modes' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :strict_modes => v } end + + it { should contain_file('sshd_config').with_content(/^StrictModes #{v}$/) } + end + end + end + + context 'tcp_keep_alive' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :tcp_keep_alive => v } end + + it { should contain_file('sshd_config').with_content(/^TCPKeepAlive #{v}$/) } + end + end + end + + context 'use_dns' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :use_dns => v } end + + it { should contain_file('sshd_config').with_content(/^UseDNS #{v}$/) } + end + end + end + + context 'use_pam' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :use_pam => v } end + + it { should contain_file('sshd_config').with_content(/^UsePAM #{v}$/) } + end + end + end + + context 'x11_forwarding' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :x11_forwarding => v } end + + it { should contain_file('sshd_config').with_content(/^X11Forwarding #{v}$/) } + end + end + end + + context 'x11_use_localhost' do + ['yes','no'].each do |v| + context "set to #{v}" do + let(:params) do { :x11_use_localhost => v } end + + it { should contain_file('sshd_config').with_content(/^X11UseLocalhost #{v}$/) } + end + end + end + + context 'accept_env' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :accept_env => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^AcceptEnv test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :accept_env => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^AcceptEnv one$/) } + it { should contain_file('sshd_config').with_content(/^AcceptEnv two$/) } + end + end + + context 'authentication_methods' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :authentication_methods => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^AuthenticationMethods test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :authentication_methods => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^AuthenticationMethods one,two$/) } + end + end + + context 'ca_signature_algorithms' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :ca_signature_algorithms => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^CASignatureAlgorithms test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :ca_signature_algorithms => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^CASignatureAlgorithms one,two$/) } + end + end + + context 'ciphers' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :ciphers => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^Ciphers test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :ciphers => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^Ciphers one,two$/) } + end + end + + context 'hostbased_accepted_key_types' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :hostbased_accepted_key_types => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^HostbasedAcceptedKeyTypes test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :hostbased_accepted_key_types => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^HostbasedAcceptedKeyTypes one,two$/) } + end + end + + context 'host_key' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :host_key => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^HostKey test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :host_key => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^HostKey one$/) } + it { should contain_file('sshd_config').with_content(/^HostKey two$/) } + end + end + + context 'host_key_algorithms' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :host_key_algorithms => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^HostKeyAlgorithms test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :host_key_algorithms => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^HostKeyAlgorithms one,two$/) } + end + end + + context 'kex_algorithms' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :kex_algorithms => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^KexAlgorithms test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :kex_algorithms => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^KexAlgorithms one,two$/) } + end + end + + context 'listen_address' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :listen_address => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^ListenAddress test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :listen_address => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^ListenAddress one$/) } + it { should contain_file('sshd_config').with_content(/^ListenAddress two$/) } + end + end + + context 'macs' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :macs => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^MACs test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :macs => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^MACs one,two$/) } + end + end + + context 'pubkey_accepted_key_types' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :pubkey_accepted_key_types => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^PubkeyAcceptedKeyTypes test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :pubkey_accepted_key_types => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^PubkeyAcceptedKeyTypes one,two$/) } + end + end + + + context 'allow_groups' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :allow_groups => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^AllowGroups test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :allow_groups => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^AllowGroups one two$/) } + end + end + + context 'allow_users' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :allow_users => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^AllowUsers test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :allow_users => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^AllowUsers one two$/) } + end + end + + context 'authorized_keys_file' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :authorized_keys_file => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^AuthorizedKeysFile test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :authorized_keys_file => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^AuthorizedKeysFile one two$/) } + end + end + + context 'deny_groups' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :deny_groups => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^DenyGroups test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :deny_groups => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^DenyGroups one two$/) } + end + end + + context 'deny_users' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :deny_users => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^DenyUsers test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :deny_users => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^DenyUsers one two$/) } + end + end + + context 'permit_listen' do + context "set to an array of strings with one element ['test']" do + let(:params) do { :permit_listen => ['test'] } end + + it { should contain_file('sshd_config').with_content(/^PermitListen test$/) } + end + context "set to an array of strings with multiple elements ['one','two']" do + let(:params) do { :permit_listen => ['one','two'] } end + + it { should contain_file('sshd_config').with_content(/^PermitListen one two$/) } + end + end + end + + describe 'validate data types of parameters' do + validations = { + 'Stdlib::Absolutepath (optional)' => { + :name => %w(package_adminfile package_source), + :valid => ['/absolute/filepath', '/absolute/directory/', :undef], + :invalid => ['../invalid', %w(array), { 'ha' => 'sh' }, 3, 2.42, false], + :message => 'expects a (match for|match for Stdlib::Absolutepath =|Stdlib::Absolutepath =) Variant\[Stdlib::Windowspath.*Stdlib::Unixpath', + }, + 'Stdlib::Absolutepath' => { + :name => %w(banner_path config_path), + :valid => ['/absolute/filepath', '/absolute/directory/'], + :invalid => ['../invalid', %w(array), { 'ha' => 'sh' }, 3, 2.42, false, nil], + :message => 'expects a (match for|match for Stdlib::Absolutepath =|Stdlib::Absolutepath =) Variant\[Stdlib::Windowspath.*Stdlib::Unixpath', + }, + 'Stdlib::Ensure::Service' => { + :name => %w(service_ensure), + :valid => %w(running stopped), + :invalid => ['present', 'absent', %w(array), { 'ha' => 'sh' }, 3, 2.42, false, nil], + :message => 'expects a match for Stdlib::Ensure::Service', + }, + 'Stdlib::Filemode' => { + :name => %w(banner_mode config_mode), + :valid => %w(0644 0755 0640 1740), + :invalid => [2770, '0844', '00644', 'string', %w(array), { 'ha' => 'sh' }, 3, 2.42, false, nil], + :message => 'expects a match for Stdlib::Filemode|Error while evaluating a Resource Statement', + }, + 'Stdlib::Port (optional)' => { + :name => %w(port), + :valid => [0, 65535, :undef], + :invalid => ['string', %w(array), { 'ha' => 'sh' }, -1, 2.42, 65536, false], + :message => 'expects a match for Stdlib::Port|Error while evaluating a Resource Statement', + }, + 'String or Array of strings' => { + :name => %w(packages), + :valid => ['string', %w(array of strings)], + :invalid => [{ 'ha' => 'sh' }, 3, 2.42, false, [0]], + :message => 'String or Array|expects a String value|Error while evaluating a Resource Statement', + }, + 'String or Array of strings (optional)' => { + :name => %w(allow_groups allow_users authorized_keys_file deny_groups deny_users permit_listen), + :valid => ['string', %w(array of strings), :undef], + :invalid => [{ 'ha' => 'sh' }, 3, 2.42, false, [0]], + :message => 'String or Array|expects a String value|Error while evaluating a Resource Statement', + }, + 'Array of strings (optional)' => { + :name => %w(accept_env authentication_methods ca_signature_algorithms ciphers host_key host_key_algorithms + hostbased_accepted_key_types kex_algorithms listen_address macs pubkey_accepted_key_types), + :valid => [%w(array of strings), :undef], + :invalid => ['string', { 'ha' => 'sh' }, 3, 2.42, false, [0]], + :message => 'Undef or Array|expects a String value|Error while evaluating a Resource Statement', + }, + 'integer => 0 (optional)' => { + :name => %w(client_alive_count_max client_alive_interval login_grace_time max_sessions x11_display_offset), + :valid => [0, 1, 23, :undef], + :invalid => ['string', %w(array), { 'ha' => 'sh' }, -1, 2.42, false], + :message => 'Undef or Integer|Error while evaluating a Resource Statement', + }, + 'integer => 2 (optional)' => { + :name => %w(max_auth_tries), + :valid => [2, 23, :undef], + :invalid => ['string', %w(array), { 'ha' => 'sh' }, -1, 2.42, 0, 1, false], + :message => 'Undef or Integer|Error while evaluating a Resource Statement', + }, + 'four digit octal (optional) for umask' => { + :name => %w(stream_local_bind_mask), + :valid => ['0000', '1234', '7777', :undef], + :invalid => ['string', %w(array), { 'ha' => 'sh' }, -1, 2.42, false, '00000', 'x234', '77e1', '011'], + :message => 'Error while evaluating a Resource Statement', + }, + 'enumeration of valid strings for permit_root_login (optional)' => { + :name => %w(permit_root_login), + :valid => ['yes', 'prohibit-password', 'without-password', 'forced-commands-only', 'no', :undef], + :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false], + :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement', + }, + 'enumeration of valid strings for syslog_facility (optional)' => { + :name => %w(syslog_facility), + :valid => ['DAEMON', 'USER', 'AUTH', 'LOCAL0', 'LOCAL1', 'LOCAL2', 'LOCAL3', 'LOCAL4', 'LOCAL5', 'LOCAL6', 'LOCAL7', 'AUTHPRIV', :undef], + :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false, 'USER0', 'daemon'], + :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement', + }, + 'enumeration of valid strings for fingerprint_hash (optional)' => { + :name => %w(fingerprint_hash), + :valid => ['md5', 'sha256', :undef], + :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false], + :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement', + }, + 'enumeration of valid strings for gateway_ports (optional)' => { + :name => %w(gateway_ports), + :valid => ['yes', 'no', 'clientspecified', :undef], + :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false], + :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement', + }, + 'enumeration of valid strings for allow_stream_local_forwarding (optional)' => { + :name => %w(allow_stream_local_forwarding), + :valid => ['yes', 'all', 'no', 'local', 'remote', :undef], + :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false], + :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement', + }, + 'enumeration of valid strings for compression (optional)' => { + :name => %w(compression), + :valid => ['yes', 'no', 'delayed', :undef], + :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false], + :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement', + }, + 'enumeration of valid strings for allow_tcp_forwarding (optional)' => { + :name => %w(allow_tcp_forwarding), + :valid => ['yes', 'no', 'local', 'remote', :undef], + :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false], + :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement', + }, + 'enumeration of valid strings for permit_tunnel (optional)' => { + :name => %w(permit_tunnel), + :valid => ['yes', 'point-to-point', 'ethernet', 'no', :undef], + :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false], + :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement', + }, + 'enumeration of valid strings for address_family (optional)' => { + :name => %w(address_family), + :valid => ['any', 'inet', 'inet6', :undef], + :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false], + :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement', + }, + 'yes or no (optional)' => { + :name => %w(allow_agent_forwarding disable_forwarding expose_auth_info gss_api_authentication gss_api_cleanup_credentials + gss_api_strict_acceptor_check hostbased_authentication hostbased_uses_name_from_packet_only ignore_rhosts ignore_user_known_hosts + kbd_interactive_authentication kerberos_authentication kerberos_get_afs_token kerberos_or_local_passwd kerberos_ticket_cleanup + password_authentication permit_empty_passwords permit_tty permit_user_rc print_last_log print_motd pubkey_authentication + stream_local_bind_unlink strict_modes tcp_keep_alive use_dns use_pam x11_forwarding x11_use_localhost), + :valid => ['yes', 'no', :undef], + :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false, 'YES', 'No'], + :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement', + }, + 'Ssh::Log_level (optional)' => { + :name => %w(log_level), + :valid => ['QUIET', 'FATAL', 'ERROR', 'INFO', 'VERBOSE', 'DEBUG', 'DEBUG1', 'DEBUG2', 'DEBUG3', :undef], + :invalid => ['invalid', %w(array), { 'ha' => 'sh' }, -1, 2.42, false, 'INFO1'], + :message => 'expects an undef value or a match for Pattern|Error while evaluating a Resource Statement', + }, + 'Boolean' => { + :name => %w(manage_service service_enable service_hasrestart service_hasstatus), + :valid => [true, false], + :invalid => ['string', %w(array), { 'ha' => 'sh' }, 3, 2.42, 'false', nil], + :message => 'expects a Boolean', + }, + 'String (optional)' => { + :name => %w(authorized_keys_command authorized_keys_command_user + authorized_principals_command authorized_principals_command_user + authorized_principals_file banner banner_content + challenge_response_authentication chroot_directory force_command + host_certificate host_key_agent ip_qos max_startups + permit_user_environment pid_file rdomain rekey_limit revoked_keys + set_env subsystem trusted_user_ca_keys version_addendum xauth_location + custom), + :valid => ['string', :undef], + :invalid => [%w(array), { 'ha' => 'sh' }, 3, 2.42, false], + :message => 'expects a value of type Undef or String', + }, + } + + validations.sort.each do |type, var| + mandatory_params = {} if mandatory_params.nil? + var[:name].each do |var_name| + var[:params] = {} if var[:params].nil? + var[:valid].each do |valid| + context "when #{var_name} (#{type}) is set to valid #{valid} (as #{valid.class})" do + let(:facts) { [mandatory_facts, var[:facts]].reduce(:merge) } if ! var[:facts].nil? + let(:params) { [mandatory_params, var[:params], { :"#{var_name}" => valid, }].reduce(:merge) } + it { should compile } + end + end + + var[:invalid].each do |invalid| + context "when #{var_name} (#{type}) is set to invalid #{invalid} (as #{invalid.class})" do + let(:params) { [mandatory_params, var[:params], { :"#{var_name}" => invalid, }].reduce(:merge) } + it 'should fail' do + expect { should contain_class(subject) }.to raise_error(Puppet::Error, /#{var[:message]}/) + end + end + end + end # var[:name].each + end # validations.sort.each + end # describe 'validate data types of parameters' +end
diff --git a/spec/defines/config_entry_spec.rb b/spec/defines/config_entry_spec.rb index eee757e..b76f6e3 100644 --- a/spec/defines/config_entry_spec.rb +++ b/spec/defines/config_entry_spec.rb
@@ -66,8 +66,8 @@ end context 'with order set to valid string <242>' do - let(:params) { mandatory_params.merge({ :order => '242' }) } - it { should contain_concat__fragment('/test/path Host test_host').with_order('242') } + let(:params) { mandatory_params.merge({ :order => 242 }) } + it { should contain_concat__fragment('/test/path Host test_host').with_order(242) } end # /!\ no functionality for $ensure implemented yet @@ -78,6 +78,6 @@ context 'with lines set to valid array [ <ForwardX11 no>, <StrictHostKeyChecking no> ]' do let(:params) { mandatory_params.merge({ :lines => ['ForwardX11 no', 'StrictHostKeyChecking no'] }) } - it { should contain_concat__fragment('/test/path Host test_host').with_content("Host test_host\nForwardX11 no\nStrictHostKeyChecking no") } + it { should contain_concat__fragment('/test/path Host test_host').with_content("Host test_host\n ForwardX11 no\n StrictHostKeyChecking no") } end end
diff --git a/spec/fixtures/ssh_config_rhel_old b/spec/fixtures/ssh_config_el5 similarity index 69% rename from spec/fixtures/ssh_config_rhel_old rename to spec/fixtures/ssh_config_el5 index df3d4bc..7a90707 100644 --- a/spec/fixtures/ssh_config_rhel_old +++ b/spec/fixtures/ssh_config_el5
@@ -1,7 +1,4 @@ -# This file is being maintained by Puppet. -# DO NOT EDIT - -# $OpenBSD: ssh_config,v 1.21 2005/12/06 22:38:27 reyk Exp $ +# $OpenBSD: ssh_config,v 1.21 2005/12/06 22:38:27 reyk Exp $ # This is the ssh client system-wide configuration file. See # ssh_config(5) for more information. This file provides defaults for @@ -25,8 +22,7 @@ # ForwardX11 no # RhostsRSAAuthentication no # RSAAuthentication yes - PasswordAuthentication yes - PubkeyAuthentication yes +# PasswordAuthentication yes # HostbasedAuthentication no # BatchMode no # CheckHostIP yes @@ -34,27 +30,23 @@ # ConnectTimeout 0 # StrictHostKeyChecking ask # IdentityFile ~/.ssh/identity - IdentityFile ~/.ssh/id_rsa - IdentityFile ~/.ssh/id_dsa +# IdentityFile ~/.ssh/id_rsa +# IdentityFile ~/.ssh/id_dsa # Port 22 - Protocol 2 +# Protocol 2,1 # Cipher 3des # Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc # EscapeChar ~ # Tunnel no # TunnelDevice any:any # PermitLocalCommand no -# HashKnownHosts no - HashKnownHosts no - GlobalKnownHostsFile /etc/ssh/ssh_known_hosts Host * -# GSSAPIAuthentication yes - GSSAPIAuthentication yes + GSSAPIAuthentication yes # If this option is set to yes then remote X11 clients will have full access # to the original X11 display. As virtually no X11 client supports the untrusted # mode correctly we set this to yes. - ForwardX11Trusted yes + ForwardX11Trusted yes # Send locale-related environment variables - SendEnv LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES - SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT - SendEnv LC_IDENTIFICATION LC_ALL + SendEnv LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES + SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT + SendEnv LC_IDENTIFICATION LC_ALL
diff --git a/spec/fixtures/ssh_config_el5_sorted b/spec/fixtures/ssh_config_el5_sorted new file mode 100644 index 0000000..87ace30 --- /dev/null +++ b/spec/fixtures/ssh_config_el5_sorted
@@ -0,0 +1,23 @@ +# This file is being maintained by Puppet. +# DO NOT EDIT +# +# See https://man.openbsd.org/sshd_config for more info + +Host * + ForwardX11Trusted yes + GSSAPIAuthentication yes + SendEnv LANG + SendEnv LANGUAGE + SendEnv LC_ADDRESS + SendEnv LC_ALL + SendEnv LC_COLLATE + SendEnv LC_CTYPE + SendEnv LC_IDENTIFICATION + SendEnv LC_MEASUREMENT + SendEnv LC_MESSAGES + SendEnv LC_MONETARY + SendEnv LC_NAME + SendEnv LC_NUMERIC + SendEnv LC_PAPER + SendEnv LC_TELEPHONE + SendEnv LC_TIME
diff --git a/spec/fixtures/ssh_config_rhel_old b/spec/fixtures/ssh_config_el6 similarity index 65% copy from spec/fixtures/ssh_config_rhel_old copy to spec/fixtures/ssh_config_el6 index df3d4bc..96c532e 100644 --- a/spec/fixtures/ssh_config_rhel_old +++ b/spec/fixtures/ssh_config_el6
@@ -1,7 +1,4 @@ -# This file is being maintained by Puppet. -# DO NOT EDIT - -# $OpenBSD: ssh_config,v 1.21 2005/12/06 22:38:27 reyk Exp $ +# $OpenBSD: ssh_config,v 1.25 2009/02/17 01:28:32 djm Exp $ # This is the ssh client system-wide configuration file. See # ssh_config(5) for more information. This file provides defaults for @@ -25,36 +22,38 @@ # ForwardX11 no # RhostsRSAAuthentication no # RSAAuthentication yes - PasswordAuthentication yes - PubkeyAuthentication yes +# PasswordAuthentication yes # HostbasedAuthentication no +# GSSAPIAuthentication no +# GSSAPIDelegateCredentials no +# GSSAPIKeyExchange no +# GSSAPITrustDNS no # BatchMode no # CheckHostIP yes # AddressFamily any # ConnectTimeout 0 # StrictHostKeyChecking ask # IdentityFile ~/.ssh/identity - IdentityFile ~/.ssh/id_rsa - IdentityFile ~/.ssh/id_dsa +# IdentityFile ~/.ssh/id_rsa +# IdentityFile ~/.ssh/id_dsa # Port 22 - Protocol 2 +# Protocol 2,1 # Cipher 3des -# Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc +# Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc +# MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160 # EscapeChar ~ # Tunnel no # TunnelDevice any:any # PermitLocalCommand no -# HashKnownHosts no - HashKnownHosts no - GlobalKnownHostsFile /etc/ssh/ssh_known_hosts +# VisualHostKey no Host * -# GSSAPIAuthentication yes - GSSAPIAuthentication yes + GSSAPIAuthentication yes # If this option is set to yes then remote X11 clients will have full access # to the original X11 display. As virtually no X11 client supports the untrusted # mode correctly we set this to yes. - ForwardX11Trusted yes + ForwardX11Trusted yes # Send locale-related environment variables - SendEnv LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES - SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT - SendEnv LC_IDENTIFICATION LC_ALL + SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES + SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT + SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE + SendEnv XMODIFIERS
diff --git a/spec/fixtures/ssh_config_el6_sorted b/spec/fixtures/ssh_config_el6_sorted new file mode 100644 index 0000000..e227ec3 --- /dev/null +++ b/spec/fixtures/ssh_config_el6_sorted
@@ -0,0 +1,24 @@ +# This file is being maintained by Puppet. +# DO NOT EDIT +# +# See https://man.openbsd.org/sshd_config for more info + +Host * + ForwardX11Trusted yes + GSSAPIAuthentication yes + SendEnv LANG + SendEnv LANGUAGE + SendEnv LC_ADDRESS + SendEnv LC_ALL + SendEnv LC_COLLATE + SendEnv LC_CTYPE + SendEnv LC_IDENTIFICATION + SendEnv LC_MEASUREMENT + SendEnv LC_MESSAGES + SendEnv LC_MONETARY + SendEnv LC_NAME + SendEnv LC_NUMERIC + SendEnv LC_PAPER + SendEnv LC_TELEPHONE + SendEnv LC_TIME + SendEnv XMODIFIERS
diff --git a/spec/fixtures/ssh_config_el7 b/spec/fixtures/ssh_config_el7 new file mode 100644 index 0000000..d1c83ea --- /dev/null +++ b/spec/fixtures/ssh_config_el7
@@ -0,0 +1,68 @@ +# $OpenBSD: ssh_config,v 1.30 2016/02/20 23:06:23 sobrado Exp $ + +# This is the ssh client system-wide configuration file. See +# ssh_config(5) for more information. This file provides defaults for +# users, and the values can be changed in per-user configuration files +# or on the command line. + +# Configuration data is parsed as follows: +# 1. command line options +# 2. user-specific file +# 3. system-wide file +# Any configuration value is only changed the first time it is set. +# Thus, host-specific definitions should be at the beginning of the +# configuration file, and defaults at the end. + +# Site-wide defaults for some commonly used options. For a comprehensive +# list of available options, their meanings and defaults, please see the +# ssh_config(5) man page. + +# Host * +# ForwardAgent no +# ForwardX11 no +# RhostsRSAAuthentication no +# RSAAuthentication yes +# PasswordAuthentication yes +# HostbasedAuthentication no +# GSSAPIAuthentication no +# GSSAPIDelegateCredentials no +# GSSAPIKeyExchange no +# GSSAPITrustDNS no +# BatchMode no +# CheckHostIP yes +# AddressFamily any +# ConnectTimeout 0 +# StrictHostKeyChecking ask +# IdentityFile ~/.ssh/identity +# IdentityFile ~/.ssh/id_rsa +# IdentityFile ~/.ssh/id_dsa +# IdentityFile ~/.ssh/id_ecdsa +# IdentityFile ~/.ssh/id_ed25519 +# Port 22 +# Protocol 2 +# Cipher 3des +# Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc +# MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160 +# EscapeChar ~ +# Tunnel no +# TunnelDevice any:any +# PermitLocalCommand no +# VisualHostKey no +# ProxyCommand ssh -q -W %h:%p gateway.example.com +# RekeyLimit 1G 1h +# +# Uncomment this if you want to use .local domain +# Host *.local +# CheckHostIP no + +Host * + GSSAPIAuthentication yes +# If this option is set to yes then remote X11 clients will have full access +# to the original X11 display. As virtually no X11 client supports the untrusted +# mode correctly we set this to yes. + ForwardX11Trusted yes +# Send locale-related environment variables + SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES + SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT + SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE + SendEnv XMODIFIERS
diff --git a/spec/fixtures/ssh_config_el7_sorted b/spec/fixtures/ssh_config_el7_sorted new file mode 100644 index 0000000..e227ec3 --- /dev/null +++ b/spec/fixtures/ssh_config_el7_sorted
@@ -0,0 +1,24 @@ +# This file is being maintained by Puppet. +# DO NOT EDIT +# +# See https://man.openbsd.org/sshd_config for more info + +Host * + ForwardX11Trusted yes + GSSAPIAuthentication yes + SendEnv LANG + SendEnv LANGUAGE + SendEnv LC_ADDRESS + SendEnv LC_ALL + SendEnv LC_COLLATE + SendEnv LC_CTYPE + SendEnv LC_IDENTIFICATION + SendEnv LC_MEASUREMENT + SendEnv LC_MESSAGES + SendEnv LC_MONETARY + SendEnv LC_NAME + SendEnv LC_NUMERIC + SendEnv LC_PAPER + SendEnv LC_TELEPHONE + SendEnv LC_TIME + SendEnv XMODIFIERS
diff --git a/spec/fixtures/ssh_config_rhel b/spec/fixtures/ssh_config_rhel deleted file mode 100644 index 4a1466c..0000000 --- a/spec/fixtures/ssh_config_rhel +++ /dev/null
@@ -1,61 +0,0 @@ -# This file is being maintained by Puppet. -# DO NOT EDIT - -# $OpenBSD: ssh_config,v 1.21 2005/12/06 22:38:27 reyk Exp $ - -# This is the ssh client system-wide configuration file. See -# ssh_config(5) for more information. This file provides defaults for -# users, and the values can be changed in per-user configuration files -# or on the command line. - -# Configuration data is parsed as follows: -# 1. command line options -# 2. user-specific file -# 3. system-wide file -# Any configuration value is only changed the first time it is set. -# Thus, host-specific definitions should be at the beginning of the -# configuration file, and defaults at the end. - -# Site-wide defaults for some commonly used options. For a comprehensive -# list of available options, their meanings and defaults, please see the -# ssh_config(5) man page. - -# Host * -# ForwardAgent no -# ForwardX11 no -# RhostsRSAAuthentication no -# RSAAuthentication yes - PasswordAuthentication yes - PubkeyAuthentication yes -# HostbasedAuthentication no -# BatchMode no -# CheckHostIP yes -# AddressFamily any -# ConnectTimeout 0 -# StrictHostKeyChecking ask -# IdentityFile ~/.ssh/identity - IdentityFile ~/.ssh/id_rsa - IdentityFile ~/.ssh/id_dsa -# Port 22 - Protocol 2 -# Cipher 3des -# Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc -# EscapeChar ~ -# Tunnel no -# TunnelDevice any:any -# PermitLocalCommand no -# HashKnownHosts no - HashKnownHosts no - GlobalKnownHostsFile /etc/ssh/ssh_known_hosts -Host * -# GSSAPIAuthentication yes - GSSAPIAuthentication yes -# If this option is set to yes then remote X11 clients will have full access -# to the original X11 display. As virtually no X11 client supports the untrusted -# mode correctly we set this to yes. - ForwardX11Trusted yes - UseRoaming no -# Send locale-related environment variables - SendEnv LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES - SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT - SendEnv LC_IDENTIFICATION LC_ALL
diff --git a/spec/fixtures/sshd_config_rhel b/spec/fixtures/sshd_config_el5 similarity index 76% rename from spec/fixtures/sshd_config_rhel rename to spec/fixtures/sshd_config_el5 index 8b5c3de..925f43b 100644 --- a/spec/fixtures/sshd_config_rhel +++ b/spec/fixtures/sshd_config_el5
@@ -1,7 +1,4 @@ -# This file is being maintained by Puppet. -# DO NOT EDIT - -# $OpenBSD: sshd_config,v 1.73 2005/12/06 22:38:28 reyk Exp $ +# $OpenBSD: sshd_config,v 1.73 2005/12/06 22:38:28 reyk Exp $ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. @@ -14,67 +11,60 @@ # default value. #Port 22 -Port 22 #Protocol 2,1 Protocol 2 #AddressFamily any -AddressFamily any +#ListenAddress 0.0.0.0 +#ListenAddress :: # HostKey for protocol version 1 #HostKey /etc/ssh/ssh_host_key # HostKeys for protocol version 2 #HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_dsa_key -HostKey /etc/ssh/ssh_host_rsa_key # Lifetime and size of ephemeral version 1 server key #KeyRegenerationInterval 1h -#ServerKeyBits 1024 -ServerKeyBits 1024 +#ServerKeyBits 768 + # Logging # obsoletes QuietMode and FascistLogging #SyslogFacility AUTH -SyslogFacility AUTH +SyslogFacility AUTHPRIV #LogLevel INFO -LogLevel INFO # Authentication: -#LoginGraceTime 120 -LoginGraceTime 120 +#LoginGraceTime 2m #PermitRootLogin yes -PermitRootLogin yes #StrictModes yes #MaxAuthTries 6 #RSAAuthentication yes #PubkeyAuthentication yes -PubkeyAuthentication yes -#AuthorizedKeysFile .ssh/authorized_keys +#AuthorizedKeysFile .ssh/authorized_keys # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts #RhostsRSAAuthentication no # similar for protocol version 2 #HostbasedAuthentication no -HostbasedAuthentication no # Change to yes if you don't trust ~/.ssh/known_hosts for # RhostsRSAAuthentication and HostbasedAuthentication #IgnoreUserKnownHosts no -IgnoreUserKnownHosts no # Don't read the user's ~/.rhosts and ~/.shosts files #IgnoreRhosts yes -IgnoreRhosts yes # To disable tunneled clear text passwords, change to no here! #PasswordAuthentication yes -PasswordAuthentication yes #PermitEmptyPasswords no +PasswordAuthentication yes # Change to no to disable s/key passwords #ChallengeResponseAuthentication yes -ChallengeResponseAuthentication yes +ChallengeResponseAuthentication no # Kerberos options +#KerberosAuthentication no #KerberosOrLocalPasswd yes #KerberosTicketCleanup yes #KerberosGetAFSToken no @@ -97,47 +87,33 @@ UsePAM yes # Accept locale-related environment variables -AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES +AcceptEnv LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT AcceptEnv LC_IDENTIFICATION LC_ALL #AllowTcpForwarding yes -AllowTcpForwarding yes #GatewayPorts no #X11Forwarding no X11Forwarding yes #X11DisplayOffset 10 #X11UseLocalhost yes -X11UseLocalhost yes #PrintMotd yes -PrintMotd yes #PrintLastLog yes #TCPKeepAlive yes -TCPKeepAlive yes #UseLogin no #UsePrivilegeSeparation yes #PermitUserEnvironment no #Compression delayed #ClientAliveInterval 0 -ClientAliveInterval 0 -ClientAliveCountMax 3 +#ClientAliveCountMax 3 #ShowPatchLevel no #UseDNS yes -UseDNS yes #PidFile /var/run/sshd.pid -#MaxStartups 10:30:100 -#MaxSessions 10 - +#MaxStartups 10 #PermitTunnel no -PermitTunnel no #ChrootDirectory none # no default banner path -#Banner none -Banner none - -#XAuthLocation /usr/bin/xauth -XAuthLocation /usr/bin/xauth +#Banner /some/path # override default of no subsystems -Subsystem sftp /usr/libexec/openssh/sftp-server - +Subsystem sftp /usr/libexec/openssh/sftp-server
diff --git a/spec/fixtures/sshd_config_el5_sorted b/spec/fixtures/sshd_config_el5_sorted new file mode 100644 index 0000000..bc7c8a8 --- /dev/null +++ b/spec/fixtures/sshd_config_el5_sorted
@@ -0,0 +1,29 @@ +# This file is being maintained by Puppet. +# DO NOT EDIT +# +# See https://man.openbsd.org/sshd_config for more info + +AcceptEnv LANG +AcceptEnv LANGUAGE +AcceptEnv LC_ADDRESS +AcceptEnv LC_ALL +AcceptEnv LC_COLLATE +AcceptEnv LC_CTYPE +AcceptEnv LC_IDENTIFICATION +AcceptEnv LC_MEASUREMENT +AcceptEnv LC_MESSAGES +AcceptEnv LC_MONETARY +AcceptEnv LC_NAME +AcceptEnv LC_NUMERIC +AcceptEnv LC_PAPER +AcceptEnv LC_TELEPHONE +AcceptEnv LC_TIME +ChallengeResponseAuthentication no +GSSAPIAuthentication yes +GSSAPICleanupCredentials yes +PasswordAuthentication yes +Subsystem sftp /usr/libexec/openssh/sftp-server +SyslogFacility AUTHPRIV +UsePAM yes +X11Forwarding yes +Protocol 2
diff --git a/spec/fixtures/sshd_config_rhel b/spec/fixtures/sshd_config_el6 similarity index 65% copy from spec/fixtures/sshd_config_rhel copy to spec/fixtures/sshd_config_el6 index 8b5c3de..810b458 100644 --- a/spec/fixtures/sshd_config_rhel +++ b/spec/fixtures/sshd_config_el6
@@ -1,7 +1,4 @@ -# This file is being maintained by Puppet. -# DO NOT EDIT - -# $OpenBSD: sshd_config,v 1.73 2005/12/06 22:38:28 reyk Exp $ +# $OpenBSD: sshd_config,v 1.80 2008/07/02 02:24:18 djm Exp $ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. @@ -14,130 +11,129 @@ # default value. #Port 22 -Port 22 -#Protocol 2,1 -Protocol 2 #AddressFamily any -AddressFamily any +#ListenAddress 0.0.0.0 +#ListenAddress :: + +# Disable legacy (protocol version 1) support in the server for new +# installations. In future the default will change to require explicit +# activation of protocol 1 +Protocol 2 # HostKey for protocol version 1 #HostKey /etc/ssh/ssh_host_key # HostKeys for protocol version 2 #HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_dsa_key -HostKey /etc/ssh/ssh_host_rsa_key # Lifetime and size of ephemeral version 1 server key #KeyRegenerationInterval 1h #ServerKeyBits 1024 -ServerKeyBits 1024 + # Logging # obsoletes QuietMode and FascistLogging #SyslogFacility AUTH -SyslogFacility AUTH +SyslogFacility AUTHPRIV #LogLevel INFO -LogLevel INFO # Authentication: -#LoginGraceTime 120 -LoginGraceTime 120 +#LoginGraceTime 2m #PermitRootLogin yes -PermitRootLogin yes #StrictModes yes #MaxAuthTries 6 +#MaxSessions 10 #RSAAuthentication yes #PubkeyAuthentication yes -PubkeyAuthentication yes -#AuthorizedKeysFile .ssh/authorized_keys +#AuthorizedKeysFile .ssh/authorized_keys +#AuthorizedKeysCommand none +#AuthorizedKeysCommandRunAs nobody # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts #RhostsRSAAuthentication no # similar for protocol version 2 #HostbasedAuthentication no -HostbasedAuthentication no # Change to yes if you don't trust ~/.ssh/known_hosts for # RhostsRSAAuthentication and HostbasedAuthentication #IgnoreUserKnownHosts no -IgnoreUserKnownHosts no # Don't read the user's ~/.rhosts and ~/.shosts files #IgnoreRhosts yes -IgnoreRhosts yes # To disable tunneled clear text passwords, change to no here! #PasswordAuthentication yes -PasswordAuthentication yes #PermitEmptyPasswords no +PasswordAuthentication no # Change to no to disable s/key passwords #ChallengeResponseAuthentication yes -ChallengeResponseAuthentication yes +ChallengeResponseAuthentication no # Kerberos options +#KerberosAuthentication no #KerberosOrLocalPasswd yes #KerberosTicketCleanup yes #KerberosGetAFSToken no +#KerberosUseKuserok yes # GSSAPI options #GSSAPIAuthentication no GSSAPIAuthentication yes #GSSAPICleanupCredentials yes GSSAPICleanupCredentials yes +#GSSAPIStrictAcceptorCheck yes +#GSSAPIKeyExchange no -# Set this to 'yes' to enable PAM authentication, account processing, -# and session processing. If this is enabled, PAM authentication will -# be allowed through the ChallengeResponseAuthentication mechanism. -# Depending on your PAM configuration, this may bypass the setting of -# PasswordAuthentication, PermitEmptyPasswords, and -# "PermitRootLogin without-password". If you just want the PAM account and -# session checks to run without PAM authentication, then enable this but set -# ChallengeResponseAuthentication=no +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication. Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. #UsePAM no UsePAM yes # Accept locale-related environment variables AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -AcceptEnv LC_IDENTIFICATION LC_ALL +AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE +AcceptEnv XMODIFIERS + +#AllowAgentForwarding yes #AllowTcpForwarding yes -AllowTcpForwarding yes #GatewayPorts no #X11Forwarding no X11Forwarding yes #X11DisplayOffset 10 #X11UseLocalhost yes -X11UseLocalhost yes #PrintMotd yes -PrintMotd yes #PrintLastLog yes #TCPKeepAlive yes -TCPKeepAlive yes #UseLogin no #UsePrivilegeSeparation yes #PermitUserEnvironment no #Compression delayed #ClientAliveInterval 0 -ClientAliveInterval 0 -ClientAliveCountMax 3 +#ClientAliveCountMax 3 #ShowPatchLevel no #UseDNS yes -UseDNS yes +UseDNS no #PidFile /var/run/sshd.pid #MaxStartups 10:30:100 -#MaxSessions 10 - #PermitTunnel no -PermitTunnel no #ChrootDirectory none # no default banner path #Banner none -Banner none - -#XAuthLocation /usr/bin/xauth -XAuthLocation /usr/bin/xauth # override default of no subsystems -Subsystem sftp /usr/libexec/openssh/sftp-server +Subsystem sftp /usr/libexec/openssh/sftp-server +# Example of overriding settings on a per-user basis +#Match User anoncvs +# X11Forwarding no +# AllowTcpForwarding no +# ForceCommand cvs server
diff --git a/spec/fixtures/sshd_config_el6_sorted b/spec/fixtures/sshd_config_el6_sorted new file mode 100644 index 0000000..660b6ef --- /dev/null +++ b/spec/fixtures/sshd_config_el6_sorted
@@ -0,0 +1,31 @@ +# This file is being maintained by Puppet. +# DO NOT EDIT +# +# See https://man.openbsd.org/sshd_config for more info + +AcceptEnv LANG +AcceptEnv LANGUAGE +AcceptEnv LC_ADDRESS +AcceptEnv LC_ALL +AcceptEnv LC_COLLATE +AcceptEnv LC_CTYPE +AcceptEnv LC_IDENTIFICATION +AcceptEnv LC_MEASUREMENT +AcceptEnv LC_MESSAGES +AcceptEnv LC_MONETARY +AcceptEnv LC_NAME +AcceptEnv LC_NUMERIC +AcceptEnv LC_PAPER +AcceptEnv LC_TELEPHONE +AcceptEnv LC_TIME +AcceptEnv XMODIFIERS +ChallengeResponseAuthentication no +GSSAPIAuthentication yes +GSSAPICleanupCredentials yes +PasswordAuthentication no +Subsystem sftp /usr/libexec/openssh/sftp-server +SyslogFacility AUTHPRIV +UseDNS no +UsePAM yes +X11Forwarding yes +Protocol 2
diff --git a/spec/fixtures/sshd_config_el7 b/spec/fixtures/sshd_config_el7 new file mode 100644 index 0000000..12e4e15 --- /dev/null +++ b/spec/fixtures/sshd_config_el7
@@ -0,0 +1,140 @@ +# $OpenBSD: sshd_config,v 1.100 2016/08/15 12:32:04 naddy Exp $ + +# This is the sshd server system-wide configuration file. See +# sshd_config(5) for more information. + +# This sshd was compiled with PATH=/usr/local/bin:/usr/bin + +# The strategy used for options in the default sshd_config shipped with +# OpenSSH is to specify options with their default value where +# possible, but leave them commented. Uncommented options override the +# default value. + +# If you want to change the port on a SELinux system, you have to tell +# SELinux about this change. +# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER +# +#Port 22 +#AddressFamily any +#ListenAddress 0.0.0.0 +#ListenAddress :: + +HostKey /etc/ssh/ssh_host_rsa_key +#HostKey /etc/ssh/ssh_host_dsa_key +HostKey /etc/ssh/ssh_host_ecdsa_key +HostKey /etc/ssh/ssh_host_ed25519_key + +# Ciphers and keying +#RekeyLimit default none + +# Logging +#SyslogFacility AUTH +SyslogFacility AUTHPRIV +#LogLevel INFO + +# Authentication: + +#LoginGraceTime 2m +#PermitRootLogin yes +#StrictModes yes +#MaxAuthTries 6 +#MaxSessions 10 + +#PubkeyAuthentication yes + +# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2 +# but this is overridden so installations will only check .ssh/authorized_keys +AuthorizedKeysFile .ssh/authorized_keys + +#AuthorizedPrincipalsFile none + +#AuthorizedKeysCommand none +#AuthorizedKeysCommandUser nobody + +# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts +#HostbasedAuthentication no +# Change to yes if you don't trust ~/.ssh/known_hosts for +# HostbasedAuthentication +#IgnoreUserKnownHosts no +# Don't read the user's ~/.rhosts and ~/.shosts files +#IgnoreRhosts yes + +# To disable tunneled clear text passwords, change to no here! +#PasswordAuthentication yes +#PermitEmptyPasswords no +PasswordAuthentication no + +# Change to no to disable s/key passwords +#ChallengeResponseAuthentication yes +ChallengeResponseAuthentication no + +# Kerberos options +#KerberosAuthentication no +#KerberosOrLocalPasswd yes +#KerberosTicketCleanup yes +#KerberosGetAFSToken no +#KerberosUseKuserok yes + +# GSSAPI options +GSSAPIAuthentication yes +GSSAPICleanupCredentials no +#GSSAPIStrictAcceptorCheck yes +#GSSAPIKeyExchange no +#GSSAPIEnablek5users no + +# Set this to 'yes' to enable PAM authentication, account processing, +# and session processing. If this is enabled, PAM authentication will +# be allowed through the ChallengeResponseAuthentication and +# PasswordAuthentication. Depending on your PAM configuration, +# PAM authentication via ChallengeResponseAuthentication may bypass +# the setting of "PermitRootLogin without-password". +# If you just want the PAM account and session checks to run without +# PAM authentication, then enable this but set PasswordAuthentication +# and ChallengeResponseAuthentication to 'no'. +# WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several +# problems. +UsePAM yes + +#AllowAgentForwarding yes +#AllowTcpForwarding yes +#GatewayPorts no +X11Forwarding yes +#X11DisplayOffset 10 +#X11UseLocalhost yes +#PermitTTY yes +#PrintMotd yes +#PrintLastLog yes +#TCPKeepAlive yes +#UseLogin no +#UsePrivilegeSeparation sandbox +#PermitUserEnvironment no +#Compression delayed +#ClientAliveInterval 0 +#ClientAliveCountMax 3 +#ShowPatchLevel no +#UseDNS yes +UseDNS no +#PidFile /var/run/sshd.pid +#MaxStartups 10:30:100 +#PermitTunnel no +#ChrootDirectory none +#VersionAddendum none + +# no default banner path +#Banner none + +# Accept locale-related environment variables +AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES +AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT +AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE +AcceptEnv XMODIFIERS + +# override default of no subsystems +Subsystem sftp /usr/libexec/openssh/sftp-server + +# Example of overriding settings on a per-user basis +#Match User anoncvs +# X11Forwarding no +# AllowTcpForwarding no +# PermitTTY no +# ForceCommand cvs server
diff --git a/spec/fixtures/sshd_config_el7_sorted b/spec/fixtures/sshd_config_el7_sorted new file mode 100644 index 0000000..9e9977e --- /dev/null +++ b/spec/fixtures/sshd_config_el7_sorted
@@ -0,0 +1,34 @@ +# This file is being maintained by Puppet. +# DO NOT EDIT +# +# See https://man.openbsd.org/sshd_config for more info + +AcceptEnv LANG +AcceptEnv LC_CTYPE +AcceptEnv LC_NUMERIC +AcceptEnv LC_TIME +AcceptEnv LC_COLLATE +AcceptEnv LC_MONETARY +AcceptEnv LC_MESSAGES +AcceptEnv LC_PAPER +AcceptEnv LC_NAME +AcceptEnv LC_ADDRESS +AcceptEnv LC_TELEPHONE +AcceptEnv LC_MEASUREMENT +AcceptEnv LC_IDENTIFICATION +AcceptEnv LC_ALL +AcceptEnv LANGUAGE +AcceptEnv XMODIFIERS +AuthorizedKeysFile .ssh/authorized_keys +ChallengeResponseAuthentication no +GSSAPIAuthentication yes +GSSAPICleanupCredentials no +HostKey /etc/ssh/ssh_host_ecdsa_key +HostKey /etc/ssh/ssh_host_ed25519_key +HostKey /etc/ssh/ssh_host_rsa_key +PasswordAuthentication no +Subsystem sftp /usr/libexec/openssh/sftp-server +SyslogFacility AUTHPRIV +UseDNS no +UsePAM yes +X11Forwarding yes
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 74f727d..eeff368 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb
@@ -1,7 +1,11 @@ +# This RSpec.configure block is listed twice due to a bug with +# puppetlabs_spec_helper. https://tickets.puppetlabs.com/browse/PDK-916 +RSpec.configure do |config| + config.mock_with :rspec +end require 'puppetlabs_spec_helper/module_spec_helper' RSpec.configure do |config| - config.hiera_config = 'spec/fixtures/hiera/hiera.yaml' config.before :each do # Ensure that we don't accidentally cache facts and environment between # test cases. This requires each example group to explicitly load the @@ -10,7 +14,11 @@ Facter.clear Facter.clear_messages end - config.default_facts = { - :environment => 'rp_env', - } +end + +RSpec.configure do |c| + # Coverage generation + c.after(:suite) do + RSpec::Puppet::Coverage.report! + end end
diff --git a/spec/spec_helper_acceptance.rb b/spec/spec_helper_acceptance.rb new file mode 100644 index 0000000..c10f674 --- /dev/null +++ b/spec/spec_helper_acceptance.rb
@@ -0,0 +1,13 @@ +require 'beaker-rspec' +require 'beaker-puppet' +require 'beaker/module_install_helper' +require 'beaker/puppet_install_helper' + +run_puppet_install_helper +install_module_dependencies +install_module + +RSpec.configure do |c| + # Readable test descriptions + c.formatter = :documentation +end
diff --git a/spec/type_aliases/key_type_spec.rb b/spec/type_aliases/key_type_spec.rb new file mode 100644 index 0000000..fd1d677 --- /dev/null +++ b/spec/type_aliases/key_type_spec.rb
@@ -0,0 +1,48 @@ +# coding: utf-8 + +require 'spec_helper' + +describe 'Ssh::Key::Type' do + describe 'valid types' do + [ + 'ssh-dss', + 'ssh-ed25519', + 'ssh-rsa', + 'ecdsa-sha2-nistp256', + 'ecdsa-sha2-nistp384', + 'ecdsa-sha2-nistp521', + 'ed25519', + 'rsa', + 'dsa', + ].each do |value| + describe value.inspect do + it { is_expected.to allow_value(value) } + end + end + end + + describe 'invalid types' do + context 'with garbage inputs' do + [ + true, + false, + :keyword, + nil, + [nil], + [nil, nil], + { 'foo' => 'bar' }, + {}, + '', + 'ネット', + '55555', + '0x123', + 'ssh-dssss', + 'xrsa', + ].each do |value| + describe value.inspect do + it { is_expected.not_to allow_value(value) } + end + end + end + end +end
diff --git a/spec/type_aliases/permit_root_login_spec.rb b/spec/type_aliases/permit_root_login_spec.rb new file mode 100644 index 0000000..90aef2a --- /dev/null +++ b/spec/type_aliases/permit_root_login_spec.rb
@@ -0,0 +1,44 @@ +# coding: utf-8 + +require 'spec_helper' + +describe 'Ssh::Permit_root_login' do + describe 'valid types' do + [ + 'yes', + 'prohibit-password', + 'without-password', + 'forced-commands-only', + 'no', + ].each do |value| + describe value.inspect do + it { is_expected.to allow_value(value) } + end + end + end + + describe 'invalid types' do + context 'with garbage inputs' do + [ + true, + false, + :keyword, + nil, + [nil], + [nil, nil], + { 'foo' => 'bar' }, + {}, + '', + 'ネット', + '55555', + '0x123', + 'ssh-dssss', + 'xrsa', + ].each do |value| + describe value.inspect do + it { is_expected.not_to allow_value(value) } + end + end + end + end +end
diff --git a/spec/type_aliases/syslog_facility_spec.rb b/spec/type_aliases/syslog_facility_spec.rb new file mode 100644 index 0000000..f1ae6f6 --- /dev/null +++ b/spec/type_aliases/syslog_facility_spec.rb
@@ -0,0 +1,51 @@ +# coding: utf-8 + +require 'spec_helper' + +describe 'Ssh::Syslog_facility' do + describe 'valid types' do + [ + 'DAEMON', + 'USER', + 'AUTH', + 'LOCAL0', + 'LOCAL1', + 'LOCAL2', + 'LOCAL3', + 'LOCAL4', + 'LOCAL5', + 'LOCAL6', + 'LOCAL7', + 'AUTHPRIV', + ].each do |value| + describe value.inspect do + it { is_expected.to allow_value(value) } + end + end + end + + describe 'invalid types' do + context 'with garbage inputs' do + [ + true, + false, + :keyword, + nil, + ['yes', 'no'], + { 'foo' => 'bar' }, + {}, + '', + 'ネット', + '55555', + '0x123', + 'daemon', + 'local', + 'AUTH0', + ].each do |value| + describe value.inspect do + it { is_expected.not_to allow_value(value) } + end + end + end + end +end
diff --git a/spec/type_aliases/yes_no_spec.rb b/spec/type_aliases/yes_no_spec.rb new file mode 100644 index 0000000..b119c65 --- /dev/null +++ b/spec/type_aliases/yes_no_spec.rb
@@ -0,0 +1,40 @@ +# coding: utf-8 + +require 'spec_helper' + +describe 'Ssh::Yes_no' do + describe 'valid types' do + [ + 'yes', + 'no', + ].each do |value| + describe value.inspect do + it { is_expected.to allow_value(value) } + end + end + end + + describe 'invalid types' do + context 'with garbage inputs' do + [ + true, + false, + :keyword, + nil, + ['yes', 'no'], + { 'foo' => 'bar' }, + {}, + '', + 'ネット', + '55555', + '0x123', + 'yess', + 'nooo' + ].each do |value| + describe value.inspect do + it { is_expected.not_to allow_value(value) } + end + end + end + end +end
diff --git a/templates/ssh_config.erb b/templates/ssh_config.erb index 9cb65e3..d76efa5 100644 --- a/templates/ssh_config.erb +++ b/templates/ssh_config.erb
@@ -1,111 +1,274 @@ # This file is being maintained by Puppet. # DO NOT EDIT +# +# See https://man.openbsd.org/sshd_config for more info -# $OpenBSD: ssh_config,v 1.21 2005/12/06 22:38:27 reyk Exp $ - -# This is the ssh client system-wide configuration file. See -# ssh_config(5) for more information. This file provides defaults for -# users, and the values can be changed in per-user configuration files -# or on the command line. - -# Configuration data is parsed as follows: -# 1. command line options -# 2. user-specific file -# 3. system-wide file -# Any configuration value is only changed the first time it is set. -# Thus, host-specific definitions should be at the beginning of the -# configuration file, and defaults at the end. - -# Site-wide defaults for some commonly used options. For a comprehensive -# list of available options, their meanings and defaults, please see the -# ssh_config(5) man page. - -# Host * -# ForwardAgent no -# ForwardX11 no -# RhostsRSAAuthentication no -# RSAAuthentication yes - PasswordAuthentication yes - PubkeyAuthentication yes -# HostbasedAuthentication no -<% if @ssh_hostbasedauthentication -%> - HostbasedAuthentication <%= @ssh_hostbasedauthentication %> +Host <%= @host %> +<% if @add_keys_to_agent != nil -%> + AddKeysToAgent <%= @add_keys_to_agent %> <% end -%> -# BatchMode no -# CheckHostIP yes -# AddressFamily any -# ConnectTimeout 0 -# StrictHostKeyChecking ask -<% if @ssh_strict_host_key_checking -%> - StrictHostKeyChecking <%= @ssh_strict_host_key_checking %> +<% if @address_family != nil -%> + AddressFamily <%= @address_family %> <% end -%> -# IdentityFile ~/.ssh/identity - IdentityFile ~/.ssh/id_rsa - IdentityFile ~/.ssh/id_dsa -# Port 22 - Protocol 2 -# Cipher 3des -# Ciphers aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc -<% if @ssh_config_ciphers -%> - Ciphers <%= @ssh_config_ciphers.join(',') %> +<% if @batch_mode != nil -%> + BatchMode <%= @batch_mode %> <% end -%> -<% if @ssh_config_kexalgorithms -%> - KexAlgorithms <%= @ssh_config_kexalgorithms.join(',') %> +<% if @bind_address != nil -%> + BindAddress <%= @bind_address %> <% end -%> -# EscapeChar ~ -# Tunnel no -# TunnelDevice any:any -# PermitLocalCommand no -# HashKnownHosts no -<% if @ssh_config_hash_known_hosts_real != nil -%> - HashKnownHosts <%= @ssh_config_hash_known_hosts_real %> +<% if @bind_interface != nil -%> + BindInterface <%= @bind_interface %> <% end -%> -<% if @ssh_config_global_known_hosts_list_real -%> - GlobalKnownHostsFile <%= @ssh_config_global_known_hosts_list_real.join(' ') %> +<% if @canonical_domains != nil -%> + CanonicalDomains <%= @canonical_domains.join(' ') %> <% end -%> -<% if @ssh_config_proxy_command -%> - ProxyCommand <%= @ssh_config_proxy_command %> +<% if @canonicalize_fallback_local != nil -%> + CanonicalizeFallbackLocal <%= @canonicalize_fallback_local %> <% end -%> -Host * -# GSSAPIAuthentication yes - GSSAPIAuthentication <%= @ssh_gssapiauthentication %> -<% if @ssh_gssapidelegatecredentials != nil -%> -GSSAPIDelegateCredentials <%= @ssh_gssapidelegatecredentials %> +<% if @canonicalize_hostname != nil -%> + CanonicalizeHostname <%= @canonicalize_hostname %> <% end -%> -# If this option is set to yes then remote X11 clients will have full access -# to the original X11 display. As virtually no X11 client supports the untrusted -# mode correctly we set this to yes. -<% if @ssh_config_forward_x11_trusted_real != nil -%> - ForwardX11Trusted <%= @ssh_config_forward_x11_trusted_real %> +<% if @canonicalize_max_dots != nil -%> + CanonicalizeMaxDots <%= @canonicalize_max_dots %> <% end -%> -<% if @ssh_config_forward_agent != nil -%> - ForwardAgent <%= @ssh_config_forward_agent %> +<% if @canonicalize_permitted_cnames != nil -%> + CanonicalizePermittedCNAMEs <%= @canonicalize_permitted_cnames.join(',') %> <% end -%> -<% if @ssh_config_forward_x11 != nil -%> - ForwardX11 <%= @ssh_config_forward_x11 %> +<% if @ca_signature_algorithms != nil -%> + CASignatureAlgorithms <%= @ca_signature_algorithms.join(',') %> <% end -%> -<% if (@ssh_config_use_roaming_real == 'yes') or (@ssh_config_use_roaming_real == 'no') -%> - UseRoaming <%= @ssh_config_use_roaming_real %> +<% if @certificate_file != nil -%> +<% @certificate_file.each do |v| -%> + CertificateFile <%= v %> +<% end -%> <% end -%> -<% if @ssh_config_server_alive_interval != nil -%> - ServerAliveInterval <%= @ssh_config_server_alive_interval %> +<% if @challenge_response_authentication != nil -%> + ChallengeResponseAuthentication <%= @challenge_response_authentication %> <% end -%> -<% if @ssh_sendenv_real == true -%> -# Send locale-related environment variables - SendEnv LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES - SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT - SendEnv LC_IDENTIFICATION LC_ALL -<% if @ssh_config_sendenv_xmodifiers_real == true -%> - SendEnv XMODIFIERS +<% if @check_host_ip != nil -%> + CheckHostIP <%= @check_host_ip %> <% end -%> +<% if @ciphers != nil -%> + Ciphers <%= @ciphers.join(',') %> <% end -%> -<% if @ssh_config_macs -%> - MACs <%= @ssh_config_macs.join(',') %> +<% if @clear_all_forwardings != nil -%> + ClearAllForwardings <%= @clear_all_forwardings %> <% end -%> -<% if not @ssh_enable_ssh_keysign.nil? -%> -# EnableSSHKeysign no - EnableSSHKeysign <%= @ssh_enable_ssh_keysign %> +<% if @compression != nil -%> + Compression <%= @compression %> <% end -%> -<% if @ssh_config_user_known_hosts_file -%> - UserKnownHostsFile <%= @ssh_config_user_known_hosts_file.join(' ') %> +<% if @connection_attempts != nil -%> + ConnectionAttempts <%= @connection_attempts %> +<% end -%> +<% if @connect_timeout != nil -%> + ConnectTimeout <%= @connect_timeout %> +<% end -%> +<% if @control_master != nil -%> + ControlMaster <%= @control_master %> +<% end -%> +<% if @control_path != nil -%> + ControlPath <%= @control_path %> +<% end -%> +<% if @control_persist != nil -%> + ControlPersist <%= @control_persist %> +<% end -%> +<% if @dynamic_forward != nil -%> + DynamicForward <%= @dynamic_forward %> +<% end -%> +<% if @enable_ssh_keysign != nil -%> + EnableSSHKeysign <%= @enable_ssh_keysign %> +<% end -%> +<% if @escape_char != nil -%> + EscapeChar <%= @escape_char %> +<% end -%> +<% if @exit_on_forward_failure != nil -%> + ExitOnForwardFailure <%= @exit_on_forward_failure %> +<% end -%> +<% if @fingerprint_hash != nil -%> + FingerprintHash <%= @fingerprint_hash %> +<% end -%> +<% if @forward_agent != nil -%> + ForwardAgent <%= @forward_agent %> +<% end -%> +<% if @forward_x11 != nil -%> + ForwardX11 <%= @forward_x11 %> +<% end -%> +<% if @forward_x11_timeout != nil -%> + ForwardX11Timeout <%= @forward_x11_timeout %> +<% end -%> +<% if @forward_x11_trusted != nil -%> + ForwardX11Trusted <%= @forward_x11_trusted %> +<% end -%> +<% if @gateway_ports != nil -%> + GatewayPorts <%= @gateway_ports %> +<% end -%> +<% if @global_known_hosts_file != nil -%> + GlobalKnownHostsFile <%= @global_known_hosts_file.join(' ') %> +<% end -%> +<% if @gss_api_authentication != nil -%> + GSSAPIAuthentication <%= @gss_api_authentication %> +<% end -%> +<% if @gss_api_delegate_credentials != nil -%> + GSSAPIDelegateCredentials <%= @gss_api_delegate_credentials %> +<% end -%> +<% if @hash_known_hosts != nil -%> + HashKnownHosts <%= @hash_known_hosts %> +<% end -%> +<% if @hostbased_authentication != nil -%> + HostbasedAuthentication <%= @hostbased_authentication %> +<% end -%> +<% if @hostbased_key_types != nil -%> + HostbasedKeyTypes <%= @hostbased_key_types.join(',') %> +<% end -%> +<% if @host_key_algorithms != nil -%> + HostKeyAlgorithms <%= @host_key_algorithms.join(',') %> +<% end -%> +<% if @host_key_alias != nil -%> + HostKeyAlias <%= @host_key_alias %> +<% end -%> +<% if @host_name != nil -%> + HostNname <%= @host_name %> +<% end -%> +<% if @identities_only != nil -%> + IdentitiesOnly <%= @identities_only %> +<% end -%> +<% if @identity_agent != nil -%> + IdentityAgent <%= @identity_agent %> +<% end -%> +<% if @identity_file != nil -%> + IdentityFile <%= @identity_file %> +<% end -%> +<% if @ignore_unknown != nil -%> + IgnoreUnknown <%= @ignore_unknown %> +<% end -%> +<% if @include != nil -%> + Include <%= @include %> +<% end -%> +<% if @ip_qos != nil -%> + IPQoS <%= @ip_qos %> +<% end -%> +<% if @kbd_interactive_authentication != nil -%> + KbdInteractiveAuthentication <%= @kbd_interactive_authentication %> +<% end -%> +<% if @kbd_interactive_devices != nil -%> + KbdInteractiveDevices <%= @kbd_interactive_devices.join(',') %> +<% end -%> +<% if @kex_algorithms != nil -%> + KexAlgorithms <%= @kex_algorithms.join(',') %> +<% end -%> +<% if @local_command != nil -%> + LocalCommand <%= @local_command %> +<% end -%> +<% if @local_forward != nil -%> + LocalForward <%= @local_forward %> +<% end -%> +<% if @log_level != nil -%> + LogLevel <%= @log_level %> +<% end -%> +<% if @no_host_authentication_for_localhost != nil -%> + NoHostAuthenticationForLocalhost <%= @no_host_authentication_for_localhost %> +<% end -%> +<% if @number_of_password_prompts != nil -%> + NumberOfPasswordPrompts <%= @number_of_password_prompts %> +<% end -%> +<% if @password_authentication != nil -%> + PasswordAuthentication <%= @password_authentication %> +<% end -%> +<% if @permit_local_command != nil -%> + PermitLocalCommand <%= @permit_local_command %> +<% end -%> +<% if @pkcs11_provider != nil -%> + PKCS11Provider <%= @pkcs11_provider %> +<% end -%> +<% if @port != nil -%> + Port <%= @port %> +<% end -%> +<% if @preferred_authentications != nil -%> + PreferredAuthentications <%= @preferred_authentications.join(',') %> +<% end -%> +<% if @proxy_command != nil -%> + ProxyCommand <%= @proxy_command %> +<% end -%> +<% if @proxy_jump != nil -%> + ProxyJump <%= @proxy_jump.join(',') %> +<% end -%> +<% if @proxy_use_fdpass != nil -%> + ProxyUseFdpass <%= @proxy_use_fdpass %> +<% end -%> +<% if @pubkey_accepted_key_types != nil -%> + PubkeyAcceptedKeyTypes <%= @pubkey_accepted_key_types.join(',') %> +<% end -%> +<% if @pubkey_authentication != nil -%> + PubkeyAuthentication <%= @pubkey_authentication %> +<% end -%> +<% if @rekey_limit != nil -%> + RekeyLimit <%= @rekey_limit %> +<% end -%> +<% if @remote_command != nil -%> + RemoteCommand <%= @remote_command %> +<% end -%> +<% if @remote_forward != nil -%> + RemoteForward <%= @remote_forward %> +<% end -%> +<% if @request_tty != nil -%> + RequestTTY <%= @request_tty %> +<% end -%> +<% if @revoked_host_keys != nil -%> + RevokedHostKeys <%= @revoked_host_keys %> +<% end -%> +<% if @send_env != nil -%> +<% @send_env.each do |v| -%> + SendEnv <%= v %> +<% end -%> +<% end -%> +<% if @server_alive_count_max != nil -%> + ServerAliveCountMax <%= @server_alive_count_max %> +<% end -%> +<% if @server_alive_interval != nil -%> + ServerAliveIAerval <%= @server_alive_interval %> +<% end -%> +<% if @set_env != nil -%> + SetEnv <%= @set_env.join(' ') %> +<% end -%> +<% if @stream_local_bind_mask != nil -%> + StreamLocalBindMask <%= @stream_local_bind_mask %> +<% end -%> +<% if @stream_local_bind_unlink != nil -%> + StreamLocalBindUnlink <%= @stream_local_bind_unlink %> +<% end -%> +<% if @strict_host_key_checking != nil -%> + StrictHostKeyChecking <%= @strict_host_key_checking %> +<% end -%> +<% if @syslog_facility != nil -%> + SyslogFacility <%= @syslog_facility %> +<% end -%> +<% if @tcp_keep_alive != nil -%> + TCPKeepAlive <%= @tcp_keep_alive %> +<% end -%> +<% if @tunnel != nil -%> + Tunnel <%= @tunnel %> +<% end -%> +<% if @tunnel_device != nil -%> + TunnelDevice <%= @tunnel_device %> +<% end -%> +<% if @update_host_keys != nil -%> + UpdateHostKeys <%= @update_host_keys %> +<% end -%> +<% if @user != nil -%> + User <%= @user %> +<% end -%> +<% if @user_known_hosts_file != nil -%> + UserKnownHostsFile <%= @user_known_hosts_file.join(' ') %> +<% end -%> +<% if @verify_host_key_dns != nil -%> + VerifyHostKeyDNS <%= @verify_host_key_dns %> +<% end -%> +<% if @visual_host_key != nil -%> + VisualHostKey <%= @visual_host_key %> +<% end -%> +<% if @xauth_location != nil -%> + XAuthLocation <%= @xauth_location %> +<% end -%> +<% if @custom != nil -%> +<%= @custom %> <% end -%>
diff --git a/templates/sshd_config.erb b/templates/sshd_config.erb index 4e1bd70..5694c3e 100644 --- a/templates/sshd_config.erb +++ b/templates/sshd_config.erb
@@ -1,288 +1,297 @@ # This file is being maintained by Puppet. # DO NOT EDIT +# +# See https://man.openbsd.org/sshd_config for more info -# $OpenBSD: sshd_config,v 1.73 2005/12/06 22:38:28 reyk Exp $ - -# This is the sshd server system-wide configuration file. See -# sshd_config(5) for more information. - -# This sshd was compiled with PATH=/usr/local/bin:/bin:/usr/bin - -# The strategy used for options in the default sshd_config shipped with -# OpenSSH is to specify options with their default value where -# possible, but leave them commented. Uncommented options change a -# default value. - -#Port 22 -<% @sshd_config_port_array.each do |p| -%> -<%= "Port #{p}" %> -<% end -%> -#Protocol 2,1 -Protocol 2 -<% if @sshd_addressfamily_real != nil -%> -#AddressFamily any -AddressFamily <%= @sshd_addressfamily_real %> -<% end -%> -<% if @sshd_listen_address.class == Array -%> -<% @sshd_listen_address.each do |val| -%> -ListenAddress <%= val %> -<% end -%> -<% elsif @sshd_listen_address.class == String -%> -ListenAddress <%= @sshd_listen_address %> -<% end -%> - -# HostKey for protocol version 1 -#HostKey /etc/ssh/ssh_host_key -# HostKeys for protocol version 2 -#HostKey /etc/ssh/ssh_host_rsa_key -#HostKey /etc/ssh/ssh_host_dsa_key -<% @sshd_config_hostkey_real.each do |hostkey| -%> -HostKey <%= hostkey %> -<% end -%> - -# Lifetime and size of ephemeral version 1 server key -#KeyRegenerationInterval 1h -#ServerKeyBits 1024 -<% if @sshd_config_serverkeybits_real != nil -%> -ServerKeyBits <%= @sshd_config_serverkeybits_real %> -<% end -%> -# Logging -# obsoletes QuietMode and FascistLogging -#SyslogFacility AUTH -SyslogFacility <%= @sshd_config_syslog_facility %> -#LogLevel INFO -LogLevel <%= @sshd_config_loglevel %> - -# Authentication: - -#LoginGraceTime 120 -LoginGraceTime <%= @sshd_config_login_grace_time %> -#PermitRootLogin yes -PermitRootLogin <%= @permit_root_login %> -#StrictModes yes -<% if @sshd_config_strictmodes -%> -StrictModes <%= @sshd_config_strictmodes %> -<% end -%> -#MaxAuthTries 6 -<% if @sshd_config_maxauthtries %> -MaxAuthTries <%= @sshd_config_maxauthtries %> -<% end -%> - -#RSAAuthentication yes -<% if @sshd_pubkeyacceptedkeytypes -%> -PubkeyAcceptedKeyTypes <%= @sshd_pubkeyacceptedkeytypes.join(',') %> -<% end -%> -#PubkeyAuthentication yes -PubkeyAuthentication <%= @sshd_pubkeyauthentication %> -#AuthorizedKeysFile .ssh/authorized_keys -<% if @sshd_config_authkey_location -%> -AuthorizedKeysFile <%= @sshd_config_authkey_location %> -<% end -%> -<% if @sshd_authorized_keys_command -%> -AuthorizedKeysCommand <%= @sshd_authorized_keys_command %> -<% end -%> -<% if @sshd_authorized_keys_command_user -%> -AuthorizedKeysCommandUser <%= @sshd_authorized_keys_command_user %> -<% end -%> - -# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts -#RhostsRSAAuthentication no -# similar for protocol version 2 -#HostbasedAuthentication no -HostbasedAuthentication <%= @sshd_hostbasedauthentication %> -# Change to yes if you don't trust ~/.ssh/known_hosts for -# RhostsRSAAuthentication and HostbasedAuthentication -#IgnoreUserKnownHosts no -IgnoreUserKnownHosts <%= @sshd_ignoreuserknownhosts %> -# Don't read the user's ~/.rhosts and ~/.shosts files -#IgnoreRhosts yes -IgnoreRhosts <%= @sshd_ignorerhosts %> - -<%- if @sshd_config_authenticationmethods -%> -AuthenticationMethods <%= @sshd_config_authenticationmethods.join(',') %> -<%- end -%> -# To disable tunneled clear text passwords, change to no here! -#PasswordAuthentication yes -PasswordAuthentication <%= @sshd_password_authentication %> -<% if @sshd_pamauthenticationviakbdint_real != nil -%> -# Use PAM via keyboard interactive method for authentication. -# Depending on the setup of pam.conf(4) this may allow tunneled clear text -# passwords even when PasswordAuthentication is set to no. This is dependent -# on what the individual modules request and is out of the control of sshd -# or the protocol. -PAMAuthenticationViaKBDInt <%= @sshd_pamauthenticationviakbdint_real %> -<% end -%> -#PermitEmptyPasswords no -<% if @sshd_config_permitemptypasswords != nil -%> -PermitEmptyPasswords <%= @sshd_config_permitemptypasswords %> -<% end -%> - -# Change to no to disable s/key passwords -#ChallengeResponseAuthentication yes -ChallengeResponseAuthentication <%= @sshd_config_challenge_resp_auth %> - -# Kerberos options -<% if @sshd_kerberos_authentication != nil -%> -#KerberosAuthentication no -KerberosAuthentication <%= @sshd_kerberos_authentication %> -<% end -%> -#KerberosOrLocalPasswd yes -#KerberosTicketCleanup yes -#KerberosGetAFSToken no - -# GSSAPI options -#GSSAPIAuthentication no -GSSAPIAuthentication <%= @sshd_gssapiauthentication %> -<% if @sshd_gssapikeyexchange_real != nil -%> -GSSAPIKeyExchange <%= @sshd_gssapikeyexchange_real %> -<% end -%> -<% if @sshd_gssapicleanupcredentials_real != nil -%> -#GSSAPICleanupCredentials yes -GSSAPICleanupCredentials <%= @sshd_gssapicleanupcredentials_real %> -<% end -%> - -<% if @sshd_use_pam_real != nil -%> -# Set this to 'yes' to enable PAM authentication, account processing, -# and session processing. If this is enabled, PAM authentication will -# be allowed through the ChallengeResponseAuthentication mechanism. -# Depending on your PAM configuration, this may bypass the setting of -# PasswordAuthentication, PermitEmptyPasswords, and -# "PermitRootLogin without-password". If you just want the PAM account and -# session checks to run without PAM authentication, then enable this but set -# ChallengeResponseAuthentication=no -#UsePAM no -UsePAM <%= @sshd_use_pam_real %> -<% end -%> - -<% if @sshd_acceptenv_real == true -%> -# Accept locale-related environment variables -AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -AcceptEnv LC_IDENTIFICATION LC_ALL -<% end -%> -#AllowTcpForwarding yes -AllowTcpForwarding <%= @sshd_allow_tcp_forwarding %> -#GatewayPorts no -#X11Forwarding no -X11Forwarding <%= @sshd_x11_forwarding %> -#X11DisplayOffset 10 -#X11UseLocalhost yes -X11UseLocalhost <%= @sshd_x11_use_localhost %> -#PrintMotd yes -PrintMotd <%= @sshd_config_print_motd %> -#PrintLastLog yes -<% if @sshd_config_print_last_log != nil -%> -PrintLastLog <%= @sshd_config_print_last_log %> -<% end -%> -#TCPKeepAlive yes -<% if @sshd_config_tcp_keepalive_real != nil -%> -TCPKeepAlive <%= @sshd_config_tcp_keepalive_real %> -<% end -%> -#UseLogin no -#UsePrivilegeSeparation yes -<% if @sshd_config_use_privilege_separation != nil -%> -UsePrivilegeSeparation <%= @sshd_config_use_privilege_separation %> -<% end -%> -#PermitUserEnvironment no -<% if @sshd_config_permituserenvironment != nil -%> -PermitUserEnvironment <%= @sshd_config_permituserenvironment %> -<% end -%> -#Compression delayed -<% if @sshd_config_compression != nil -%> -Compression <%= @sshd_config_compression %> -<% end -%> -#ClientAliveInterval 0 -ClientAliveInterval <%= @sshd_client_alive_interval %> -ClientAliveCountMax <%= @sshd_client_alive_count_max %> -#ShowPatchLevel no -<% if @sshd_config_use_dns_real != nil -%> -#UseDNS yes -UseDNS <%= @sshd_config_use_dns_real %> -<% end -%> -#PidFile /var/run/sshd.pid -<% if @sshd_config_maxstartups -%> -MaxStartups <%= @sshd_config_maxstartups %> -<% else -%> -#MaxStartups 10:30:100 -<% end -%> -<% if @sshd_config_maxsessions_integer != nil -%> -MaxSessions <%= @sshd_config_maxsessions_integer %> -<% else -%> -#MaxSessions 10 -<% end -%> - -#PermitTunnel no -<% if @sshd_config_permittunnel_real != nil -%> -PermitTunnel <%= @sshd_config_permittunnel_real %> -<% end -%> -<% if @sshd_config_chrootdirectory -%> -ChrootDirectory <%= @sshd_config_chrootdirectory %> -<% else -%> -#ChrootDirectory none -<% end -%> -<% if @sshd_config_forcecommand -%> -ForceCommand <%= @sshd_config_forcecommand %> -<% end -%> -<% if @sshd_config_allowagentforwarding != nil -%> -#AllowAgentForwarding yes -AllowAgentForwarding <%= @sshd_config_allowagentforwarding %> -<% end -%> - -# no default banner path -#Banner none -Banner <%= @sshd_config_banner %> - -<% if @sshd_config_xauth_location_real -%> -#XAuthLocation /usr/bin/xauth -XAuthLocation <%= @sshd_config_xauth_location_real %> - -<% end -%> -# override default of no subsystems -Subsystem sftp <%= @sshd_config_subsystem_sftp_real %> - -<% if @sshd_config_ciphers -%> -Ciphers <%= @sshd_config_ciphers.join(',') %> -<% end -%> -<% if @sshd_config_kexalgorithms -%> -KexAlgorithms <%= @sshd_config_kexalgorithms.join(',') %> -<% end -%> -<% if @sshd_config_macs -%> -MACs <%= @sshd_config_macs.join(',') %> -<% end -%> -<% if @sshd_config_denyusers_real != [] -%> -DenyUsers <%= @sshd_config_denyusers_real.join(' ') %> -<% end -%> -<% if @sshd_config_denygroups_real != [] -%> -DenyGroups <%= @sshd_config_denygroups_real.join(' ') %> -<% end -%> -<% if @sshd_config_allowusers_real != [] -%> -AllowUsers <%= @sshd_config_allowusers_real.join(' ') %> -<% end -%> -<% if @sshd_config_allowgroups_real != [] -%> -AllowGroups <%= @sshd_config_allowgroups_real.join(' ') %> -<% end -%> -<% if @sshd_config_key_revocation_list_real -%> -RevokedKeys <%= @sshd_config_key_revocation_list_real %> -<% end -%> -<% if @sshd_config_hostcertificate_real.class == Array -%> -<% @sshd_config_hostcertificate_real.each do |cert| -%> -HostCertificate <%= cert %> +<% if @accept_env != nil -%> +<% @accept_env.each do |v| -%> +AcceptEnv <%= v %> <% end -%> -<% elsif @sshd_config_hostcertificate_real.class == String -%> -HostCertificate <%= @sshd_config_hostcertificate_real %> <% end -%> -<% if @sshd_config_trustedusercakeys_real -%> -TrustedUserCAKeys <%= @sshd_config_trustedusercakeys_real %> +<% if @address_family != nil -%> +AddressFamily <%= @address_family %> <% end -%> -<% if @sshd_config_authorized_principals_file_real -%> -AuthorizedPrincipalsFile <%= @sshd_config_authorized_principals_file_real %> +<% if @allow_agent_forwarding != nil -%> +AllowAgentForwarding <%= @allow_agent_forwarding %> <% end -%> -<% if @sshd_config_match -%> - -<% @sshd_config_match.sort.each do |key, hash| -%> -Match <%= key %> -<% hash.sort.each do |values| -%> - <%= values %> -<% end -%> +<% if @allow_groups != nil -%> +<% if @allow_groups.class == Array -%> +AllowGroups <%= @allow_groups.join(' ') %> +<% elsif @allow_groups.class == String -%> +AllowGroups <%= @allow_groups %> <% end -%> <% end -%> +<% if @allow_stream_local_forwarding != nil -%> +AllowStreamLocalForwarding <%= @allow_stream_local_forwarding %> +<% end -%> +<% if @allow_tcp_forwarding != nil -%> +AllowTcpForwarding <%= @allow_tcp_forwarding %> +<% end -%> +<% if @allow_users != nil -%> +<% if @allow_users.class == Array -%> +AllowUsers <%= @allow_users.join(' ') %> +<% elsif @allow_users.class == String -%> +AllowUsers <%= @allow_users %> +<% end -%> +<% end -%> +<% if @authentication_methods != nil -%> +AuthenticationMethods <%= @authentication_methods.join(',') %> +<% end -%> +<% if @authorized_keys_command != nil -%> +AuthorizedKeysCommand <%= @authorized_keys_command %> +<% end -%> +<% if @authorized_keys_command_user != nil -%> +AuthorizedKeysCommandUser <%= @authorized_keys_command_user %> +<% end -%> +<% if @authorized_keys_file != nil -%> +<% if @authorized_keys_file.class == Array -%> +AuthorizedKeysFile <%= @authorized_keys_file.join(' ') %> +<% elsif @authorized_keys_file.class == String -%> +AuthorizedKeysFile <%= @authorized_keys_file %> +<% end -%> +<% end -%> +<% if @authorized_principals_command != nil -%> +AuthorizedPrincipalsCommand <%= @authorized_principals_command %> +<% end -%> +<% if @authorized_principals_command_user != nil -%> +AuthorizedPrincipalsCommandUser <%= @authorized_principals_command_user %> +<% end -%> +<% if @authorized_principals_file != nil -%> +AuthorizedPrincipalsFile <%= @authorized_principals_file %> +<% end -%> +<% if @banner != nil -%> +Banner <%= @banner %> +<% end -%> +<% if @ca_signature_algorithms != nil -%> +CASignatureAlgorithms <%= @ca_signature_algorithms.join(',') %> +<% end -%> +<% if @challenge_response_authentication != nil -%> +ChallengeResponseAuthentication <%= @challenge_response_authentication %> +<% end -%> +<% if @chroot_directory != nil -%> +ChrootDirectory <%= @chroot_directory %> +<% end -%> +<% if @ciphers != nil -%> +Ciphers <%= @ciphers.join(',') %> +<% end -%> +<% if @client_alive_count_max != nil -%> +ClientAliveCountMax <%= @client_alive_count_max %> +<% end -%> +<% if @client_alive_interval != nil -%> +ClientAliveInterval <%= @client_alive_interval %> +<% end -%> +<% if @compression != nil -%> +Compression <%= @compression %> +<% end -%> +<% if @deny_groups != nil -%> +<% if @deny_groups.class == Array -%> +DenyGroups <%= @deny_groups.join(' ') %> +<% elsif @deny_groups.class == String -%> +DenyGroups <%= @deny_groups %> +<% end -%> +<% end -%> +<% if @deny_users != nil -%> +<% if @deny_users.class == Array -%> +DenyUsers <%= @deny_users.join(' ') %> +<% elsif @deny_users.class == String -%> +DenyUsers <%= @deny_users %> +<% end -%> +<% end -%> +<% if @disable_forwarding != nil -%> +DisableForwarding <%= @disable_forwarding %> +<% end -%> +<% if @expose_auth_info != nil -%> +ExposeAuthInfo <%= @expose_auth_info %> +<% end -%> +<% if @fingerprint_hash != nil -%> +FingerprintHash <%= @fingerprint_hash %> +<% end -%> +<% if @force_command != nil -%> +ForceCommand <%= @force_command %> +<% end -%> +<% if @gateway_ports != nil -%> +GatewayPorts <%= @gateway_ports %> +<% end -%> +<% if @gss_api_authentication != nil -%> +GSSAPIAuthentication <%= @gss_api_authentication %> +<% end -%> +<% if @gss_api_cleanup_credentials != nil -%> +GSSAPICleanupCredentials <%= @gss_api_cleanup_credentials %> +<% end -%> +<% if @gss_api_strict_acceptor_check != nil -%> +GSSAPIStrictAcceptorCheck <%= @gss_api_strict_acceptor_check %> +<% end -%> +<% if @hostbased_accepted_key_types != nil -%> +HostbasedAcceptedKeyTypes <%= @hostbased_accepted_key_types.join(',') %> +<% end -%> +<% if @hostbased_authentication != nil -%> +HostbasedAuthentication <%= @hostbased_authentication %> +<% end -%> +<% if @hostbased_uses_name_from_packet_only != nil -%> +HostbasedUsesNameFromPacketOnly <%= @hostbased_uses_name_from_packet_only %> +<% end -%> +<% if @host_certificate != nil -%> +HostCertificate <%= @host_certificate %> +<% end -%> +<% if @host_key != nil -%> +<% @host_key.each do |v| -%> +HostKey <%= v %> +<% end -%> +<% end -%> +<% if @host_key_agent != nil -%> +HostKeyAgent <%= @host_key_agent %> +<% end -%> +<% if @host_key_algorithms != nil -%> +HostKeyAlgorithms <%= @host_key_algorithms.join(',') %> +<% end -%> +<% if @ignore_rhosts != nil -%> +IgnoreRhosts <%= @ignore_rhosts %> +<% end -%> +<% if @ignore_user_known_hosts != nil -%> +IgnoreUserKnownHosts <%= @ignore_user_known_hosts %> +<% end -%> +<% if @ip_qos != nil -%> +IPQoS <%= @ip_qos %> +<% end -%> +<% if @kbd_interactive_authentication != nil -%> +KbdInteractiveAuthentication <%= @kbd_interactive_authentication %> +<% end -%> +<% if @kerberos_authentication != nil -%> +KerberosAuthentication <%= @kerberos_authentication %> +<% end -%> +<% if @kerberos_get_afs_token != nil -%> +KerberosGetAFSToken <%= @kerberos_get_afs_token %> +<% end -%> +<% if @kerberos_or_local_passwd != nil -%> +KerberosOrLocalPasswd <%= @kerberos_or_local_passwd %> +<% end -%> +<% if @kerberos_ticket_cleanup != nil -%> +KerberosTicketCleanup <%= @kerberos_ticket_cleanup %> +<% end -%> +<% if @kex_algorithms != nil -%> +KexAlgorithms <%= @kex_algorithms.join(',') %> +<% end -%> +<% if @listen_address != nil -%> +<% @listen_address.each do |v| -%> +ListenAddress <%= v %> +<% end -%> +<% end -%> +<% if @login_grace_time != nil -%> +LoginGraceTime <%= @login_grace_time %> +<% end -%> +<% if @log_level != nil -%> +LogLevel <%= @log_level %> +<% end -%> +<% if @macs != nil -%> +MACs <%= @macs.join(',') %> +<% end -%> +<% if @max_auth_tries != nil -%> +MaxAuthTries <%= @max_auth_tries %> +<% end -%> +<% if @max_sessions != nil -%> +MaxSessions <%= @max_sessions %> +<% end -%> +<% if @max_startups != nil -%> +MaxStartups <%= @max_startups %> +<% end -%> +<% if @password_authentication != nil -%> +PasswordAuthentication <%= @password_authentication %> +<% end -%> +<% if @permit_empty_passwords != nil -%> +PermitEmptyPasswords <%= @permit_empty_passwords %> +<% end -%> +<% if @permit_listen != nil -%> +<% if @permit_listen.class == Array -%> +PermitListen <%= @permit_listen.join(' ') %> +<% elsif @permit_listen.class == String -%> +PermitListen <%= @permit_listen %> +<% end -%> +<% end -%> +<% if @permit_root_login != nil -%> +<% end -%> +<% if @permit_tty != nil -%> +PermitTTY <%= @permit_tty %> +<% end -%> +<% if @permit_tunnel != nil -%> +PermitTunnel <%= @permit_tunnel %> +<% end -%> +<% if @permit_user_environment != nil -%> +PermitUserEnvironment <%= @permit_user_environment %> +<% end -%> +<% if @permit_user_rc != nil -%> +PermitUserRC <%= @permit_user_rc %> +<% end -%> +<% if @pid_file != nil -%> +PidFile <%= @pid_file %> +<% end -%> +<% if @port != nil -%> +<% end -%> +<% if @print_last_log != nil -%> +PrintLastLog <%= @print_last_log %> +<% end -%> +<% if @print_motd != nil -%> +PrintMotd <%= @print_motd %> +<% end -%> +<% if @pubkey_accepted_key_types != nil -%> +PubkeyAcceptedKeyTypes <%= @pubkey_accepted_key_types.join(',') %> +<% end -%> +<% if @pubkey_authentication != nil -%> +PubkeyAuthentication <%= @pubkey_authentication %> +<% end -%> +<% if @rekey_limit != nil -%> +RekeyLimit <%= @rekey_limit %> +<% end -%> +<% if @revoked_keys != nil -%> +RevokedKeys <%= @revoked_keys %> +<% end -%> +<% if @rdomain != nil -%> +RDomain <%= @rdomain %> +<% end -%> +<% if @set_env != nil -%> +SetEnv <%= @set_env %> +<% end -%> +<% if @stream_local_bind_mask != nil -%> +StreamLocalBindMask <%= @stream_local_bind_mask %> +<% end -%> +<% if @stream_local_bind_unlink != nil -%> +StreamLocalBindUnlink <%= @stream_local_bind_unlink %> +<% end -%> +<% if @strict_modes != nil -%> +StrictModes <%= @strict_modes %> +<% end -%> +<% if @subsystem != nil -%> +Subsystem <%= @subsystem %> +<% end -%> +<% if @syslog_facility != nil -%> +SyslogFacility <%= @syslog_facility %> +<% end -%> +<% if @tcp_keep_alive != nil -%> +TCPKeepAlive <%= @tcp_keep_alive %> +<% end -%> +<% if @trusted_user_ca_keys != nil -%> +TrustedUserCAKeys <%= @trusted_user_ca_keys %> +<% end -%> +<% if @use_dns != nil -%> +UseDNS <%= @use_dns %> +<% end -%> +<% if @use_pam != nil -%> +UsePAM <%= @use_pam %> +<% end -%> +<% if @version_addendum != nil -%> +VersionAddendum <%= @version_addendum %> +<% end -%> +<% if @x11_display_offset != nil -%> +X11DisplayOffset <%= @x11_display_offset %> +<% end -%> +<% if @x11_forwarding != nil -%> +X11Forwarding <%= @x11_forwarding %> +<% end -%> +<% if @x11_use_localhost != nil -%> +X11UseLocalhost <%= @x11_use_localhost %> +<% end -%> +<% if @xauth_location != nil -%> +XAuthLocation <%= @xauth_location %> +<% end -%> +<% if @custom != nil -%> +<%= @custom %> +<% end -%>
diff --git a/tests/init.pp b/tests/init.pp index ea1c831..13a4638 100644 --- a/tests/init.pp +++ b/tests/init.pp
@@ -1 +1 @@ -include ::ssh +include ssh
diff --git a/tests/provision.sh b/tests/provision.sh new file mode 100644 index 0000000..7f9a539 --- /dev/null +++ b/tests/provision.sh
@@ -0,0 +1,77 @@ +#!/bin/bash + +if [ $# -ne 1 ]; then + echo "Must pass one argument of either 'debian' or 'el'" + exit 255 +fi + +case "$1" in + 'el') + function rpm_install() { + package=$(echo $1 | awk -F "/" '{print $NF}') + wget --quiet $1 + yum install -y ./$package + rm -f $package + } + + release=$(awk -F \: '{print $5}' /etc/system-release-cpe) + + rpm --import http://download-ib01.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-${release} + rpm --import http://yum.puppetlabs.com/RPM-GPG-KEY-puppet + rpm --import http://vault.centos.org/RPM-GPG-KEY-CentOS-${release} + + yum install -y wget + + rpm_install http://yum.puppetlabs.com/puppet5/puppet5-release-el-${release}.noarch.rpm + yum -y install puppet-agent + ;; + + 'debian') + function deb_install() { + package=$(echo $1 | awk -F "/" '{print $NF}') + wget --quiet $1 + dpkg -i ./$package + rm -f $package + } + + export DEBIAN_FRONTEND=noninteractive + + if [ -f /etc/lsb-release ]; then + # ubuntu + . /etc/lsb-release + CODENAME=$DISTRIB_CODENAME + else + # debian + CODENAME=$(grep ^VERSION= /etc/os-release | awk -F \( '{print $2}' | awk -F \) '{print $1}') + apt-get -y install apt-transport-https + apt-get update + fi + + # Debian 9 (stretch) complains about the dirmngr package missing. + if [ "${CODENAME}" == 'stretch' ]; then + apt-get -y install dirmngr + fi + + apt-key adv --fetch-keys http://apt.puppetlabs.com/DEB-GPG-KEY-puppet + apt-get -y install wget + + deb_install http://apt.puppetlabs.com/puppet5-release-${CODENAME}.deb + apt-get update + apt-get -y install puppet-agent + ;; + + *) + echo "argument is <${1}> and must be either 'debian' or 'el'." + exit 1 + ;; +esac + +# ensure puppet is in the path by symlinking to /usr/bin +ln -s /opt/puppetlabs/puppet/bin/puppet /usr/bin/puppet + +# use local ssh module +puppet resource file /etc/puppetlabs/code/environments/production/modules/ssh ensure=link target=/vagrant + +# setup module dependencies +puppet module install puppetlabs/stdlib --version 5.2.0 +
diff --git a/tests/vagrant_test_all.sh b/tests/vagrant_test_all.sh new file mode 100755 index 0000000..ba96d21 --- /dev/null +++ b/tests/vagrant_test_all.sh
@@ -0,0 +1,16 @@ +#!/bin/bash -e + +systems=$(vagrant status |grep virtualbox | awk '{print $1}') +echo -e "\nsystems to test:" +echo -e "================" +echo -e "\n${systems}" + +for i in $systems +do + echo -e "\n\n\n========= Running: vagrant up ${i}" + vagrant up $i + echo -e "\n\n\n========= Testing ssh to ${i}" + vagrant ssh $i -c "exit" + echo -e "\n\n\n========= Running: vagrant destroy -f ${i}" + vagrant destroy -f $i +done
diff --git a/types/key/type.pp b/types/key/type.pp new file mode 100644 index 0000000..d8f0277 --- /dev/null +++ b/types/key/type.pp
@@ -0,0 +1,12 @@ +# From https://github.com/puppetlabs/puppetlabs-sshkeys_core/blob/master/lib/puppet/type/sshkey.rb v1.0.2 +type Ssh::Key::Type = Enum[ + 'ssh-dss', + 'ssh-ed25519', + 'ssh-rsa', + 'ecdsa-sha2-nistp256', + 'ecdsa-sha2-nistp384', + 'ecdsa-sha2-nistp521', + 'ed25519', + 'rsa', + 'dsa', +]
diff --git a/types/log_level.pp b/types/log_level.pp new file mode 100644 index 0000000..9513e50 --- /dev/null +++ b/types/log_level.pp
@@ -0,0 +1,11 @@ +type Ssh::Log_level = Enum[ + 'QUIET', + 'FATAL', + 'ERROR', + 'INFO', + 'VERBOSE', + 'DEBUG', + 'DEBUG1', + 'DEBUG2', + 'DEBUG3', +]
diff --git a/types/permit_root_login.pp b/types/permit_root_login.pp new file mode 100644 index 0000000..921eaf6 --- /dev/null +++ b/types/permit_root_login.pp
@@ -0,0 +1,8 @@ +# 'without-password' is a deprecated alias for 'prohibit-password' +type Ssh::Permit_root_login = Enum[ + 'yes', + 'prohibit-password', + 'without-password', + 'forced-commands-only', + 'no', +]
diff --git a/types/syslog_facility.pp b/types/syslog_facility.pp new file mode 100644 index 0000000..1d5eca1 --- /dev/null +++ b/types/syslog_facility.pp
@@ -0,0 +1,14 @@ +type Ssh::Syslog_facility = Enum[ + 'DAEMON', + 'USER', + 'AUTH', + 'LOCAL0', + 'LOCAL1', + 'LOCAL2', + 'LOCAL3', + 'LOCAL4', + 'LOCAL5', + 'LOCAL6', + 'LOCAL7', + 'AUTHPRIV', # this is not documented, but it is what EL 7 uses +]
diff --git a/types/yes_no.pp b/types/yes_no.pp new file mode 100644 index 0000000..0d9789f --- /dev/null +++ b/types/yes_no.pp
@@ -0,0 +1 @@ +type Ssh::Yes_no = Enum['yes', 'no']