diff --git a/.rubocop.yml b/.rubocop.yml index 33c33fa5..3479f61a 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,534 +1,539 @@ --- require: - rubocop-performance - rubocop-rspec AllCops: DisplayCopNames: true TargetRubyVersion: '2.4' Include: - "**/*.rb" Exclude: - bin/* - ".vendor/**/*" - "**/Gemfile" - "**/Rakefile" - pkg/**/* - spec/fixtures/**/* - vendor/**/* - "**/Puppetfile" - "**/Vagrantfile" - "**/Guardfile" +inherit_from: ".rubocop_todo.yml" Layout/LineLength: Description: People have wide screens, use them. Max: 200 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 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 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/TrailingCommaInArrayLiteral: Description: Prefer always trailing comma on multiline literals. This makes diffs, and re-ordering nicer. EnforcedStyleForMultiline: comma Style/SymbolArray: Description: Using percent style obscures symbolic intent of array's contents. EnforcedStyle: brackets RSpec/MessageSpies: EnforcedStyle: receive Style/Documentation: Exclude: - lib/puppet/parser/functions/**/* - spec/**/* Style/WordArray: EnforcedStyle: brackets Performance/AncestorsInclude: Enabled: true Performance/BigDecimalWithNumericArgument: Enabled: true Performance/BlockGivenWithExplicitBlock: Enabled: true Performance/Caller: Enabled: true Performance/CaseWhenSplat: Enabled: true Performance/Casecmp: Enabled: true Performance/CollectionLiteralInLoop: + Exclude: + - spec/**/* Enabled: true Performance/CompareWithBlock: Enabled: true Performance/ConstantRegexp: Enabled: true Performance/Count: Enabled: true Performance/Detect: Enabled: true Performance/DoubleStartEndWith: Enabled: true Performance/EndWith: Enabled: true Performance/FixedSize: Enabled: true Performance/FlatMap: Enabled: true Performance/MethodObjectAsBlock: Enabled: true Performance/RangeInclude: Enabled: true Performance/RedundantBlockCall: Enabled: true Performance/RedundantMatch: Enabled: true Performance/RedundantMerge: Enabled: true Performance/RedundantSortBlock: Enabled: true Performance/RedundantStringChars: Enabled: true Performance/RegexpMatch: Enabled: true Performance/ReverseEach: Enabled: true Performance/ReverseFirst: Enabled: true Performance/Size: Enabled: true Performance/SortReverse: Enabled: true Performance/Squeeze: Enabled: true Performance/StartWith: Enabled: true Performance/StringInclude: Enabled: true Performance/StringReplacement: Enabled: true Performance/Sum: Enabled: true Performance/TimesMap: Enabled: true Style/CollectionMethods: Enabled: true Style/MethodCalledOnDoEndBlock: Enabled: true Style/StringMethods: Enabled: true Bundler/InsecureProtocolSource: Enabled: false Gemspec/DuplicatedAssignment: Enabled: false Gemspec/OrderedDependencies: Enabled: false Gemspec/RequiredRubyVersion: Enabled: false Gemspec/RubyVersionGlobalsUsage: Enabled: false Layout/ArgumentAlignment: Enabled: false Layout/BeginEndAlignment: Enabled: false Layout/ClosingHeredocIndentation: Enabled: false Layout/EmptyComment: Enabled: false Layout/EmptyLineAfterGuardClause: Enabled: false Layout/EmptyLinesAroundArguments: Enabled: false Layout/EmptyLinesAroundAttributeAccessor: Enabled: false Layout/EndOfLine: Enabled: false Layout/FirstArgumentIndentation: Enabled: false Layout/HashAlignment: Enabled: false Layout/HeredocIndentation: Enabled: false Layout/LeadingEmptyLines: Enabled: false Layout/SpaceAroundMethodCallOperator: Enabled: false Layout/SpaceInsideArrayLiteralBrackets: Enabled: false Layout/SpaceInsideReferenceBrackets: Enabled: false Lint/BigDecimalNew: Enabled: false Lint/BooleanSymbol: Enabled: false Lint/ConstantDefinitionInBlock: Enabled: false Lint/DeprecatedOpenSSLConstant: Enabled: false Lint/DisjunctiveAssignmentInConstructor: Enabled: false Lint/DuplicateBranch: Enabled: false Lint/DuplicateElsifCondition: Enabled: false Lint/DuplicateRegexpCharacterClassElement: Enabled: false Lint/DuplicateRequire: Enabled: false Lint/DuplicateRescueException: Enabled: false Lint/EmptyBlock: Enabled: false Lint/EmptyClass: Enabled: false Lint/EmptyConditionalBody: Enabled: false Lint/EmptyFile: Enabled: false Lint/ErbNewArguments: Enabled: false Lint/FloatComparison: Enabled: false Lint/HashCompareByIdentity: Enabled: false Lint/IdentityComparison: Enabled: false Lint/InterpolationCheck: Enabled: false Lint/MissingCopEnableDirective: Enabled: false Lint/MixedRegexpCaptureTypes: Enabled: false Lint/NestedPercentLiteral: Enabled: false Lint/NoReturnInBeginEndBlocks: Enabled: false Lint/NonDeterministicRequireOrder: Enabled: false Lint/OrderedMagicComments: Enabled: false Lint/OutOfRangeRegexpRef: Enabled: false Lint/RaiseException: Enabled: false Lint/RedundantCopEnableDirective: Enabled: false Lint/RedundantRequireStatement: Enabled: false Lint/RedundantSafeNavigation: Enabled: false Lint/RedundantWithIndex: Enabled: false Lint/RedundantWithObject: Enabled: false Lint/RegexpAsCondition: Enabled: false Lint/ReturnInVoidContext: Enabled: false Lint/SafeNavigationConsistency: Enabled: false Lint/SafeNavigationWithEmpty: Enabled: false Lint/SelfAssignment: Enabled: false Lint/SendWithMixinArgument: Enabled: false Lint/ShadowedArgument: Enabled: false Lint/StructNewOverride: Enabled: false Lint/ToEnumArguments: Enabled: false Lint/ToJSON: Enabled: false Lint/TopLevelReturnWithArgument: Enabled: false Lint/TrailingCommaInAttributeDeclaration: Enabled: false Lint/UnexpectedBlockArity: Enabled: false Lint/UnmodifiedReduceAccumulator: Enabled: false Lint/UnreachableLoop: Enabled: false Lint/UriEscapeUnescape: Enabled: false Lint/UriRegexp: Enabled: false Lint/UselessMethodDefinition: Enabled: false Lint/UselessTimes: 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 Migration/DepartmentName: Enabled: false +Naming/AccessorMethodName: + Enabled: false Naming/BlockParameterName: Enabled: false Naming/HeredocDelimiterCase: Enabled: false Naming/HeredocDelimiterNaming: Enabled: false Naming/MemoizedInstanceVariableName: Enabled: false Naming/MethodParameterName: Enabled: false Naming/RescuedExceptionsVariableName: Enabled: false RSpec/Be: Enabled: false RSpec/Capybara/CurrentPathExpectation: Enabled: false RSpec/Capybara/FeatureMethods: Enabled: false RSpec/Capybara/VisibilityMatcher: Enabled: false RSpec/ContextMethod: Enabled: false RSpec/ContextWording: Enabled: false RSpec/DescribeClass: Enabled: false RSpec/EmptyHook: Enabled: false RSpec/EmptyLineAfterExample: Enabled: false RSpec/EmptyLineAfterExampleGroup: Enabled: false RSpec/EmptyLineAfterHook: Enabled: false RSpec/ExampleLength: Enabled: false RSpec/ExampleWithoutDescription: Enabled: false RSpec/ExpectChange: Enabled: false RSpec/ExpectInHook: Enabled: false RSpec/FactoryBot/AttributeDefinedStatically: Enabled: false RSpec/FactoryBot/CreateList: Enabled: false RSpec/FactoryBot/FactoryClassName: Enabled: false RSpec/HooksBeforeExamples: Enabled: false RSpec/ImplicitBlockExpectation: Enabled: false RSpec/ImplicitSubject: Enabled: false RSpec/LeakyConstantDeclaration: Enabled: false RSpec/LetBeforeExamples: Enabled: false RSpec/MissingExampleGroupArgument: Enabled: false RSpec/MultipleExpectations: Enabled: false RSpec/MultipleMemoizedHelpers: Enabled: false RSpec/MultipleSubjects: Enabled: false RSpec/NestedGroups: Enabled: false RSpec/PredicateMatcher: Enabled: false RSpec/ReceiveCounts: Enabled: false RSpec/ReceiveNever: Enabled: false RSpec/RepeatedExampleGroupBody: Enabled: false RSpec/RepeatedExampleGroupDescription: Enabled: false RSpec/RepeatedIncludeExample: Enabled: false RSpec/ReturnFromStub: Enabled: false RSpec/SharedExamples: Enabled: false RSpec/StubbedMock: Enabled: false RSpec/UnspecifiedException: Enabled: false RSpec/VariableDefinition: Enabled: false RSpec/VoidExpect: Enabled: false RSpec/Yield: Enabled: false Security/Open: Enabled: false Style/AccessModifierDeclarations: Enabled: false Style/AccessorGrouping: Enabled: false Style/ArgumentsForwarding: Enabled: false Style/AsciiComments: Enabled: false Style/BisectedAttrAccessor: Enabled: false Style/CaseLikeIf: Enabled: false Style/ClassEqualityComparison: Enabled: false Style/CollectionCompact: Enabled: false Style/ColonMethodDefinition: Enabled: false Style/CombinableLoops: Enabled: false Style/CommentedKeyword: Enabled: false Style/Dir: Enabled: false Style/DocumentDynamicEvalDefinition: Enabled: false Style/DoubleCopDisableDirective: Enabled: false Style/EmptyBlockParameter: Enabled: false Style/EmptyLambdaParameter: Enabled: false Style/Encoding: Enabled: false Style/EvalWithLocation: Enabled: false Style/ExpandPathArguments: Enabled: false Style/ExplicitBlockArgument: Enabled: false Style/ExponentialNotation: Enabled: false Style/FloatDivision: Enabled: false Style/GlobalStdStream: Enabled: false Style/HashAsLastArrayItem: Enabled: false Style/HashLikeCase: Enabled: false Style/HashTransformKeys: Enabled: false Style/HashTransformValues: Enabled: false Style/IfUnlessModifier: Enabled: false Style/KeywordParametersOrder: Enabled: false Style/MinMax: Enabled: false Style/MixinUsage: Enabled: false Style/MultilineWhenThen: Enabled: false Style/NegatedIfElseCondition: Enabled: false Style/NegatedUnless: Enabled: false Style/NilLambda: Enabled: false Style/NumericPredicate: Enabled: false Style/OptionalBooleanParameter: Enabled: false Style/OrAssignment: Enabled: false Style/RandomWithOffset: Enabled: false Style/RedundantArgument: Enabled: false Style/RedundantAssignment: Enabled: false Style/RedundantCondition: Enabled: false Style/RedundantConditional: Enabled: false Style/RedundantFetchBlock: Enabled: false Style/RedundantFileExtensionInRequire: Enabled: false Style/RedundantRegexpCharacterClass: Enabled: false Style/RedundantRegexpEscape: Enabled: false Style/RedundantSelfAssignment: Enabled: false Style/RedundantSort: Enabled: false Style/RescueStandardError: Enabled: false Style/SingleArgumentDig: Enabled: false Style/SlicingWithRange: Enabled: false Style/SoleNestedConditional: Enabled: false Style/StderrPuts: Enabled: false Style/StringConcatenation: Enabled: false Style/Strip: Enabled: false Style/SwapValues: Enabled: false Style/SymbolProc: Enabled: false Style/TrailingBodyOnClass: Enabled: false Style/TrailingBodyOnMethodDefinition: Enabled: false Style/TrailingBodyOnModule: Enabled: false Style/TrailingCommaInHashLiteral: Enabled: false Style/TrailingMethodEndStatement: Enabled: false Style/UnpackFirst: Enabled: false diff --git a/.sync.yml b/.sync.yml index c98af8dc..76e37157 100644 --- a/.sync.yml +++ b/.sync.yml @@ -1,50 +1,52 @@ --- ".gitlab-ci.yml": delete: true +".rubocop.yml": + include_todos: true ".travis.yml": global_env: - HONEYCOMB_WRITEKEY="7f3c63a70eecc61d635917de46bea4e6",HONEYCOMB_DATASET="litmus tests" deploy_to_forge: enabled: false secure: '' branches: - release use_litmus: true litmus: provision_list: - ---travis_el - travis_deb - travis_el7 - travis_el8 complex: - collection: puppet_collection: - puppet6 provision_list: - travis_ub_6 - collection: puppet_collection: - puppet5 provision_list: - travis_ub_5 simplecov: true notifications: slack: secure: MrXQwGIUO7WNmLbe7iiWgURiZPUgyvDLkKe3d9S58ohE6gdN6pqlsjP8YgodK8JmIBV1zp5Wj/0cXUmY3xvCtnDmII0DCEk2Y1Cs/W1drKZtS/0BsUpJkj0rDP2fSlKsY5ifESdEta/y8+NkjRnqadbl7SQPYeek4IjAfxjjuig= appveyor.yml: delete: true Gemfile: optional: ":development": - gem: github_changelog_generator spec/spec_helper.rb: mock_with: ":rspec" coverage_report: true .gitpod.Dockerfile: unmanaged: false .gitpod.yml: unmanaged: false .github/workflows/nightly.yml: unmanaged: false .github/workflows/pr_test.yml: unmanaged: false diff --git a/spec/acceptance/apache_ssl_spec.rb b/spec/acceptance/apache_ssl_spec.rb index 42a187ef..4645db4d 100644 --- a/spec/acceptance/apache_ssl_spec.rb +++ b/spec/acceptance/apache_ssl_spec.rb @@ -1,160 +1,160 @@ # frozen_string_literal: true require 'spec_helper_acceptance' apache_hash = apache_settings_hash describe 'apache ssl' do describe 'ssl parameters' do pp = <<-MANIFEST class { 'apache': service_ensure => stopped, default_ssl_vhost => true, default_ssl_cert => '/tmp/ssl_cert', default_ssl_key => '/tmp/ssl_key', default_ssl_chain => '/tmp/ssl_chain', default_ssl_ca => '/tmp/ssl_ca', default_ssl_crl_path => '/tmp/ssl_crl_path', default_ssl_crl => '/tmp/ssl_crl', default_ssl_crl_check => 'chain', } MANIFEST it 'runs without error' do idempotent_apply(pp) end describe file("#{apache_hash['mod_ssl_dir']}/ssl.conf") do it { is_expected.to be_file } - if os[:family] =~ %r{redhat} && os[:release].to_i == 8 + if os[:family].include?(redhat) && os[:release].to_i == 8 it { is_expected.to contain 'SSLProtocol all' } else it { is_expected.to contain 'SSLProtocol all -SSLv2 -SSLv3' } end end describe file("#{apache_hash['vhost_dir']}/15-default-ssl.conf") do it { is_expected.to be_file } it { is_expected.to contain 'SSLCertificateFile "/tmp/ssl_cert"' } it { is_expected.to contain 'SSLCertificateKeyFile "/tmp/ssl_key"' } it { is_expected.to contain 'SSLCertificateChainFile "/tmp/ssl_chain"' } it { is_expected.to contain 'SSLCACertificateFile "/tmp/ssl_ca"' } it { is_expected.to contain 'SSLCARevocationPath "/tmp/ssl_crl_path"' } it { is_expected.to contain 'SSLCARevocationFile "/tmp/ssl_crl"' } if apache_hash['version'] == '2.4' it { is_expected.to contain 'SSLCARevocationCheck chain' } else it { is_expected.not_to contain 'SSLCARevocationCheck' } end end end describe 'vhost ssl parameters' do pp = <<-MANIFEST class { 'apache': service_ensure => stopped, } apache::vhost { 'test_ssl': docroot => '/tmp/test', ssl => true, ssl_cert => '/tmp/ssl_cert', ssl_key => '/tmp/ssl_key', ssl_chain => '/tmp/ssl_chain', ssl_ca => '/tmp/ssl_ca', ssl_crl_path => '/tmp/ssl_crl_path', ssl_crl => '/tmp/ssl_crl', ssl_crl_check => 'chain flag', ssl_certs_dir => '/tmp', ssl_protocol => 'test', ssl_cipher => 'test', ssl_honorcipherorder => 'test', ssl_verify_client => 'require', ssl_verify_depth => 'test', ssl_options => ['test', 'test1'], ssl_proxyengine => true, ssl_proxy_protocol => 'TLSv1.2', } MANIFEST it 'runs without error' do idempotent_apply(pp) end describe file("#{apache_hash['vhost_dir']}/25-test_ssl.conf") do it { is_expected.to be_file } it { is_expected.to contain 'SSLCertificateFile "/tmp/ssl_cert"' } it { is_expected.to contain 'SSLCertificateKeyFile "/tmp/ssl_key"' } it { is_expected.to contain 'SSLCertificateChainFile "/tmp/ssl_chain"' } it { is_expected.to contain 'SSLCACertificateFile "/tmp/ssl_ca"' } it { is_expected.to contain 'SSLCACertificatePath "/tmp"' } it { is_expected.to contain 'SSLCARevocationPath "/tmp/ssl_crl_path"' } it { is_expected.to contain 'SSLCARevocationFile "/tmp/ssl_crl"' } it { is_expected.to contain 'SSLProxyEngine On' } it { is_expected.to contain 'SSLProtocol test' } it { is_expected.to contain 'SSLCipherSuite test' } it { is_expected.to contain 'SSLHonorCipherOrder test' } it { is_expected.to contain 'SSLVerifyClient require' } it { is_expected.to contain 'SSLVerifyDepth test' } it { is_expected.to contain 'SSLOptions test test1' } if apache_hash['version'] == '2.4' it { is_expected.to contain 'SSLCARevocationCheck chain flag' } else it { is_expected.not_to contain 'SSLCARevocationCheck' } end end end describe 'vhost ssl ssl_ca only' do pp = <<-MANIFEST class { 'apache': service_ensure => stopped, } apache::vhost { 'test_ssl_ca_only': docroot => '/tmp/test', ssl => true, ssl_cert => '/tmp/ssl_cert', ssl_key => '/tmp/ssl_key', ssl_ca => '/tmp/ssl_ca', ssl_verify_client => 'optional', } MANIFEST it 'runs without error' do idempotent_apply(pp) end describe file("#{apache_hash['vhost_dir']}/25-test_ssl_ca_only.conf") do it { is_expected.to be_file } it { is_expected.to contain 'SSLCertificateFile "/tmp/ssl_cert"' } it { is_expected.to contain 'SSLCertificateKeyFile "/tmp/ssl_key"' } it { is_expected.to contain 'SSLCACertificateFile "/tmp/ssl_ca"' } it { is_expected.not_to contain 'SSLCACertificatePath' } end end describe 'vhost ssl ssl_certs_dir' do pp = <<-MANIFEST class { 'apache': service_ensure => stopped, } apache::vhost { 'test_ssl_certs_dir_only': docroot => '/tmp/test', ssl => true, ssl_cert => '/tmp/ssl_cert', ssl_key => '/tmp/ssl_key', ssl_certs_dir => '/tmp', ssl_verify_client => 'require', } MANIFEST it 'runs without error' do idempotent_apply(pp) end describe file("#{apache_hash['vhost_dir']}/25-test_ssl_certs_dir_only.conf") do it { is_expected.to be_file } it { is_expected.to contain 'SSLCertificateFile "/tmp/ssl_cert"' } it { is_expected.to contain 'SSLCertificateKeyFile "/tmp/ssl_key"' } it { is_expected.to contain 'SSLCACertificatePath "/tmp"' } it { is_expected.to contain 'SSLVerifyClient require' } it { is_expected.not_to contain 'SSLCACertificateFile' } end end end diff --git a/spec/acceptance/mod_php_spec.rb b/spec/acceptance/mod_php_spec.rb index 02926df2..b95f7385 100644 --- a/spec/acceptance/mod_php_spec.rb +++ b/spec/acceptance/mod_php_spec.rb @@ -1,89 +1,89 @@ # frozen_string_literal: true require 'spec_helper_acceptance' apache_hash = apache_settings_hash describe 'apache::mod::php class', if: mod_supported_on_platform?('apache::mod::php') do context 'default php config' do pp = <<-MANIFEST class { 'apache': mpm_module => 'prefork', } class { 'apache::mod::php': } apache::vhost { 'php.example.com': port => '80', docroot => '#{apache_hash['doc_root']}/php', } host { 'php.example.com': ip => '127.0.0.1', } file { '#{apache_hash['doc_root']}/php/index.php': ensure => file, content => "\\n", } MANIFEST it 'succeeds in puppeting php' do apply_manifest(pp, catch_failures: true) end if (os[:family] == 'ubuntu' && os[:release] == '16.04') || - (os[:family] == 'debian' && os[:release] =~ %r{9}) + (os[:family] == 'debian' && os[:release] =~ %r{^9\.}) describe file("#{apache_hash['mod_dir']}/php7.0.conf") do it { is_expected.to contain 'DirectoryIndex index.php' } end - elsif os[:family] == 'debian' && os[:release] =~ %r{10} + elsif os[:family] == 'debian' && os[:release] =~ %r{^10\.} describe file("#{apache_hash['mod_dir']}/php7.3.conf") do it { is_expected.to contain 'DirectoryIndex index.php' } end elsif os[:family] == 'ubuntu' && os[:release] == '18.04' describe file("#{apache_hash['mod_dir']}/php7.2.conf") do it { is_expected.to contain 'DirectoryIndex index.php' } end elsif os[:family] == 'ubuntu' && os[:release] == '20.04' describe file("#{apache_hash['mod_dir']}/php7.4.conf") do it { is_expected.to contain 'DirectoryIndex index.php' } end - elsif os[:family] == 'redhat' && os[:release] =~ %r{^8} + elsif os[:family] == 'redhat' && os[:release] =~ %r{^8\.} describe file("#{apache_hash['mod_dir']}/php7.conf") do it { is_expected.to contain 'DirectoryIndex index.php' } end else describe file("#{apache_hash['mod_dir']}/php5.conf") do it { is_expected.to contain 'DirectoryIndex index.php' } end end end context 'custom extensions, php_flag, php_value, php_admin_flag, and php_admin_value' do pp = <<-MANIFEST class { 'apache': mpm_module => 'prefork', } class { 'apache::mod::php': extensions => ['.php','.php5'], } apache::vhost { 'php.example.com': port => '80', docroot => '#{apache_hash['doc_root']}/php', php_values => { 'include_path' => '.:/usr/share/pear:/usr/bin/php', }, php_flags => { 'display_errors' => 'on', }, php_admin_values => { 'open_basedir' => '/var/www/php/:/usr/share/pear/', }, php_admin_flags => { 'engine' => 'on', }, } host { 'php.example.com': ip => '127.0.0.1', } file { '#{apache_hash['doc_root']}/php/index.php5': ensure => file, content => "\\n", } MANIFEST it 'succeeds in puppeting php' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-php.example.com.conf") do it { is_expected.to contain ' php_flag display_errors on' } it { is_expected.to contain ' php_value include_path ".:/usr/share/pear:/usr/bin/php"' } it { is_expected.to contain ' php_admin_flag engine on' } it { is_expected.to contain ' php_admin_value open_basedir /var/www/php/:/usr/share/pear/' } end end end diff --git a/spec/acceptance/vhost_spec.rb b/spec/acceptance/vhost_spec.rb index 8c0079e8..5ddf6df3 100644 --- a/spec/acceptance/vhost_spec.rb +++ b/spec/acceptance/vhost_spec.rb @@ -1,1292 +1,1292 @@ # frozen_string_literal: true require 'spec_helper_acceptance' apache_hash = apache_settings_hash describe 'apache::vhost define' do context 'no default vhosts' do pp = <<-MANIFEST class { 'apache': default_vhost => false, default_ssl_vhost => false, service_ensure => stopped, } if ($::osfamily == 'Suse' and $::operatingsystemrelease < '15') { exec { '/usr/bin/gensslcert': require => Class['apache'], } } elsif ($::osfamily == 'Suse' and $::operatingsystemrelease >= '15') { # In SLES 15, if not given a name, gensslcert defaults the name to be the hostname exec { '/usr/bin/gensslcert -n default': require => Class['apache'], } } MANIFEST it 'creates no default vhosts' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/15-default.conf") do it { is_expected.not_to be_file } end describe file("#{apache_hash['vhost_dir']}/15-default-ssl.conf") do it { is_expected.not_to be_file } end end context 'default vhost without ssl' do pp = <<-MANIFEST class { 'apache': } MANIFEST it 'creates a default vhost config' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/15-default.conf") do it { is_expected.to contain '' } end describe file("#{apache_hash['vhost_dir']}/15-default-ssl.conf") do it { is_expected.not_to be_file } end end - context 'default vhost with ssl', unless: (os[:family] =~ %r{redhat} && os[:release].to_i == 8) do + context 'default vhost with ssl', unless: (os[:family].inclde?(redhat) && os[:release].to_i == 8) do pp = <<-MANIFEST file { '#{apache_hash['run_dir']}': ensure => 'directory', recurse => true, } class { 'apache': default_ssl_vhost => true, require => File['#{apache_hash['run_dir']}'], } MANIFEST it 'creates default vhost configs' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/15-default.conf") do it { is_expected.to contain '' } end describe file("#{apache_hash['vhost_dir']}/15-default-ssl.conf") do it { is_expected.to contain '' } it { is_expected.to contain 'SSLEngine on' } end end context 'new vhost on port 80' do pp = <<-MANIFEST class { 'apache': } file { '/var/www': ensure => 'directory', recurse => true, } apache::vhost { 'first.example.com': port => '80', docroot => '/var/www/first', require => File['/var/www'], } MANIFEST it 'configures an apache vhost' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-first.example.com.conf") do it { is_expected.to contain '' } it { is_expected.to contain 'ServerName first.example.com' } end end context 'new proxy vhost on port 80' do pp = <<-MANIFEST class { 'apache': } apache::vhost { 'proxy.example.com': port => '80', docroot => '/var/www/proxy', proxy_pass => [ { 'path' => '/foo', 'url' => 'http://backend-foo/'}, ], proxy_preserve_host => true, proxy_error_override => true, } MANIFEST it 'configures an apache proxy vhost' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-proxy.example.com.conf") do it { is_expected.to contain '' } it { is_expected.to contain 'ServerName proxy.example.com' } it { is_expected.to contain 'ProxyPass' } it { is_expected.to contain 'ProxyPreserveHost On' } it { is_expected.to contain 'ProxyErrorOverride On' } it { is_expected.not_to contain 'ProxyAddHeaders' } it { is_expected.not_to contain "" } end end context 'new proxy vhost on port 80' do pp = <<-MANIFEST class { 'apache': } apache::vhost { 'proxy.example.com': port => '80', docroot => '#{apache_hash['doc_root']}/proxy', proxy_pass_match => [ { 'path' => '/foo', 'url' => 'http://backend-foo/'}, ], proxy_preserve_host => true, proxy_error_override => true, } MANIFEST it 'configures an apache proxy vhost' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-proxy.example.com.conf") do it { is_expected.to contain '' } it { is_expected.to contain 'ServerName proxy.example.com' } it { is_expected.to contain 'ProxyPassMatch /foo http://backend-foo/' } it { is_expected.to contain 'ProxyPreserveHost On' } it { is_expected.to contain 'ProxyErrorOverride On' } it { is_expected.not_to contain 'ProxyAddHeaders' } it { is_expected.not_to contain "" } end end context 'new vhost with multiple IP addresses on multiple ports' do pp = <<-MANIFEST class { 'apache': default_vhost => false, } apache::vhost { 'example.com': port => ['80', '8080'], ip => ['127.0.0.1','127.0.0.2'], ip_based => true, docroot => '/var/www/html', } host { 'host1.example.com': ip => '127.0.0.1', } host { 'host2.example.com': ip => '127.0.0.2', } file { '/var/www/html/index.html': ensure => file, content => "Hello from vhost\\n", } MANIFEST it 'configures one apache vhost with 2 ip addresses and 2 ports' do apply_manifest(pp, catch_failures: true) end describe service(apache_hash['service_name']), skip: 'FM-8483' do it { is_expected.to be_enabled } it { is_expected.to be_running } end describe file("#{apache_hash['vhost_dir']}/25-example.com.conf") do it { is_expected.to contain '' } it { is_expected.to contain 'ServerName example.com' } end describe file(apache_hash['ports_file']) do it { is_expected.to be_file } it { is_expected.to contain 'Listen 127.0.0.1:80' } it { is_expected.to contain 'Listen 127.0.0.1:8080' } it { is_expected.to contain 'Listen 127.0.0.2:80' } it { is_expected.to contain 'Listen 127.0.0.2:8080' } it { is_expected.not_to contain 'NameVirtualHost 127.0.0.1:80' } it { is_expected.not_to contain 'NameVirtualHost 127.0.0.1:8080' } it { is_expected.not_to contain 'NameVirtualHost 127.0.0.2:80' } it { is_expected.not_to contain 'NameVirtualHost 127.0.0.2:8080' } end it 'answers to host1.example.com port 80' do run_shell('/usr/bin/curl host1.example.com:80', acceptable_exit_codes: 0) do |r| expect(r.stdout).to eq("Hello from vhost\n") end end it 'answers to host1.example.com port 8080' do run_shell('/usr/bin/curl host1.example.com:8080', acceptable_exit_codes: 0) do |r| expect(r.stdout).to eq("Hello from vhost\n") end end it 'answers to host2.example.com port 80' do run_shell('/usr/bin/curl host2.example.com:80', acceptable_exit_codes: 0) do |r| expect(r.stdout).to eq("Hello from vhost\n") end end it 'answers to host2.example.com port 8080' do run_shell('/usr/bin/curl host2.example.com:8080', acceptable_exit_codes: 0) do |r| expect(r.stdout).to eq("Hello from vhost\n") end end end context 'new vhost with IPv6 address on port 80', :ipv6 do pp = <<-MANIFEST class { 'apache': default_vhost => false, } apache::vhost { 'example.com': port => '80', ip => '::1', ip_based => true, docroot => '/var/www/html', } host { 'ipv6.example.com': ip => '::1', } file { '/var/www/html/index.html': ensure => file, content => "Hello from vhost\\n", } MANIFEST it 'configures one apache vhost with an ipv6 address' do apply_manifest(pp, catch_failures: true) end describe service(apache_hash['service_name']), skip: 'FM-8483' do it { is_expected.to be_enabled } it { is_expected.to be_running } end describe file("#{apache_hash['vhost_dir']}/25-example.com.conf") do it { is_expected.to contain '' } it { is_expected.to contain 'ServerName example.com' } end describe file(apache_hash['ports_file']) do it { is_expected.to be_file } it { is_expected.to contain 'Listen [::1]:80' } it { is_expected.not_to contain 'NameVirtualHost [::1]:80' } end it 'answers to ipv6.example.com' do run_shell('/usr/bin/curl ipv6.example.com:80', acceptable_exit_codes: 0) do |r| expect(r.stdout).to eq("Hello from vhost\n") end end end context 'apache_directories' do let(:pp) do <<-MANIFEST class { 'apache': } if versioncmp('#{apache_hash['version']}', '2.4') >= 0 { $_files_match_directory = { 'path' => '(\.swp|\.bak|~)$', 'provider' => 'filesmatch', 'require' => 'all denied', } } else { $_files_match_directory = { 'path' => '(\.swp|\.bak|~)$', 'provider' => 'filesmatch', 'deny' => 'from all', } } $_directories = [ { 'path' => '/var/www/files', }, $_files_match_directory, ] apache::vhost { 'files.example.net': docroot => '/var/www/files', directories => $_directories, } file { '/var/www/files/index.html': ensure => file, content => "Hello World\\n", } file { '/var/www/files/index.html.bak': ensure => file, content => "Hello World\\n", } host { 'files.example.net': ip => '127.0.0.1', } MANIFEST end describe 'readme example, adapted' do it 'configures a vhost with Files' do apply_manifest(pp, catch_failures: true) end describe service(apache_hash['service_name']), skip: 'FM-8483' do it { is_expected.to be_enabled } it { is_expected.to be_running } end it 'answers to files.example.net #stdout' do expect(run_shell('/usr/bin/curl -sSf files.example.net:80/index.html').stdout).to eq("Hello World\n") end it 'answers to files.example.net #stderr' do result = run_shell('/usr/bin/curl -sSf files.example.net:80/index.html.bak', expect_failures: true) expect(result.stderr).to match(%r{curl: \(22\) The requested URL returned error: 403}) expect(result.exit_code).to eq 22 end end describe 'other Directory options' do pp_one = <<-MANIFEST class { 'apache': } if versioncmp($apache_version, '2.4') >= 0 { $_files_match_directory = { 'path' => 'private.html$', 'provider' => 'filesmatch', 'require' => 'all denied' } } else { $_files_match_directory = [ { 'path' => 'private.html$', 'provider' => 'filesmatch', 'deny' => 'from all' }, { 'path' => '/bar/bar.html', 'provider' => 'location', allow => [ 'from 127.0.0.1', ] }, ] } $_directories = [ { 'path' => '/var/www/files', }, { 'path' => '/foo/', 'provider' => 'location', 'directoryindex' => 'notindex.html', }, $_files_match_directory, ] apache::vhost { 'files.example.net': docroot => '/var/www/files', directories => $_directories, } file { '/var/www/files/foo': ensure => directory, } file { '/var/www/files/foo/notindex.html': ensure => file, content => "Hello Foo\\n", } file { '/var/www/files/private.html': ensure => file, content => "Hello World\\n", } file { '/var/www/files/bar': ensure => directory, } file { '/var/www/files/bar/bar.html': ensure => file, content => "Hello Bar\\n", } host { 'files.example.net': ip => '127.0.0.1', } MANIFEST it 'configures a vhost with multiple Directory sections' do apply_manifest(pp_one, catch_failures: true) end describe service(apache_hash['service_name']), skip: 'FM-8483' do it { is_expected.to be_enabled } it { is_expected.to be_running } end it 'answers to files.example.net #stdout' do expect(run_shell('/usr/bin/curl -sSf files.example.net:80/').stdout).to eq("Hello World\n") end it 'answers to files.example.net #stdout foo' do expect(run_shell('/usr/bin/curl -sSf files.example.net:80/foo/').stdout).to eq("Hello Foo\n") end it 'answers to files.example.net #stderr' do result = run_shell('/usr/bin/curl -sSf files.example.net:80/private.html', expect_failures: true) expect(result.stderr).to match(%r{curl: \(22\) The requested URL returned error: 403}) expect(result.exit_code).to eq 22 end it 'answers to files.example.net #stdout bar' do expect(run_shell('/usr/bin/curl -sSf files.example.net:80/bar/bar.html').stdout).to eq("Hello Bar\n") end end describe 'SetHandler directive' do pp_two = <<-MANIFEST class { 'apache': } apache::mod { 'status': } host { 'files.example.net': ip => '127.0.0.1', } apache::vhost { 'files.example.net': docroot => '/var/www/files', directories => [ { path => '/var/www/files', }, { path => '/server-status', provider => 'location', sethandler => 'server-status', }, ], } file { '/var/www/files/index.html': ensure => file, content => "Hello World\\n", } MANIFEST it 'configures a vhost with a SetHandler directive' do apply_manifest(pp_two, catch_failures: true) end describe service(apache_hash['service_name']), skip: 'FM-8483' do it { is_expected.to be_enabled } it { is_expected.to be_running } end it 'answers to files.example.net #stdout' do expect(run_shell('/usr/bin/curl -sSf files.example.net:80/index.html').stdout).to eq("Hello World\n") end it 'answers to files.example.net #stdout regex' do expect(run_shell('/usr/bin/curl -sSf files.example.net:80/server-status?auto').stdout).to match(%r{Scoreboard: }) end end describe 'Satisfy and Auth directive', unless: apache_hash['version'] == '2.4' do pp_two = <<-MANIFEST class { 'apache': } host { 'files.example.net': ip => '127.0.0.1', } apache::vhost { 'files.example.net': docroot => '/var/www/files', directories => [ { path => '/var/www/files/foo', auth_type => 'Basic', auth_name => 'Basic Auth', auth_user_file => '/var/www/htpasswd', auth_require => "valid-user", }, { path => '/var/www/files/bar', auth_type => 'Basic', auth_name => 'Basic Auth', auth_user_file => '/var/www/htpasswd', auth_require => 'valid-user', satisfy => 'Any', }, { path => '/var/www/files/baz', allow => 'from 10.10.10.10', auth_type => 'Basic', auth_name => 'Basic Auth', auth_user_file => '/var/www/htpasswd', auth_require => 'valid-user', satisfy => 'Any', }, ], } file { '/var/www/files/foo': ensure => directory, } file { '/var/www/files/bar': ensure => directory, } file { '/var/www/files/baz': ensure => directory, } file { '/var/www/files/foo/index.html': ensure => file, content => "Hello World\\n", } file { '/var/www/files/bar/index.html': ensure => file, content => "Hello World\\n", } file { '/var/www/files/baz/index.html': ensure => file, content => "Hello World\\n", } file { '/var/www/htpasswd': ensure => file, content => "login:IZ7jMcLSx0oQk", # "password" as password } MANIFEST it 'configures a vhost with Satisfy and Auth directive' do apply_manifest(pp_two, catch_failures: true) end describe service(apache_hash['service_name']), skip: 'FM-8483' do it { is_expected.to be_enabled } it { is_expected.to be_running } it 'answers to files.example.net' do result = run_shell('/usr/bin/curl -sSf files.example.net:80/foo/index.html', expect_failures: true) expect(result.stderr).to match(%r{curl: \(22\) The requested URL returned error: 401}) expect(result.exit_code).to eq 22 expect(run_shell('/usr/bin/curl -sSf -u login:password files.example.net:80/foo/index.html').stdout).to eq("Hello World\n") expect(run_shell('/usr/bin/curl -sSf files.example.net:80/bar/index.html').stdout).to eq("Hello World\n") expect(run_shell('/usr/bin/curl -sSf -u login:password files.example.net:80/bar/index.html').stdout).to eq("Hello World\n") result = run_shell('/usr/bin/curl -sSf files.example.net:80/baz/index.html', expect_failures: true) expect(result.stderr).to match(%r{curl: \(22\) The requested URL returned error: 401}) expect(result.exit_code).to eq 22 expect(run_shell('/usr/bin/curl -sSf -u login:password files.example.net:80/baz/index.html').stdout).to eq("Hello World\n") end end end end context 'virtual_docroot hosting separate sites' do pp = <<-MANIFEST class { 'apache': } apache::vhost { 'virt.example.com': vhost_name => '*', serveraliases => '*virt.example.com', port => '80', docroot => '/var/www/virt', virtual_docroot => '/var/www/virt/%1', } host { 'virt.example.com': ip => '127.0.0.1', } host { 'a.virt.example.com': ip => '127.0.0.1', } host { 'b.virt.example.com': ip => '127.0.0.1', } file { [ '/var/www/virt/a', '/var/www/virt/b', ]: ensure => directory, } file { '/var/www/virt/a/index.html': ensure => file, content => "Hello from a.virt\\n", } file { '/var/www/virt/b/index.html': ensure => file, content => "Hello from b.virt\\n", } MANIFEST it 'configures a vhost with VirtualDocumentRoot' do apply_manifest(pp, catch_failures: true) end describe service(apache_hash['service_name']), skip: 'FM-8483' do it { is_expected.to be_enabled } it { is_expected.to be_running } end it 'answers to a.virt.example.com' do run_shell('/usr/bin/curl a.virt.example.com:80', acceptable_exit_codes: 0) do |r| expect(r.stdout).to eq("Hello from a.virt\n") end end it 'answers to b.virt.example.com' do run_shell('/usr/bin/curl b.virt.example.com:80', acceptable_exit_codes: 0) do |r| expect(r.stdout).to eq("Hello from b.virt\n") end end end context 'proxy_pass for alternative vhost' do it 'configures a local vhost and a proxy vhost' do apply_manifest(%( class { 'apache': default_vhost => false, } apache::vhost { 'localhost': docroot => '/var/www/local', ip => '127.0.0.1', port => '8888', } apache::listen { '*:80': } apache::vhost { 'proxy.example.com': docroot => '/var/www', port => '80', add_listen => false, proxy_pass => { 'path' => '/', 'url' => 'http://localhost:8888/subdir/', }, } host { 'proxy.example.com': ip => '127.0.0.1', } file { ['/var/www/local', '/var/www/local/subdir']: ensure => directory, } file { '/var/www/local/subdir/index.html': ensure => file, content => "Hello from localhost\\n", } ), catch_failures: true) end describe service(apache_hash['service_name']), skip: 'FM-8483' do it { is_expected.to be_enabled } it { is_expected.to be_running } end it 'gets a response from the back end #stdout' do run_shell('/usr/bin/curl --max-redirs 0 proxy.example.com:80') do |r| expect(r.stdout).to eq("Hello from localhost\n") end end it 'gets a response from the back end #exit_code' do run_shell('/usr/bin/curl --max-redirs 0 proxy.example.com:80') do |r| expect(r.exit_code).to eq(0) end end end context 'proxy_pass_match for alternative vhost' do it 'configures a local vhost and a proxy vhost' do apply_manifest(%( class { 'apache': default_vhost => false, } apache::vhost { 'localhost': docroot => '/var/www/local', ip => '127.0.0.1', port => '8888', } apache::listen { '*:80': } apache::vhost { 'proxy.example.com': docroot => '/var/www', port => '80', add_listen => false, proxy_pass_match => { 'path' => '/', 'url' => 'http://localhost:8888/subdir/', }, } host { 'proxy.example.com': ip => '127.0.0.1', } file { ['/var/www/local', '/var/www/local/subdir']: ensure => directory, } file { '/var/www/local/subdir/index.html': ensure => file, content => "Hello from localhost\\n", } ), catch_failures: true) end describe service(apache_hash['service_name']), skip: 'FM-8483' do it { is_expected.to be_enabled } it { is_expected.to be_running } end it 'gets a response from the back end #stdout' do run_shell('/usr/bin/curl --max-redirs 0 proxy.example.com:80') do |r| expect(r.stdout).to eq("Hello from localhost\n") end end it 'gets a response from the back end #exit_code' do run_shell('/usr/bin/curl --max-redirs 0 proxy.example.com:80') do |r| expect(r.exit_code).to eq(0) end end end describe 'ip_based' do pp = <<-MANIFEST class { 'apache': } host { 'test.server': ip => '127.0.0.1' } apache::vhost { 'test.server': docroot => '/tmp', ip_based => true, servername => 'test.server', } MANIFEST it 'applies cleanly' do apply_manifest(pp, catch_failures: true) end describe file(apache_hash['ports_file']) do it { is_expected.to be_file } it { is_expected.not_to contain 'NameVirtualHost test.server' } end describe file("#{apache_hash['vhost_dir']}/25-test.server.conf") do it { is_expected.to be_file } it { is_expected.to contain 'ServerName test.server' } end end describe 'ip_based and no servername' do pp = <<-MANIFEST class { 'apache': } host { 'test.server': ip => '127.0.0.1' } apache::vhost { 'test.server': docroot => '/tmp', ip_based => true, servername => '', } MANIFEST it 'applies cleanly' do apply_manifest(pp, catch_failures: true) end describe file(apache_hash['ports_file']) do it { is_expected.to be_file } it { is_expected.not_to contain 'NameVirtualHost test.server' } end describe file("#{apache_hash['vhost_dir']}/25-test.server.conf") do it { is_expected.to be_file } it { is_expected.not_to contain 'ServerName' } end end describe 'add_listen' do pp = <<-MANIFEST class { 'apache': default_vhost => false } host { 'testlisten.server': ip => '127.0.0.1' } apache::listen { '81': } apache::vhost { 'testlisten.server': docroot => '/tmp', port => '80', add_listen => false, servername => 'testlisten.server', } MANIFEST it 'applies cleanly' do apply_manifest(pp, catch_failures: true) end describe file(apache_hash['ports_file']) do it { is_expected.to be_file } it { is_expected.not_to contain 'Listen 80' } it { is_expected.to contain 'Listen 81' } end end describe 'docroot' do pp = <<-MANIFEST user { 'test_owner': ensure => present, } group { 'test_group': ensure => present, } class { 'apache': } host { 'test.server': ip => '127.0.0.1' } apache::vhost { 'test.server': docroot => '/tmp/test', docroot_owner => 'test_owner', docroot_group => 'test_group', docroot_mode => '0750', } MANIFEST it 'applies cleanly' do apply_manifest(pp, catch_failures: true) end describe file('/tmp/test') do it { is_expected.to be_directory } it { is_expected.to be_owned_by 'test_owner' } it { is_expected.to be_grouped_into 'test_group' } it { is_expected.to be_mode 750 } end end describe 'default_vhost' do pp = <<-MANIFEST class { 'apache': } host { 'test.server': ip => '127.0.0.1' } apache::vhost { 'test.server': docroot => '/tmp', default_vhost => true, } MANIFEST it 'applies cleanly' do apply_manifest(pp, catch_failures: true) end describe file(apache_hash['ports_file']) do it { is_expected.to be_file } end describe file("#{apache_hash['vhost_dir']}/10-test.server.conf") do it { is_expected.to be_file } end end describe 'parameter tests', if: mod_supported_on_platform?('apache::mod::itk') do pp = <<-MANIFEST class { 'apache': } host { 'test.itk': ip => '127.0.0.1' } apache::vhost { 'test.itk': docroot => '/tmp', itk => { user => 'nobody', group => 'nobody' } } host { 'test.custom_fragment': ip => '127.0.0.1' } apache::vhost { 'test.custom_fragment': docroot => '/tmp', custom_fragment => inline_template('#weird test string'), } apache::vhost { 'test.without_priority_prefix': priority => false, docroot => '/tmp' } apache::vhost { 'test.ssl_protocol': docroot => '/tmp', ssl => true, ssl_protocol => ['All', '-SSLv2'], ssl_user_name => 'SSL_CLIENT_S_DN_CN', } apache::vhost { 'test.block': docroot => '/tmp', block => 'scm', } apache::vhost { 'test.setenv_setenvif': docroot => '/tmp', setenv => ['TEST /test'], setenvif => ['Request_URI "\.gif$" object_is_image=gif'] } apache::vhost { 'test.rewrite': docroot => '/tmp', rewrites => [ { comment => 'test', rewrite_cond => '%{HTTP_USER_AGENT} ^Lynx/ [OR]', rewrite_rule => ['^index\.html$ welcome.html'], rewrite_map => ['lc int:tolower'], } ], } apache::vhost { 'test.request_headers': docroot => '/tmp', request_headers => ['append MirrorID "mirror 12"'], } apache::vhost { 'test.redirect': docroot => '/tmp', redirect_source => ['/images'], redirect_dest => ['http://test.server/'], redirect_status => ['permanent'], } apache::vhost { 'test.no_proxy_uris': docroot => '/tmp', proxy_dest => 'http://test2', no_proxy_uris => [ 'http://test2/test' ], } apache::vhost { 'test.proxy': docroot => '/tmp', proxy_dest => 'http://testproxy', } apache::vhost { 'test.scriptaliases': docroot => '/tmp', scriptaliases => [{ alias => '/myscript', path => '/usr/share/myscript', }], } apache::vhost { 'test.aliases': docroot => '/tmp', aliases => [ { alias => '/image' , path => '/ftp/pub/image' } , { scriptalias => '/myscript' , path => '/usr/share/myscript' } ], } apache::vhost { 'test.access_logs': docroot => '/tmp', logroot => '/tmp', access_logs => [ {'file' => 'log1'}, {'file' => 'log2', 'env' => 'admin' }, {'file' => '/var/tmp/log3', 'format' => '%h %l'}, {'syslog' => 'syslog' } ] } apache::vhost { 'test.access_log_env_var': docroot => '/tmp', logroot => '/tmp', access_log_syslog => 'syslog', access_log_env_var => 'admin', } apache::vhost { 'test.access_log_format': docroot => '/tmp', logroot => '/tmp', access_log_syslog => 'syslog', access_log_format => '%h %l', } apache::vhost { 'test.logroot': docroot => '/tmp', logroot => '/tmp', } apache::vhost { 'test.override': docroot => '/tmp', override => ['All'], } apache::vhost { 'test.options': docroot => '/tmp', options => ['Indexes','FollowSymLinks', 'ExecCGI'], } MANIFEST it 'applies cleanly' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-test.itk.conf") do it { is_expected.to be_file } it { is_expected.to contain 'AssignUserId nobody nobody' } end describe file("#{apache_hash['vhost_dir']}/25-test.custom_fragment.conf") do it { is_expected.to be_file } it { is_expected.to contain '#weird test string' } end describe file("#{apache_hash['vhost_dir']}/test.without_priority_prefix.conf") do it { is_expected.to be_file } end describe file("#{apache_hash['vhost_dir']}/25-test.ssl_protocol.conf") do it { is_expected.to be_file } it { is_expected.to contain 'SSLProtocol *All -SSLv2' } it { is_expected.to contain 'SSLUserName *SSL_CLIENT_S_DN_CN' } end describe file("#{apache_hash['vhost_dir']}/25-test.block.conf") do it { is_expected.to be_file } it { is_expected.to contain '' } end describe file("#{apache_hash['vhost_dir']}/25-test.setenv_setenvif.conf") do it { is_expected.to be_file } it { is_expected.to contain 'SetEnv TEST /test' } it { is_expected.to contain 'SetEnvIf Request_URI "\.gif$" object_is_image=gif' } end describe file("#{apache_hash['vhost_dir']}/25-test.rewrite.conf") do it { is_expected.to be_file } it { is_expected.to contain '#test' } it { is_expected.to contain 'RewriteCond %{HTTP_USER_AGENT} ^Lynx/ [OR]' } it { is_expected.to contain 'RewriteRule ^index.html$ welcome.html' } it { is_expected.to contain 'RewriteMap lc int:tolower' } end describe file("#{apache_hash['vhost_dir']}/25-test.request_headers.conf") do it { is_expected.to be_file } it { is_expected.to contain 'append MirrorID "mirror 12"' } end describe file("#{apache_hash['vhost_dir']}/25-test.redirect.conf") do it { is_expected.to be_file } it { is_expected.to contain 'Redirect permanent /images http://test.server/' } end describe file("#{apache_hash['vhost_dir']}/25-test.no_proxy_uris.conf") do it { is_expected.to be_file } it { is_expected.to contain 'ProxyPass http://test2/test !' } it { is_expected.to contain 'ProxyPass / http://test2/' } end describe file("#{apache_hash['vhost_dir']}/25-test.proxy.conf") do it { is_expected.to be_file } it { is_expected.to contain 'ProxyPass / http://testproxy/' } end describe file("#{apache_hash['vhost_dir']}/25-test.scriptaliases.conf") do it { is_expected.to be_file } it { is_expected.to contain 'ScriptAlias /myscript "/usr/share/myscript"' } end describe file("#{apache_hash['vhost_dir']}/25-test.aliases.conf") do it { is_expected.to be_file } it { is_expected.to contain 'Alias /image "/ftp/pub/image"' } it { is_expected.to contain 'ScriptAlias /myscript "/usr/share/myscript"' } end describe file("#{apache_hash['vhost_dir']}/25-test.access_logs.conf") do it { is_expected.to be_file } it { is_expected.to contain 'CustomLog "/tmp/log1" combined' } it { is_expected.to contain 'CustomLog "/tmp/log2" combined env=admin' } it { is_expected.to contain 'CustomLog "/var/tmp/log3" "%h %l"' } it { is_expected.to contain 'CustomLog "syslog" combined' } end describe file("#{apache_hash['vhost_dir']}/25-test.access_log_env_var.conf") do it { is_expected.to be_file } it { is_expected.to contain 'CustomLog "syslog" combined env=admin' } end describe file("#{apache_hash['vhost_dir']}/25-test.access_log_format.conf") do it { is_expected.to be_file } it { is_expected.to contain 'CustomLog "syslog" "%h %l"' } end describe file("#{apache_hash['vhost_dir']}/25-test.logroot.conf") do it { is_expected.to be_file } it { is_expected.to contain ' CustomLog "/tmp' } end describe file("#{apache_hash['vhost_dir']}/25-test.override.conf") do it { is_expected.to be_file } it { is_expected.to contain 'AllowOverride All' } end describe file("#{apache_hash['vhost_dir']}/25-test.options.conf") do it { is_expected.to be_file } it { is_expected.to contain 'Options Indexes FollowSymLinks ExecCGI' } end end context 'when a manifest defines $servername' do describe 'when the $use_servername_for_filenames parameter is set to true' do pp = <<-MANIFEST class { 'apache': } host { 'test.server': ip => '127.0.0.1' } apache::vhost { 'test.server': use_servername_for_filenames => true, servername => 'test.servername', docroot => '/tmp', logroot => '/tmp', } MANIFEST it 'applies cleanly and DOES NOT print warning about $use_servername_for_filenames usage for test.server vhost' do result = apply_manifest(pp, catch_failures: true) expect(result.stderr).not_to contain %r{ .*Warning\:\sScope\(Apache::Vhost\[test\.server\]\)\:.* It\sis\spossible\sfor\sthe\s\$name\sparameter.* sanitized\s\$servername\sparameter\swhen\snot\sexplicitly\sdefined\. }xm end describe file("#{apache_hash['vhost_dir']}/25-test.servername.conf") do it { is_expected.to be_file } it { is_expected.to contain ' ErrorLog "/tmp/test.servername_error.log' } it { is_expected.to contain ' CustomLog "/tmp/test.servername_access.log' } end end describe 'when the $use_servername_for_filenames parameter is NOT defined' do pp = <<-MANIFEST class { 'apache': } host { 'test.server': ip => '127.0.0.1' } apache::vhost { 'test.server': servername => 'test.servername', docroot => '/tmp', logroot => '/tmp', } MANIFEST it 'applies cleanly and prints warning about $use_servername_for_filenames usage for test.server vhost' do result = apply_manifest(pp, catch_failures: true) expect(result.stderr).to contain %r{ .*Warning\:\sScope\(Apache::Vhost\[test\.server\]\)\:.* It\sis\spossible\sfor\sthe\s\$name\sparameter.* sanitized\s\$servername\sparameter\swhen\snot\sexplicitly\sdefined\. }xm end describe file("#{apache_hash['vhost_dir']}/25-test.server.conf") do it { is_expected.to be_file } it { is_expected.to contain ' ErrorLog "/tmp/test.server_error.log' } it { is_expected.to contain ' CustomLog "/tmp/test.server_access.log' } end end end ['access', 'error'].each do |logtype| case logtype when 'access' logname = 'CustomLog' when 'error' logname = 'ErrorLog' end describe "#{logtype}_log" do pp = <<-MANIFEST class { 'apache': } host { 'test.server': ip => '127.0.0.1' } apache::vhost { 'test.server': docroot => '/tmp', logroot => '/tmp', #{logtype}_log => false, } MANIFEST it 'applies cleanly' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-test.server.conf") do it { is_expected.to be_file } it { is_expected.not_to contain " #{logname} \"/tmp" } end end describe "#{logtype}_log_pipe" do pp = <<-MANIFEST class { 'apache': } host { 'test.server': ip => '127.0.0.1' } apache::vhost { 'test.server': docroot => '/tmp', logroot => '/tmp', #{logtype}_log_pipe => '|/bin/sh', } MANIFEST it 'applies cleanly' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-test.server.conf") do it { is_expected.to be_file } it { is_expected.to contain " #{logname} \"|/bin/sh" } end end describe "#{logtype}_log_syslog" do pp = <<-MANIFEST class { 'apache': } host { 'test.server': ip => '127.0.0.1' } apache::vhost { 'test.server': docroot => '/tmp', logroot => '/tmp', #{logtype}_log_syslog => 'syslog', } MANIFEST it 'applies cleanly' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-test.server.conf") do it { is_expected.to be_file } it { is_expected.to contain " #{logname} \"syslog\"" } end end end describe 'actions' do pp = <<-MANIFEST class { 'apache': } host { 'test.server': ip => '127.0.0.1' } apache::vhost { 'test.server': docroot => '/tmp', action => 'php-fastcgi', } MANIFEST it 'applies cleanly' do pp += "\nclass { 'apache::mod::actions': }" if %r{debian|suse|ubuntu|sles}.match?(os[:family]) apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-test.server.conf") do it { is_expected.to be_file } it { is_expected.to contain 'Action php-fastcgi /cgi-bin virtual' } end end describe 'suphp' do pp = <<-MANIFEST class { 'apache': service_ensure => stopped, } host { 'test.server': ip => '127.0.0.1' } apache::vhost { 'test.server': docroot => '/tmp', suphp_addhandler => '#{apache_hash['suphp_handler']}', suphp_engine => 'on', suphp_configpath => '#{apache_hash['suphp_configpath']}', } MANIFEST it 'applies cleanly' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-test.server.conf") do it { is_expected.to be_file } it { is_expected.to contain "suPHP_AddHandler #{apache_hash['suphp_handler']}" } it { is_expected.to contain 'suPHP_Engine on' } it { is_expected.to contain "suPHP_ConfigPath \"#{apache_hash['suphp_configpath']}\"" } end end describe 'directory rewrite rules' do pp = <<-MANIFEST class { 'apache': } host { 'test.server': ip => '127.0.0.1' } if ! defined(Class['apache::mod::rewrite']) { include ::apache::mod::rewrite } apache::vhost { 'test.server': docroot => '/tmp', directories => [ { path => '/tmp', rewrites => [ { comment => 'Permalink Rewrites', rewrite_base => '/', }, { rewrite_rule => [ '^index\\.php$ - [L]' ] }, { rewrite_cond => [ '%{REQUEST_FILENAME} !-f', '%{REQUEST_FILENAME} !-d', ], rewrite_rule => [ '. /index.php [L]' ], } ], }, ], } MANIFEST it 'applies cleanly' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-test.server.conf") do it { is_expected.to be_file } it { is_expected.to contain '#Permalink Rewrites' } it { is_expected.to contain 'RewriteEngine On' } it { is_expected.to contain 'RewriteBase /' } it { is_expected.to contain 'RewriteRule ^index\.php$ - [L]' } it { is_expected.to contain 'RewriteCond %{REQUEST_FILENAME} !-f' } it { is_expected.to contain 'RewriteCond %{REQUEST_FILENAME} !-d' } it { is_expected.to contain 'RewriteRule . /index.php [L]' } end end describe 'wsgi' do context 'filter on OS', if: mod_supported_on_platform?('apache::mod::wsgi') do pp = <<-MANIFEST class { 'apache': } class { 'apache::mod::wsgi': } host { 'test.server': ip => '127.0.0.1' } apache::vhost { 'test.server': docroot => '/tmp', wsgi_application_group => '%{GLOBAL}', wsgi_daemon_process => { 'wsgi' => { 'python-home' => '/usr' }, 'foo' => {} }, wsgi_daemon_process_options => {processes => '2'}, wsgi_import_script => '/test1', wsgi_import_script_options => { application-group => '%{GLOBAL}', process-group => 'wsgi' }, wsgi_process_group => 'nobody', wsgi_script_aliases => { '/test' => '/test1' }, wsgi_script_aliases_match => { '/test/([^/*])' => '/test1' }, wsgi_pass_authorization => 'On', wsgi_chunked_request => 'On', } MANIFEST it 'import_script applies cleanly' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-test.server.conf") do it { is_expected.to be_file } it { is_expected.to contain 'WSGIApplicationGroup %{GLOBAL}' } it { is_expected.to contain 'WSGIDaemonProcess foo' } it { is_expected.to contain 'WSGIDaemonProcess wsgi python-home=/usr' } it { is_expected.to contain 'WSGIImportScript /test1 application-group=%{GLOBAL} process-group=wsgi' } it { is_expected.to contain 'WSGIProcessGroup nobody' } it { is_expected.to contain 'WSGIScriptAlias /test "/test1"' } it { is_expected.to contain 'WSGIPassAuthorization On' } it { is_expected.to contain 'WSGIChunkedRequest On' } end end end describe 'additional_includes' do pp = <<-MANIFEST if $::osfamily == 'RedHat' and "$::selinux" == "true" { $semanage_package = $::operatingsystemmajrelease ? { '5' => 'policycoreutils', '8' => 'policycoreutils-python-utils', default => 'policycoreutils-python', } package { $semanage_package: ensure => installed } exec { 'set_apache_defaults': command => 'semanage fcontext -a -t httpd_sys_content_t "/apache_spec(/.*)?"', path => '/bin:/usr/bin/:/sbin:/usr/sbin', require => Package[$semanage_package], } exec { 'restorecon_apache': command => 'restorecon -Rv /apache_spec', path => '/bin:/usr/bin/:/sbin:/usr/sbin', before => Service['httpd'], require => Class['apache'], } } class { 'apache': } host { 'test.server': ip => '127.0.0.1' } file { '/apache_spec': ensure => directory, } file { '/apache_spec/include': ensure => present, content => '#additional_includes' } apache::vhost { 'test.server': docroot => '/apache_spec', additional_includes => '/apache_spec/include', } MANIFEST it 'applies cleanly' do apply_manifest(pp, catch_failures: false) end describe file("#{apache_hash['vhost_dir']}/25-test.server.conf") do it { is_expected.to be_file } it { is_expected.to contain 'Include "/apache_spec/include"' } end end describe 'shibboleth parameters', if: (os[:family] == 'debian' && os[:release] != '7') do # Debian 7 is too old for ShibCompatValidUser pp = <<-MANIFEST class { 'apache': } class { 'apache::mod::shib': } apache::vhost { 'test.server': port => '80', docroot => '/var/www/html', shib_compat_valid_user => 'On' } MANIFEST it 'applies cleanly' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-test.server.conf") do it { is_expected.to be_file } it { is_expected.to contain 'ShibCompatValidUser On' } end end # IAC-587: These tests do not currently run successfully on certain RHEL OSs due to dependency issues with the # mod_auth_openidc module. describe 'auth_oidc', if: mod_supported_on_platform?('apache::mod::authnz_ldap') do pp = <<-MANIFEST class { 'apache': } apache::vhost { 'test.server': port => '80', docroot => '/var/www/html', auth_oidc => true, oidc_settings => { 'ProviderMetadataURL' => 'https://login.example.com/.well-known/openid-configuration', 'ClientID' => 'test', 'RedirectURI' => 'https://login.example.com/redirect_uri', 'ProviderTokenEndpointAuth' => 'client_secret_basic', 'RemoteUserClaim' => 'sub', 'ClientSecret' => 'aae053a9-4abf-4824-8956-e94b2af335c8', 'CryptoPassphrase' => '4ad1bb46-9979-450e-ae58-c696967df3cd' } } MANIFEST it 'applys cleanly' do apply_manifest(pp, catch_failures: true) end describe file("#{apache_hash['vhost_dir']}/25-test.server.conf") do it { is_expected.to be_file } it { is_expected.to contain 'OIDCProviderMetadataURL https://login.example.com/.well-known/openid-configuration' } it { is_expected.to contain 'OIDCClientID test' } it { is_expected.to contain 'OIDCRedirectURI https://login.example.com/redirect_uri' } it { is_expected.to contain 'OIDCProviderTokenEndpointAuth client_secret_basic' } it { is_expected.to contain 'OIDCRemoteUserClaim sub' } it { is_expected.to contain 'OIDCClientSecret aae053a9-4abf-4824-8956-e94b2af335c8' } it { is_expected.to contain 'OIDCCryptoPassphrase 4ad1bb46-9979-450e-ae58-c696967df3cd' } end end end diff --git a/spec/classes/mod/info_spec.rb b/spec/classes/mod/info_spec.rb index 9ca66544..5dc70f71 100644 --- a/spec/classes/mod/info_spec.rb +++ b/spec/classes/mod/info_spec.rb @@ -1,218 +1,218 @@ # frozen_string_literal: true require 'spec_helper' # This function is called inside the OS specific contexts -def general_info_specs_22 +def general_info_specs_apache22 it { is_expected.to contain_apache__mod('info') } context 'passing no parameters' do expected = "\n"\ " SetHandler server-info\n"\ " Order deny,allow\n"\ " Deny from all\n"\ " Allow from 127.0.0.1\n"\ " Allow from ::1\n"\ "\n" it { is_expected.to contain_file('info.conf').with_content(expected) } end context 'passing restrict_access => false' do let :params do { restrict_access: false, } end it { is_expected.to contain_file('info.conf').with_content( "\n"\ " SetHandler server-info\n"\ "\n", ) } end context "passing allow_from => ['10.10.1.2', '192.168.1.2', '127.0.0.1']" do let :params do { allow_from: ['10.10.1.2', '192.168.1.2', '127.0.0.1'] } end expected = "\n"\ " SetHandler server-info\n"\ " Order deny,allow\n"\ " Deny from all\n"\ " Allow from 10.10.1.2\n"\ " Allow from 192.168.1.2\n"\ " Allow from 127.0.0.1\n"\ "\n" it { is_expected.to contain_file('info.conf').with_content(expected) } end context 'passing both restrict_access and allow_from' do let :params do { restrict_access: false, allow_from: ['10.10.1.2', '192.168.1.2', '127.0.0.1'], } end it { is_expected.to contain_file('info.conf').with_content( "\n"\ " SetHandler server-info\n"\ "\n", ) } end end -def general_info_specs_24 +def general_info_specs_apache24 it { is_expected.to contain_apache__mod('info') } context 'passing no parameters' do expected = "\n"\ " SetHandler server-info\n"\ " Require ip 127.0.0.1 ::1\n"\ "\n" it { is_expected.to contain_file('info.conf').with_content(expected) } end context 'passing restrict_access => false' do let :params do { restrict_access: false, } end it { is_expected.to contain_file('info.conf').with_content( "\n"\ " SetHandler server-info\n"\ "\n", ) } end context "passing allow_from => ['10.10.1.2', '192.168.1.2', '127.0.0.1']" do let :params do { allow_from: ['10.10.1.2', '192.168.1.2', '127.0.0.1'] } end expected = "\n"\ " SetHandler server-info\n"\ " Require ip 10.10.1.2 192.168.1.2 127.0.0.1\n"\ "\n" it { is_expected.to contain_file('info.conf').with_content(expected) } end context 'passing both restrict_access and allow_from' do let :params do { restrict_access: false, allow_from: ['10.10.1.2', '192.168.1.2', '127.0.0.1'], } end it { is_expected.to contain_file('info.conf').with_content( "\n"\ " SetHandler server-info\n"\ "\n", ) } end end describe 'apache::mod::info', type: :class do it_behaves_like 'a mod class, without including apache' context 'On a Debian OS' do let :facts do { osfamily: 'Debian', operatingsystemrelease: '6', lsbdistcodename: 'squeeze', operatingsystem: 'Debian', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end # Load the more generic tests for this context - general_info_specs_22 + general_info_specs_apache22 it { is_expected.to contain_file('info.conf').with(ensure: 'file', path: '/etc/apache2/mods-available/info.conf') } it { is_expected.to contain_file('info.conf symlink').with(ensure: 'link', path: '/etc/apache2/mods-enabled/info.conf') } end context 'on a RedHat OS' do let :facts do { osfamily: 'RedHat', operatingsystemrelease: '6', operatingsystem: 'RedHat', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end # Load the more generic tests for this context - general_info_specs_22 + general_info_specs_apache22 it { is_expected.to contain_file('info.conf').with(ensure: 'file', path: '/etc/httpd/conf.d/info.conf') } end context 'on a FreeBSD OS' do let :facts do { osfamily: 'FreeBSD', operatingsystemrelease: '10', operatingsystem: 'FreeBSD', id: 'root', kernel: 'FreeBSD', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end # Load the more generic tests for this context - general_info_specs_24 + general_info_specs_apache24 it { is_expected.to contain_file('info.conf').with(ensure: 'file', path: '/usr/local/etc/apache24/Modules/info.conf') } end context 'on a Gentoo OS' do let :facts do { osfamily: 'Gentoo', operatingsystem: 'Gentoo', operatingsystemrelease: '3.16.1-gentoo', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin', is_pe: false, } end # Load the more generic tests for this context - general_info_specs_24 + general_info_specs_apache24 it { is_expected.to contain_file('info.conf').with(ensure: 'file', path: '/etc/apache2/modules.d/info.conf') } end end diff --git a/spec/classes/mod/security_spec.rb b/spec/classes/mod/security_spec.rb index 62ea9a61..50e9986a 100644 --- a/spec/classes/mod/security_spec.rb +++ b/spec/classes/mod/security_spec.rb @@ -1,214 +1,210 @@ # frozen_string_literal: true require 'spec_helper' describe 'apache::mod::security', type: :class do on_supported_os.each do |os, facts| context "on #{os} " do let :facts do facts end case facts[:os]['family'] when 'RedHat' context 'on RedHat based systems' do it { is_expected.to contain_apache__mod('security').with( id: 'security2_module', lib: 'mod_security2.so', ) } it { is_expected.to contain_apache__mod('unique_id_module').with( id: 'unique_id_module', lib: 'mod_unique_id.so', ) } + it { is_expected.to contain_package('mod_security_crs') } - if facts[:os]['release']['major'].to_i > 6 && facts[:os]['release']['major'].to_i <= 7 - it { - is_expected.to contain_file('security.conf').with( - path: '/etc/httpd/conf.modules.d/security.conf', - ) - } - end - if facts[:os]['release']['major'].to_i >= 8 + + if (facts[:os]['release']['major'].to_i > 6 && facts[:os]['release']['major'].to_i <= 7) || (facts[:os]['release']['major'].to_i >= 8) it { is_expected.to contain_file('security.conf').with( path: '/etc/httpd/conf.modules.d/security.conf', ) } end + it { is_expected.to contain_file('security.conf') .with_content(%r{^\s+SecAuditLogRelevantStatus "\^\(\?:5\|4\(\?!04\)\)"$}) .with_content(%r{^\s+SecAuditLogParts ABIJDEFHZ$}) .with_content(%r{^\s+SecAuditLogType Serial$}) .with_content(%r{^\s+SecDebugLog /var/log/httpd/modsec_debug.log$}) .with_content(%r{^\s+SecAuditLog /var/log/httpd/modsec_audit.log$}) } it { is_expected.to contain_file('/etc/httpd/modsecurity.d').with( ensure: 'directory', path: '/etc/httpd/modsecurity.d', owner: 'root', group: 'root', mode: '0755' ) } it { is_expected.to contain_file('/etc/httpd/modsecurity.d/activated_rules').with( ensure: 'directory', path: '/etc/httpd/modsecurity.d/activated_rules', owner: 'apache', group: 'apache' ) } it { is_expected.to contain_file('/etc/httpd/modsecurity.d/security_crs.conf').with( path: '/etc/httpd/modsecurity.d/security_crs.conf', ) } it { is_expected.to contain_apache__security__rule_link('base_rules/modsecurity_35_bad_robots.data') } it { is_expected.to contain_file('modsecurity_35_bad_robots.data').with( path: '/etc/httpd/modsecurity.d/activated_rules/modsecurity_35_bad_robots.data', target: '/usr/lib/modsecurity.d/base_rules/modsecurity_35_bad_robots.data', ) } describe 'with parameters' do let :params do { activated_rules: [ '/tmp/foo/bar.conf', ], audit_log_relevant_status: '^(?:5|4(?!01|04))', audit_log_parts: 'ABCDZ', audit_log_type: 'Concurrent', audit_log_storage_dir: '/var/log/httpd/audit', secdefaultaction: 'deny,status:406,nolog,auditlog', } end it { is_expected.to contain_file('security.conf').with_content %r{^\s+SecAuditLogRelevantStatus "\^\(\?:5\|4\(\?!01\|04\)\)"$} } it { is_expected.to contain_file('security.conf').with_content %r{^\s+SecAuditLogParts ABCDZ$} } it { is_expected.to contain_file('security.conf').with_content %r{^\s+SecAuditLogType Concurrent$} } it { is_expected.to contain_file('security.conf').with_content %r{^\s+SecAuditLogStorageDir /var/log/httpd/audit$} } it { is_expected.to contain_file('/etc/httpd/modsecurity.d/security_crs.conf').with_content %r{^\s*SecDefaultAction "phase:2,deny,status:406,nolog,auditlog"$} } it { is_expected.to contain_file('bar.conf').with( path: '/etc/httpd/modsecurity.d/activated_rules/bar.conf', target: '/tmp/foo/bar.conf', ) } end describe 'with other modsec parameters' do let :params do { manage_security_crs: false, } end it { is_expected.not_to contain_file('/etc/httpd/modsecurity.d/security_crs.conf') } end end when 'Debian' context 'on Debian based systems' do it { is_expected.to contain_apache__mod('security').with( id: 'security2_module', lib: 'mod_security2.so', ) } it { is_expected.to contain_apache__mod('unique_id_module').with( id: 'unique_id_module', lib: 'mod_unique_id.so', ) } it { is_expected.to contain_package('modsecurity-crs') } it { is_expected.to contain_file('security.conf').with( path: '/etc/apache2/mods-available/security.conf', ) } it { is_expected.to contain_file('security.conf') .with_content(%r{^\s+SecAuditLogRelevantStatus "\^\(\?:5\|4\(\?!04\)\)"$}) .with_content(%r{^\s+SecAuditLogParts ABIJDEFHZ$}) .with_content(%r{^\s+SecAuditLogType Serial$}) .with_content(%r{^\s+SecDebugLog /var/log/apache2/modsec_debug.log$}) .with_content(%r{^\s+SecAuditLog /var/log/apache2/modsec_audit.log$}) } it { is_expected.to contain_file('/etc/modsecurity').with( ensure: 'directory', path: '/etc/modsecurity', owner: 'root', group: 'root', mode: '0755' ) } it { is_expected.to contain_file('/etc/modsecurity/activated_rules').with( ensure: 'directory', path: '/etc/modsecurity/activated_rules', owner: 'www-data', group: 'www-data' ) } it { is_expected.to contain_file('/etc/modsecurity/security_crs.conf').with( path: '/etc/modsecurity/security_crs.conf', ) } if (facts[:os]['release']['major'].to_i < 18 && facts[:os]['name'] == 'Ubuntu') || (facts[:os]['release']['major'].to_i < 9 && facts[:os]['name'] == 'Debian') it { is_expected.to contain_apache__security__rule_link('base_rules/modsecurity_35_bad_robots.data') } it { is_expected.to contain_file('modsecurity_35_bad_robots.data').with( path: '/etc/modsecurity/activated_rules/modsecurity_35_bad_robots.data', target: '/usr/share/modsecurity-crs/base_rules/modsecurity_35_bad_robots.data', ) } end describe 'with parameters' do let :params do { activated_rules: [ '/tmp/foo/bar.conf', ], audit_log_relevant_status: '^(?:5|4(?!01|04))', audit_log_parts: 'ABCDZ', audit_log_type: 'Concurrent', audit_log_storage_dir: '/var/log/httpd/audit', secdefaultaction: 'deny,status:406,nolog,auditlog', } end if (facts[:os]['release']['major'].to_i < 18 && facts[:os]['name'] == 'Ubuntu') || (facts[:os]['release']['major'].to_i < 9 && facts[:os]['name'] == 'Debian') it { is_expected.to contain_file('security.conf').with_content %r{^\s+SecAuditLogRelevantStatus "\^\(\?:5\|4\(\?!01\|04\)\)"$} } it { is_expected.to contain_file('security.conf').with_content %r{^\s+SecAuditLogParts ABCDZ$} } it { is_expected.to contain_file('security.conf').with_content %r{^\s+SecAuditLogStorageDir /var/log/httpd/audit$} } it { is_expected.to contain_file('/etc/modsecurity/security_crs.conf').with_content %r{^\s*SecDefaultAction "phase:2,deny,status:406,nolog,auditlog"$} } it { is_expected.to contain_file('bar.conf').with( path: '/etc/modsecurity/activated_rules/bar.conf', target: '/tmp/foo/bar.conf', ) } end end describe 'with mod security version' do let :params do { version: 2, } end it { is_expected.to contain_apache__mod('security2') } it { is_expected.to contain_file('security.conf').with( path: '/etc/apache2/mods-available/security2.conf', ) } end end end end end end diff --git a/spec/classes/mod/status_spec.rb b/spec/classes/mod/status_spec.rb index 5f1ad0f1..f4741a99 100644 --- a/spec/classes/mod/status_spec.rb +++ b/spec/classes/mod/status_spec.rb @@ -1,356 +1,358 @@ # frozen_string_literal: true require 'spec_helper' # Helper function for testing the contents of `status.conf` # Apache < 2.4 def status_conf_spec(allow_from, extended_status, status_path) expected = "\n"\ " SetHandler server-status\n"\ " Order deny,allow\n"\ " Deny from all\n"\ " Allow from #{Array(allow_from).join(' ')}\n"\ "\n"\ "ExtendedStatus #{extended_status}\n"\ "\n"\ "\n"\ " # Show Proxy LoadBalancer status in mod_status\n"\ " ProxyStatus On\n"\ "\n" - it do + it('status conf') do is_expected.to contain_file('status.conf').with_content(expected) end end # Apache >= 2.4 def require_directives(requires) if requires == :undef " Require ip 127.0.0.1 ::1\n" elsif requires.is_a?(String) if ['', 'unmanaged'].include? requires.downcase '' else " Require #{requires}\n" end elsif requires.is_a?(Array) requires.map { |req| " Require #{req}\n" }.join('') elsif requires.is_a?(Hash) if requires.key?(:enforce) \ " \n" + \ requires[:requires].map { |req| " Require #{req}\n" }.join('') + \ " \n" else requires[:requires].map { |req| " Require #{req}\n" }.join('') end end end def status_conf_spec_require(requires, extended_status, status_path) expected = "\n"\ " SetHandler server-status\n"\ "#{require_directives(requires)}"\ "\n"\ "ExtendedStatus #{extended_status}\n"\ "\n"\ "\n"\ " # Show Proxy LoadBalancer status in mod_status\n"\ " ProxyStatus On\n"\ "\n" - it do + it('status conf require') do is_expected.to contain_file('status.conf').with_content(expected) end end describe 'apache::mod::status', type: :class do it_behaves_like 'a mod class, without including apache' context 'default configuration with parameters' do context 'on a Debian 6 OS with default params' do let :facts do { osfamily: 'Debian', operatingsystemrelease: '6', lsbdistcodename: 'squeeze', operatingsystem: 'Debian', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end it { is_expected.to contain_apache__mod('status') } status_conf_spec(['127.0.0.1', '::1'], 'On', '/server-status') it { is_expected.to contain_file('status.conf').with(ensure: 'file', path: '/etc/apache2/mods-available/status.conf') } it { is_expected.to contain_file('status.conf symlink').with(ensure: 'link', path: '/etc/apache2/mods-enabled/status.conf') } end context 'on a RedHat 6 OS with default params' do let :facts do { osfamily: 'RedHat', operatingsystemrelease: '6', operatingsystem: 'RedHat', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end it { is_expected.to contain_apache__mod('status') } status_conf_spec(['127.0.0.1', '::1'], 'On', '/server-status') it { is_expected.to contain_file('status.conf').with_path('/etc/httpd/conf.d/status.conf') } end valid_requires = { undef: :undef, empty: '', unmanaged: 'unmanaged', string: 'ip 127.0.0.1 192.168', array: [ 'ip 127.0.0.1', 'ip ::1', 'host localhost', ], hash: { requires: [ 'ip 10.1', 'host somehost', ], }, enforce: { enforce: 'all', requires: [ 'ip 127.0.0.1', 'host localhost', ], }, } valid_requires.each do |req_key, req_value| context "on a Debian 8 OS with default params and #{req_key} requires" do let :facts do { osfamily: 'Debian', operatingsystemrelease: '8', lsbdistcodename: 'squeeze', operatingsystem: 'Debian', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end let :params do { requires: req_value, } end it { is_expected.to contain_apache__mod('status') } status_conf_spec_require(req_value, 'On', '/server-status') it { is_expected.to contain_file('status.conf').with(ensure: 'file', path: '/etc/apache2/mods-available/status.conf') } it { is_expected.to contain_file('status.conf symlink').with(ensure: 'link', path: '/etc/apache2/mods-enabled/status.conf') } end context "on a RedHat 7 OS with default params and #{req_key} requires" do let :facts do { osfamily: 'RedHat', operatingsystemrelease: '7', operatingsystem: 'RedHat', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end let :params do { requires: req_value, } end it { is_expected.to contain_apache__mod('status') } status_conf_spec_require(req_value, 'On', '/server-status') it { is_expected.to contain_file('status.conf').with_path('/etc/httpd/conf.modules.d/status.conf') } end context "on a RedHat 8 OS with default params and #{req_key} requires" do let :facts do { osfamily: 'RedHat', operatingsystemrelease: '8', operatingsystem: 'RedHat', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end let :params do { requires: req_value, } end it { is_expected.to contain_apache__mod('status') } status_conf_spec_require(req_value, 'On', '/server-status') it { is_expected.to contain_file('status.conf').with_path('/etc/httpd/conf.modules.d/status.conf') } end end context "with custom parameters $allow_from => ['10.10.10.10','11.11.11.11'], $extended_status => 'Off', $status_path => '/custom-status'" do let :facts do { osfamily: 'Debian', operatingsystemrelease: '6', lsbdistcodename: 'squeeze', operatingsystem: 'Debian', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end let :params do { allow_from: ['10.10.10.10', '11.11.11.11'], extended_status: 'Off', status_path: '/custom-status', } end + it { is_expected.to compile } + status_conf_spec(['10.10.10.10', '11.11.11.11'], 'Off', '/custom-status') end context "with valid parameter type $allow_from => ['10.10.10.10']" do let :facts do { osfamily: 'Debian', operatingsystemrelease: '6', lsbdistcodename: 'squeeze', operatingsystem: 'Debian', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end let :params do { allow_from: ['10.10.10.10'] } end it 'expects to succeed array validation' do expect { is_expected.to contain_file('status.conf') }.not_to raise_error end end context "with invalid parameter type $allow_from => '10.10.10.10'" do let :facts do { osfamily: 'Debian', operatingsystemrelease: '6', operatingsystem: 'Debian', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end let :params do { allow_from: '10.10.10.10' } end it 'expects to fail array validation' do expect { is_expected.to contain_file('status.conf') }.to raise_error(Puppet::Error) end end # Only On or Off are valid options ['On', 'Off'].each do |valid_param| context "with valid value $extended_status => '#{valid_param}'" do let :facts do { osfamily: 'Debian', operatingsystemrelease: '6', lsbdistcodename: 'squeeze', operatingsystem: 'Debian', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end let :params do { extended_status: valid_param } end it 'expects to succeed regular expression validation' do expect { is_expected.to contain_file('status.conf') }.not_to raise_error end end end ['Yes', 'No'].each do |invalid_param| context "with invalid value $extended_status => '#{invalid_param}'" do let :facts do { osfamily: 'Debian', operatingsystemrelease: '6', operatingsystem: 'Debian', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end let :params do { extended_status: invalid_param } end it 'expects to fail regular expression validation' do expect { is_expected.to contain_file('status.conf') }.to raise_error(Puppet::Error) end end end end end diff --git a/spec/defines/fastcgi_server_spec.rb b/spec/defines/fastcgi_server_spec.rb index 6a0e7377..44ba4dd8 100644 --- a/spec/defines/fastcgi_server_spec.rb +++ b/spec/defines/fastcgi_server_spec.rb @@ -1,107 +1,100 @@ # frozen_string_literal: true require 'spec_helper' describe 'apache::fastcgi::server', type: :define do let :pre_condition do 'include apache' end let :title do 'www' end on_supported_os.each do |os, facts| next if facts[:os]['release']['major'] == '18.04' || facts[:os]['release']['major'] == '20.04' next if (facts[:os]['release']['major'] == '7' || facts[:os]['release']['major'] == '8') && facts[:os]['family']['RedHat'] context "on #{os} " do let :facts do facts end it { is_expected.to contain_class('apache') } it { is_expected.to contain_class('apache::mod::fastcgi') } case facts[:os]['family'] when 'RedHat' it { is_expected.to contain_file("fastcgi-pool-#{title}.conf").with( ensure: 'file', path: "/etc/httpd/conf.d/fastcgi-pool-#{title}.conf", ) } - when 'Debian' + when 'Debian', 'Gentoo' it { is_expected.to contain_file("fastcgi-pool-#{title}.conf").with( ensure: 'file', path: "/etc/apache2/conf.d/fastcgi-pool-#{title}.conf", ) } when 'FreeBSD' it { is_expected.to contain_file("fastcgi-pool-#{title}.conf").with( ensure: 'file', path: "/usr/local/etc/apache24/Includes/fastcgi-pool-#{title}.conf", ) } - when 'Gentoo' - it { - is_expected.to contain_file("fastcgi-pool-#{title}.conf").with( - ensure: 'file', - path: "/etc/apache2/conf.d/fastcgi-pool-#{title}.conf", - ) - } end describe 'os-independent items' do describe '.conf content using TCP communication' do let :params do { host: '127.0.0.1:9001', timeout: 30, flush: true, faux_path: '/var/www/php-www.fcgi', fcgi_alias: '/php-www.fcgi', file_type: 'application/x-httpd-php', pass_header: 'Authorization', } end let :expected do # rubocop:disable Layout/IndentationWidth : Changes to the indent causes test failures. 'FastCGIExternalServer /var/www/php-www.fcgi -idle-timeout 30 -flush -host 127.0.0.1:9001 -pass-header Authorization Alias /php-www.fcgi /var/www/php-www.fcgi Action application/x-httpd-php /php-www.fcgi ' # rubocop:enable Layout/IndentationWidth end it do is_expected.to contain_file('fastcgi-pool-www.conf').with_content(expected) end end describe '.conf content using socket communication' do let :params do { host: '/var/run/fcgi.sock', timeout: 30, flush: true, faux_path: '/var/www/php-www.fcgi', fcgi_alias: '/php-www.fcgi', file_type: 'application/x-httpd-php', } end let :expected do # rubocop:disable Layout/IndentationWidth : Changes to the indent causes test failures. 'FastCGIExternalServer /var/www/php-www.fcgi -idle-timeout 30 -flush -socket /var/run/fcgi.sock Alias /php-www.fcgi /var/www/php-www.fcgi Action application/x-httpd-php /php-www.fcgi ' # rubocop:enable Layout/IndentationWidth end it do is_expected.to contain_file('fastcgi-pool-www.conf').with_content(expected) end end end end end end diff --git a/spec/defines/vhost_custom_spec.rb b/spec/defines/vhost_custom_spec.rb index 007481c3..962e12da 100644 --- a/spec/defines/vhost_custom_spec.rb +++ b/spec/defines/vhost_custom_spec.rb @@ -1,109 +1,111 @@ # frozen_string_literal: true require 'spec_helper' describe 'apache::vhost::custom', type: :define do let :title do 'rspec.example.com' end let :default_params do { content: 'foobar', } end describe 'os-dependent items' do context 'on RedHat based systems' do let :default_facts do { osfamily: 'RedHat', operatingsystemrelease: '6', operatingsystem: 'RedHat', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end let(:params) { default_params } let(:facts) { default_facts } + + it { is_expected.to compile } end context 'on Debian based systems' do let :default_facts do { osfamily: 'Debian', operatingsystemrelease: '8', lsbdistcodename: 'jessie', operatingsystem: 'Debian', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end let(:params) { default_params } let(:facts) { default_facts } it { is_expected.to contain_file('apache_rspec.example.com').with( ensure: 'present', content: 'foobar', path: '/etc/apache2/sites-available/25-rspec.example.com.conf', ) } it { is_expected.to contain_file('25-rspec.example.com.conf symlink').with( ensure: 'link', path: '/etc/apache2/sites-enabled/25-rspec.example.com.conf', target: '/etc/apache2/sites-available/25-rspec.example.com.conf', ) } end context 'on FreeBSD systems' do let :default_facts do { osfamily: 'FreeBSD', operatingsystemrelease: '9', operatingsystem: 'FreeBSD', id: 'root', kernel: 'FreeBSD', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', is_pe: false, } end let(:params) { default_params } let(:facts) { default_facts } it { is_expected.to contain_file('apache_rspec.example.com').with( ensure: 'present', content: 'foobar', path: '/usr/local/etc/apache24/Vhosts/25-rspec.example.com.conf', ) } end context 'on Gentoo systems' do let :default_facts do { osfamily: 'Gentoo', operatingsystem: 'Gentoo', operatingsystemrelease: '3.16.1-gentoo', id: 'root', kernel: 'Linux', path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin', is_pe: false, } end let(:params) { default_params } let(:facts) { default_facts } it { is_expected.to contain_file('apache_rspec.example.com').with( ensure: 'present', content: 'foobar', path: '/etc/apache2/vhosts.d/25-rspec.example.com.conf', ) } end end end diff --git a/spec/unit/apache_version_spec.rb b/spec/unit/facter/util/fact_apache_version_spec.rb similarity index 100% rename from spec/unit/apache_version_spec.rb rename to spec/unit/facter/util/fact_apache_version_spec.rb diff --git a/spec/unit/provider/a2mod/gentoo_spec.rb b/spec/unit/provider/a2mod/gentoo_spec.rb index 53e1c83f..2fb48f34 100644 --- a/spec/unit/provider/a2mod/gentoo_spec.rb +++ b/spec/unit/provider/a2mod/gentoo_spec.rb @@ -1,178 +1,179 @@ # frozen_string_literal: true require 'spec_helper' provider_class = Puppet::Type.type(:a2mod).provider(:gentoo) describe provider_class do before :each do provider_class.clear end [:conf_file, :instances, :modules, :initvars, :conf_file, :clear].each do |method| it "responds to the class method #{method}" do expect(provider_class).to respond_to(method) end end describe 'when fetching modules' do let(:filetype) do double end it 'returns a sorted array of the defined parameters' do expect(filetype).to receive(:read).and_return(%(APACHE2_OPTS="-D FOO -D BAR -D BAZ"\n)) expect(provider_class).to receive(:filetype) { filetype } expect(provider_class.modules).to eq(['bar', 'baz', 'foo']) end it 'caches the module list' do expect(filetype).to receive(:read).once { %(APACHE2_OPTS="-D FOO -D BAR -D BAZ"\n) } # rubocop:disable Lint/AmbiguousBlockAssociation expect(provider_class).to receive(:filetype).once { filetype } # rubocop:disable Lint/AmbiguousBlockAssociation 2.times { expect(provider_class.modules).to eq(['bar', 'baz', 'foo']) } end it 'normalizes parameters' do expect(filetype).to receive(:read).and_return(%(APACHE2_OPTS="-D FOO -D BAR -D BAR"\n)) expect(provider_class).to receive(:filetype) { filetype } expect(provider_class.modules).to eq(['bar', 'foo']) end end describe 'when prefetching' do it 'matches providers to resources' do provider = instance_double('ssl_provider', name: 'ssl') resource = instance_double('ssl_resource') expect(resource).to receive(:provider=).with(provider) expect(provider_class).to receive(:instances) { [provider] } provider_class.prefetch('ssl' => resource) end end describe 'when flushing' do + let(:filetype) { double } + let(:info) { double } + let(:mpm) { double } + let(:ssl) { double } + before :each do - @filetype = double - allow(@filetype).to receive(:backup) - allow(provider_class).to receive(:filetype).at_least(:once) { @filetype } + allow(filetype).to receive(:backup) + allow(provider_class).to receive(:filetype).at_least(:once) { filetype } - @info = double - allow(@info).to receive(:[]).with(:name) { 'info' } - allow(@info).to receive(:provider=) + allow(info).to receive(:[]).with(:name) { 'info' } + allow(info).to receive(:provider=) - @mpm = double - allow(@mpm).to receive(:[]).with(:name) { 'mpm' } - allow(@mpm).to receive(:provider=) + allow(mpm).to receive(:[]).with(:name) { 'mpm' } + allow(mpm).to receive(:provider=) - @ssl = double - allow(@ssl).to receive(:[]).with(:name) { 'ssl' } - allow(@ssl).to receive(:provider=) + allow(ssl).to receive(:[]).with(:name) { 'ssl' } + allow(ssl).to receive(:provider=) end it 'adds modules whose ensure is present' do - expect(@filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="") } - expect(@filetype).to receive(:write).with(%(APACHE2_OPTS="-D INFO")) + expect(filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="") } + expect(filetype).to receive(:write).with(%(APACHE2_OPTS="-D INFO")) - allow(@info).to receive(:should).with(:ensure) { :present } - provider_class.prefetch('info' => @info) + allow(info).to receive(:should).with(:ensure) { :present } + provider_class.prefetch('info' => info) provider_class.flush end it 'removes modules whose ensure is present' do - expect(@filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="-D INFO") } - expect(@filetype).to receive(:write).with(%(APACHE2_OPTS="")) + expect(filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="-D INFO") } + expect(filetype).to receive(:write).with(%(APACHE2_OPTS="")) - allow(@info).to receive(:should).with(:ensure) { :absent } - allow(@info).to receive(:provider=) - provider_class.prefetch('info' => @info) + allow(info).to receive(:should).with(:ensure) { :absent } + allow(info).to receive(:provider=) + provider_class.prefetch('info' => info) provider_class.flush end it 'does not modify providers without resources' do - expect(@filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="-D INFO -D MPM") } - expect(@filetype).to receive(:write).with(%(APACHE2_OPTS="-D MPM -D SSL")) + expect(filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="-D INFO -D MPM") } + expect(filetype).to receive(:write).with(%(APACHE2_OPTS="-D MPM -D SSL")) - allow(@info).to receive(:should).with(:ensure) { :absent } - provider_class.prefetch('info' => @info) + allow(info).to receive(:should).with(:ensure) { :absent } + provider_class.prefetch('info' => info) - allow(@ssl).to receive(:should).with(:ensure) { :present } - provider_class.prefetch('ssl' => @ssl) + allow(ssl).to receive(:should).with(:ensure) { :present } + provider_class.prefetch('ssl' => ssl) provider_class.flush end it 'writes the modules in sorted order' do - expect(@filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="") } - expect(@filetype).to receive(:write).with(%(APACHE2_OPTS="-D INFO -D MPM -D SSL")) + expect(filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="") } + expect(filetype).to receive(:write).with(%(APACHE2_OPTS="-D INFO -D MPM -D SSL")) - allow(@mpm).to receive(:should).with(:ensure) { :present } - provider_class.prefetch('mpm' => @mpm) - allow(@info).to receive(:should).with(:ensure) { :present } - provider_class.prefetch('info' => @info) - allow(@ssl).to receive(:should).with(:ensure) { :present } - provider_class.prefetch('ssl' => @ssl) + allow(mpm).to receive(:should).with(:ensure) { :present } + provider_class.prefetch('mpm' => mpm) + allow(info).to receive(:should).with(:ensure) { :present } + provider_class.prefetch('info' => info) + allow(ssl).to receive(:should).with(:ensure) { :present } + provider_class.prefetch('ssl' => ssl) provider_class.flush end it 'writes the records back once' do - expect(@filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="") } - expect(@filetype).to receive(:write).once.with(%(APACHE2_OPTS="-D INFO -D SSL")) + expect(filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="") } + expect(filetype).to receive(:write).once.with(%(APACHE2_OPTS="-D INFO -D SSL")) - allow(@info).to receive(:should).with(:ensure) { :present } - provider_class.prefetch('info' => @info) + allow(info).to receive(:should).with(:ensure) { :present } + provider_class.prefetch('info' => info) - allow(@ssl).to receive(:should).with(:ensure) { :present } - provider_class.prefetch('ssl' => @ssl) + allow(ssl).to receive(:should).with(:ensure) { :present } + provider_class.prefetch('ssl' => ssl) provider_class.flush end it 'onlies modify the line containing APACHE2_OPTS' do - expect(@filetype).to receive(:read).at_least(:once) { %(# Comment\nAPACHE2_OPTS=""\n# Another comment) } - expect(@filetype).to receive(:write).once.with(%(# Comment\nAPACHE2_OPTS="-D INFO"\n# Another comment)) + expect(filetype).to receive(:read).at_least(:once) { %(# Comment\nAPACHE2_OPTS=""\n# Another comment) } + expect(filetype).to receive(:write).once.with(%(# Comment\nAPACHE2_OPTS="-D INFO"\n# Another comment)) - allow(@info).to receive(:should).with(:ensure) { :present } - provider_class.prefetch('info' => @info) + allow(info).to receive(:should).with(:ensure) { :present } + provider_class.prefetch('info' => info) provider_class.flush end it 'restores any arbitrary arguments' do - expect(@filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="-Y -D MPM -X") } - expect(@filetype).to receive(:write).once.with(%(APACHE2_OPTS="-Y -X -D INFO -D MPM")) + expect(filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="-Y -D MPM -X") } + expect(filetype).to receive(:write).once.with(%(APACHE2_OPTS="-Y -X -D INFO -D MPM")) - allow(@info).to receive(:should).with(:ensure) { :present } - provider_class.prefetch('info' => @info) + allow(info).to receive(:should).with(:ensure) { :present } + provider_class.prefetch('info' => info) provider_class.flush end it 'backups the file once if changes were made' do - expect(@filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="") } - expect(@filetype).to receive(:write).once.with(%(APACHE2_OPTS="-D INFO -D SSL")) + expect(filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="") } + expect(filetype).to receive(:write).once.with(%(APACHE2_OPTS="-D INFO -D SSL")) - allow(@info).to receive(:should).with(:ensure) { :present } - provider_class.prefetch('info' => @info) + allow(info).to receive(:should).with(:ensure) { :present } + provider_class.prefetch('info' => info) - allow(@ssl).to receive(:should).with(:ensure) { :present } - provider_class.prefetch('ssl' => @ssl) + allow(ssl).to receive(:should).with(:ensure) { :present } + provider_class.prefetch('ssl' => ssl) - expect(@filetype).to receive(:backup) + expect(filetype).to receive(:backup) provider_class.flush end it 'does not write the file or run backups if no changes were made' do - expect(@filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="-X -D INFO -D SSL -Y") } - expect(@filetype).to receive(:write).never + expect(filetype).to receive(:read).at_least(:once) { %(APACHE2_OPTS="-X -D INFO -D SSL -Y") } + expect(filetype).to receive(:write).never - allow(@info).to receive(:should).with(:ensure) { :present } - provider_class.prefetch('info' => @info) + allow(info).to receive(:should).with(:ensure) { :present } + provider_class.prefetch('info' => info) - allow(@ssl).to receive(:should).with(:ensure) { :present } - provider_class.prefetch('ssl' => @ssl) + allow(ssl).to receive(:should).with(:ensure) { :present } + provider_class.prefetch('ssl' => ssl) - expect(@filetype).to receive(:backup).never + expect(filetype).to receive(:backup).never provider_class.flush end end end diff --git a/spec/util/apache_mod_platform_support_spec.rb b/spec/util/apache_mod_platform_compatibility_spec.rb similarity index 100% rename from spec/util/apache_mod_platform_support_spec.rb rename to spec/util/apache_mod_platform_compatibility_spec.rb diff --git a/util/apache_mod_platform_support.rb b/util/apache_mod_platform_support.rb index 320142fb..5c608cf5 100644 --- a/util/apache_mod_platform_support.rb +++ b/util/apache_mod_platform_support.rb @@ -1,149 +1,149 @@ # frozen_string_literal: true require 'json' # Helper class to facilitate exclusion of tests that use an Apache MOD on platforms it isn't supported on. # All Apache MOD classes are defined under 'manifests/mod'. The exclusion should be in the format: # # @note Unsupported platforms: OS: ver, ver; OS: ver, ver, ver; OS: all' # class apache::mod::foobar { # ... # # For example: # @note Unsupported platforms: RedHat: 5, 6; Ubuntu: 14.04; SLES: all; Scientific: 11 SP1' # class apache::mod::actions { # apache::mod { 'actions': } # } # # Filtering is then performed during the test using RSpec's filtering, like so: # # describe 'auth_oidc', unless: mod_unsupported_on_platform('apache::mod::auth_openidc') do # ... # it 'applies cleanly', unless: mod_unsupported_on_platform('apache::mod::auth_openidc') do # ... class ApacheModPlatformCompatibility ERROR_MSG = { tag_parse: 'OS and version information in incorrect format:', os_parse: 'OS name is not present in metadata.json:', }.freeze def initialize @os = {} @mapping = {} @manifest_errors = [] @compatible_platform_versions = {} @mod_platform_compatibility_mapping = {} end def register_running_platform(os) @os = { family: os[:family], release: os[:release].to_i } end def generate_supported_platforms_versions metadata = JSON.parse(File.read('metadata.json')) metadata['operatingsystem_support'].each do |os| @compatible_platform_versions[os['operatingsystem'].downcase] = os['operatingsystemrelease'].map(&:to_i) end end # Class to hold the details of an error whilst parsing an unsupported tag class ManifestError attr_reader :manifest, :line_num, :error_type, :error_detail def initialize(manifest, line_num, error_type, error_detail) @manifest = manifest @line_num = line_num @error_type = error_type @error_detail = error_detail end end def print_parsing_errors return if @manifest_errors.empty? $stderr.puts "The following errors were encountered when trying to parse the 'Unsupported platforms' tag(s) in 'manifests/mod':\n" @manifest_errors.each do |manifest_error| $stderr.puts " * #{manifest_error.manifest} (line #{manifest_error.line_num}): #{ERROR_MSG[manifest_error.error_type]} #{manifest_error.error_detail}" end File.readlines('util/_resources/tag_format_help_msg.txt').each do |line| $stderr.puts line end end def valid_os?(os) - @compatible_platform_versions.keys.include? os + @compatible_platform_versions.key?(os) end def register_error(manifest, line_num, error_type, error_detail) @manifest_errors << ManifestError.new(manifest, line_num, error_type, error_detail) end def register_unsupported_platforms(manifest, line_num, mod, platforms_versions) - platforms_versions.keys.each do |os| + platforms_versions.each_key do |os| unless valid_os?(os) register_error(manifest, line_num, :os_parse, os) next end if @mod_platform_compatibility_mapping.key? mod @mod_platform_compatibility_mapping[mod].merge!(platforms_versions) else @mod_platform_compatibility_mapping[mod] = platforms_versions end end end def extract_os_ver_pairs(line) platforms_versions = {} os_ver_groups = line.delete(' ').downcase # E.g. "debian:5,6;centos:5;sles:11sp1,12;scientific:all;ubuntu:14.04,16.04" if %r{^((?:\w+:(?:(?:\d+(?:\.\d+|sp\d+)?|all),?)+;?)+)$}i.match?(os_ver_groups) os_ver_groups.split(';').each do |os_vers| os, vers = os_vers.split(':') vers.gsub!(%r{sp\d+}, '') # Remove SP ver as we cannot determine this level of granularity from values from Litmus platforms_versions[os] = vers.split(',').map(&:to_i) # 'all' will be converted to 0 end end platforms_versions end def process_line(line) data = {} return data unless %r{@note\sUnsupported\splatforms?:\s?|class\sapache::mod}i.match?(line) if (match = %r{@note\sUnsupported\splatforms?:\s?(?.*)$}i.match(line)) data[:type] = :unsupported_platform_declaration data[:value] = match[:os_vers] elsif (match = %r{class\s(?apache::mod::\w+)}i.match(line)) data[:type] = :class_declaration data[:value] = match[:mod] end data end def generate_mod_platform_exclusions Dir.glob('manifests/mod/*.pp').each do |manifest| platforms_versions = [] line_num = 0 File.readlines(manifest).each do |line| line_num += 1 data = process_line(line) next if data.empty? if data[:type] == :unsupported_platform_declaration platforms_versions = extract_os_ver_pairs(data[:value]) register_error(manifest, line_num, :tag_parse, line) if platforms_versions.empty? next elsif data[:type] == :class_declaration register_unsupported_platforms(manifest, line_num, data[:value], platforms_versions) unless platforms_versions.empty? break # Once we detect the class declaration, we can move on end end end end # Called from within the context of a test run, making use of RSpec's filtering, e.g.: # it 'should do some test', if: mod_supported_on_platform('apache::mod::foobar') def mod_supported_on_platform?(mod) return true if @mod_platform_compatibility_mapping.empty? return true unless @mod_platform_compatibility_mapping.key? mod return true unless @mod_platform_compatibility_mapping[mod].key? @os[:family] return false if @mod_platform_compatibility_mapping[mod][@os[:family]] == [0] !@mod_platform_compatibility_mapping[mod][@os[:family]].include? @os[:release] end end