Skip to content

(CAT-1417) Nested require support for authz_core mod #2460

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,8 @@ RSpec/RepeatedExampleGroupDescription:
RSpec/StubbedMock:
Exclude:
- 'spec/util/apache_mod_platform_compatibility_spec.rb'

# Offense count: 1
Metrics/BlockLength:
Exclude:
- 'lib/puppet/functions/apache/authz_core_config.rb'
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
[`apache::mod::auth_mellon`]: https://forge.puppet.com/modules/puppetlabs/apache/reference#apachemodauth_mellon
[`apache::mod::authn_dbd`]: https://forge.puppet.com/modules/puppetlabs/apache/reference#apachemodauthn_dbd
[`apache::mod::authnz_ldap`]: https://forge.puppet.com/modules/puppetlabs/apache/reference#apachemodauthnz_ldap
[`apache::mod::authz_core`]: https://forge.puppet.com/modules/puppetlabs/apache/reference#apachemodauthz_core
[`apache::mod::cluster`]: https://forge.puppet.com/modules/puppetlabs/apache/reference#apachemodcluster
[`apache::mod::data]: https://forge.puppet.com/modules/puppetlabs/apache/reference#apachemoddata
[`apache::mod::disk_cache`]: https://forge.puppet.com/modules/puppetlabs/apache/reference#apachemoddisk_cache
Expand Down Expand Up @@ -157,6 +158,7 @@
[`mod_authnz_external`]: https://github.com/phokz/mod-auth-external
[`mod_auth_dbd`]: http://httpd.apache.org/docs/current/mod/mod_authn_dbd.html
[`mod_auth_mellon`]: https://github.com/UNINETT/mod_auth_mellon
[`mod_authz_core`]: https://httpd.apache.org/docs/current/mod/mod_authz_core.html
[`mod_dbd`]: http://httpd.apache.org/docs/current/mod/mod_dbd.html
[`mod_disk_cache`]: https://httpd.apache.org/docs/2.2/mod/mod_disk_cache.html
[`mod_dumpio`]: https://httpd.apache.org/docs/2.4/mod/mod_dumpio.html
Expand Down
389 changes: 268 additions & 121 deletions REFERENCE.md

Large diffs are not rendered by default.

78 changes: 78 additions & 0 deletions lib/puppet/functions/apache/authz_core_config.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# frozen_string_literal: true

# @summary
# Function to generate the authz_core configuration directives.
#
Puppet::Functions.create_function(:'apache::authz_core_config') do
# @param config
# The input as JSON format.
#
# @return
# Returns the authz_core config directives in array.
#
# @example
#
# arg = {
# require_all => {
# 'require_any' => {
# 'require' => ['user superadmin'],
# 'require_all' => {
# 'require' => ['group admins'],
# },
# },
# 'require_none' => {
# 'require' => ['group temps']
# }
# }
# }
#
# apache::bool2httpd(arg)
# returns :
# [
# " <RequireAll>",
# " <RequireAny>",
# " Require user superadmin",
# " <RequireAll>",
# " Require group admins",
# " Require ldap-group \"cn=Administrators,o=Airius\"",
# " </RequireAll>",
# " </RequireAny>",
# " <RequireNone>",
# " Require group temps",
# " Require ldap-group \"cn=Temporary Employees,o=Airius\"",
# " </RequireNone>",
# " </RequireAll>"
# ]
#
dispatch :authz_core_config do
param 'Hash', :config
return_type 'Array'
end

private

def build_directive(value)
value.split('_').map(&:capitalize).join
end

def authz_core_config(config, count = 1)
result_string = []
config.map do |key, value|
directive = build_directive(key)
if value.is_a?(Hash)
result_string << spacing("<#{directive}>", count)
result_string << authz_core_config(value, count + 1)
result_string << spacing("</#{directive}>", count)
else
value.map do |v|
result_string << spacing("#{directive} #{v}", count)
end
end
end
result_string.flatten
end

def spacing(string, count)
(' ' * count) + string
end
end
12 changes: 3 additions & 9 deletions manifests/default_mods.pp
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@
include apache::mod::filter

# authz_core is needed for 'Require' directive
::apache::mod { 'authz_core':
id => 'authz_core_module',
}
include apache::mod::authz_core

# lots of stuff seems to break without access_compat
::apache::mod { 'access_compat': }
Expand All @@ -145,17 +143,13 @@
::apache::default_mods::load { $mods: }

# authz_core is needed for 'Require' directive
::apache::mod { 'authz_core':
id => 'authz_core_module',
}
include apache::mod::authz_core

# filter is needed by mod_deflate
include apache::mod::filter
} else {
# authz_core is needed for 'Require' directive
::apache::mod { 'authz_core':
id => 'authz_core_module',
}
include apache::mod::authz_core

# filter is needed by mod_deflate
include apache::mod::filter
Expand Down
8 changes: 8 additions & 0 deletions manifests/mod/authz_core.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# @summary
# Installs `mod_authz_core`.
#
# @see https://httpd.apache.org/docs/current/mod/mod_authz_core.html for additional documentation.
#
class apache::mod::authz_core {
apache::mod { 'authz_core': }
}
127 changes: 77 additions & 50 deletions manifests/vhost.pp
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,83 @@
# Any handlers you do not set in these hashes are considered `undefined` within Puppet and
# are not added to the virtual host, resulting in the module using their default values.
#
# The `directories` param can accepts the different authentication ways, including `gssapi`, `Basic (authz_core)`,
# and others.
#
# * `gssapi` - Specifies mod_auth_gssapi parameters for particular directories in a virtual host directory
# TODO: check, if this Documentation is obsolete
#
# ```puppet
# apache::vhost { 'sample.example.net':
# docroot => '/path/to/directory',
# directories => [
# { path => '/path/to/different/dir',
# gssapi => {
# acceptor_name => '{HOSTNAME}',
# allowed_mech => ['krb5', 'iakerb', 'ntlmssp'],
# authname => 'Kerberos 5',
# authtype => 'GSSAPI',
# basic_auth => true,
# basic_auth_mech => ['krb5', 'iakerb', 'ntlmssp'],
# basic_ticket_timeout => 300,
# connection_bound => true,
# cred_store => {
# ccache => ['/path/to/directory'],
# client_keytab => ['/path/to/example.keytab'],
# keytab => ['/path/to/example.keytab'],
# },
# deleg_ccache_dir => '/path/to/directory',
# deleg_ccache_env_var => 'KRB5CCNAME',
# deleg_ccache_perms => {
# mode => '0600',
# uid => 'example-user',
# gid => 'example-group',
# },
# deleg_ccache_unique => true,
# impersonate => true,
# local_name => true,
# name_attributes => 'json',
# negotiate_once => true,
# publish_errors => true,
# publish_mech => true,
# required_name_attributes => 'auth-indicators=high',
# session_key => 'file:/path/to/example.key',
# signal_persistent_auth => true,
# ssl_only => true,
# use_s4u2_proxy => true,
# use_sessions => true,
# }
# },
# ],
# }
# ```
#
# * `Basic` - Specifies mod_authz_core parameters for particular directories in a virtual host directory
# ```puppet
# apache::vhost { 'sample.example.net':
# docroot => '/path/to/directory',
# directories => [
# {
# path => '/path/to/different/dir',
# auth_type => 'Basic',
# authz_core => {
# require_all => {
# 'require_any' => {
# 'require' => ['user superadmin'],
# 'require_all' => {
# 'require' => ['group admins', 'ldap-group "cn=Administrators,o=Airius"'],
# },
# },
# 'require_none' => {
# 'require' => ['group temps', 'ldap-group "cn=Temporary Employees,o=Airius"']
# }
# }
# }
# },
# ],
# }
# ```
#
# @param custom_fragment
# Pass a string of custom configuration directives to be placed at the end of the directory
# configuration.
Expand Down Expand Up @@ -1405,56 +1482,6 @@
# }
# ```
#
# TODO: check, if this Documentation is obsolete
# lint:ignore:parameter_documentation
# @param gssapi
# lint:endignore
# Specfies mod_auth_gssapi parameters for particular directories in a virtual host directory
# ```puppet
# apache::vhost { 'sample.example.net':
# docroot => '/path/to/directory',
# directories => [
# { path => '/path/to/different/dir',
# gssapi => {
# acceptor_name => '{HOSTNAME}',
# allowed_mech => ['krb5', 'iakerb', 'ntlmssp'],
# authname => 'Kerberos 5',
# authtype => 'GSSAPI',
# basic_auth => true,
# basic_auth_mech => ['krb5', 'iakerb', 'ntlmssp'],
# basic_ticket_timeout => 300,
# connection_bound => true,
# cred_store => {
# ccache => ['/path/to/directory'],
# client_keytab => ['/path/to/example.keytab'],
# keytab => ['/path/to/example.keytab'],
# },
# deleg_ccache_dir => '/path/to/directory',
# deleg_ccache_env_var => 'KRB5CCNAME',
# deleg_ccache_perms => {
# mode => '0600',
# uid => 'example-user',
# gid => 'example-group',
# },
# deleg_ccache_unique => true,
# impersonate => true,
# local_name => true,
# name_attributes => 'json',
# negotiate_once => true,
# publish_errors => true,
# publish_mech => true,
# required_name_attributes => 'auth-indicators=high',
# session_key => 'file:/path/to/example.key',
# signal_persistent_auth => true,
# ssl_only => true,
# use_s4u2_proxy => true,
# use_sessions => true,
# }
# },
# ],
# }
# ```
#
# @param ssl
# Enables SSL for the virtual host. SSL virtual hosts only respond to HTTPS queries.
#
Expand Down
53 changes: 53 additions & 0 deletions spec/functions/authz_core_config_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

require 'spec_helper'

describe 'apache::authz_core_config' do
let(:input1) do
{
'Require' => [
'user foo',
'user bar',
]
}
end

let(:input2) do
{
'require_all' => {
'require_any' => {
'require' => ['user superadmin'],
'require_all' => {
'require' => ['group admins', 'ldap-group "cn=Administrators,o=Airius"']
}
},
'require_none' => {
'require' => ['group temps', 'ldap-group "cn=Temporary Employees,o=Airius"']
}
}
}
end
let(:output2) do
[
' <RequireAll>',
' <RequireAny>',
' Require user superadmin',
' <RequireAll>',
' Require group admins',
' Require ldap-group "cn=Administrators,o=Airius"',
' </RequireAll>',
' </RequireAny>',
' <RequireNone>',
' Require group temps',
' Require ldap-group "cn=Temporary Employees,o=Airius"',
' </RequireNone>',
' </RequireAll>',
]
end

it { is_expected.to run.with_params(nil).and_raise_error(StandardError) }
it { is_expected.to run.with_params([]).and_raise_error(StandardError) }
it { is_expected.to run.with_params({}).and_return([]) }
it { is_expected.to run.with_params(input1).and_return([' Require user foo', ' Require user bar']) }
it { is_expected.to run.with_params(input2).and_return(output2) }
end
3 changes: 3 additions & 0 deletions templates/vhost/_authz_core.epp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<% $authz_core_config.each |$line| { -%>
<%= $line %>
<%- } -%>
3 changes: 3 additions & 0 deletions templates/vhost/_directories.erb
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,9 @@
<%- if directory['custom_fragment'] -%>
<%= directory['custom_fragment'] %>
<%- end -%>
<%- if directory['authz_core'] -%>
<%= scope.call_function('epp',["apache/vhost/_authz_core.epp", 'authz_core_config' => scope.call_function('apache::authz_core_config', directory['authz_core'])]) -%>
<%- end -%>
<%- if directory['gssapi'] -%>
<%= scope.call_function('epp',["apache/vhost/_gssapi.epp", directory['gssapi']]) -%>
<%- end -%>
Expand Down