Skip to content

Commit

Permalink
Add mod_auth_openidc to the supported modules
Browse files Browse the repository at this point in the history
  • Loading branch information
asieraguado committed Dec 19, 2019
1 parent ebfb108 commit 9f7f38f
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 0 deletions.
13 changes: 13 additions & 0 deletions manifests/mod/auth_openidc.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# @summary
# Installs and configures `mod_auth_openidc`.
#
# @see https://github.com/zmartzone/mod_auth_openidc for additional documentation.
#
class apache::mod::auth_openidc (
) inherits ::apache::params {

include ::apache
include ::apache::mod::authz_user
apache::mod { 'auth_openidc': }

}
5 changes: 5 additions & 0 deletions manifests/params.pp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@
'auth_kerb' => 'mod_auth_kerb',
'auth_gssapi' => 'mod_auth_gssapi',
'auth_mellon' => 'mod_auth_mellon',
'auth_openidc' => 'mod_auth_openidc',
'authnz_ldap' => $::apache::version::distrelease ? {
'7' => 'mod_ldap',
default => 'mod_authz_ldap',
Expand Down Expand Up @@ -343,6 +344,7 @@
$mod_packages = {
'auth_cas' => 'libapache2-mod-auth-cas',
'auth_kerb' => 'libapache2-mod-auth-kerb',
'auth_openidc' => 'libapache2-mod-auth-openidc',
'auth_gssapi' => 'libapache2-mod-auth-gssapi',
'auth_mellon' => 'libapache2-mod-auth-mellon',
'authnz_pam' => 'libapache2-mod-authnz-pam',
Expand Down Expand Up @@ -376,6 +378,7 @@
$mod_packages = {
'auth_cas' => 'libapache2-mod-auth-cas',
'auth_kerb' => 'libapache2-mod-auth-kerb',
'auth_openidc' => 'libapache2-mod-auth-openidc',
'auth_gssapi' => 'libapache2-mod-auth-gssapi',
'auth_mellon' => 'libapache2-mod-auth-mellon',
'authnz_pam' => 'libapache2-mod-authnz-pam',
Expand Down Expand Up @@ -403,6 +406,7 @@
$mod_packages = {
'auth_cas' => 'libapache2-mod-auth-cas',
'auth_kerb' => 'libapache2-mod-auth-kerb',
'auth_openidc' => 'libapache2-mod-auth-openidc',
'auth_gssapi' => 'libapache2-mod-auth-gssapi',
'auth_mellon' => 'libapache2-mod-auth-mellon',
'authnz_pam' => 'libapache2-mod-authnz-pam',
Expand Down Expand Up @@ -578,6 +582,7 @@
# NOTE: not sure where the shibboleth should come from
'auth_kerb' => 'www/mod_auth_kerb2',
'auth_gssapi' => 'www/mod_auth_gssapi',
'auth_openidc'=> 'www/mod_auth_openidc',
'fcgid' => 'www/mod_fcgid',
'passenger' => 'www/rubygem-passenger',
'perl' => 'www/mod_perl2',
Expand Down
23 changes: 23 additions & 0 deletions manifests/vhost.pp
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,12 @@
# this lets you define configuration variables inside a vhost using [`Define`](https://httpd.apache.org/docs/2.4/mod/core.html#define),
# these can then be used to replace configuration values. All Defines are Undefined at the end of the VirtualHost.
#
# @param auth_oidc
# Enable `mod_auth_openidc` parameters for OpenID Connect authentication.
#
# @param oidc_settings
# An Apache::OIDCSettings Struct containing (mod_auth_openidc settings)[https://github.com/zmartzone/mod_auth_openidc/blob/master/auth_openidc.conf].
#
define apache::vhost(
Variant[Boolean,String] $docroot,
$manage_docroot = true,
Expand Down Expand Up @@ -1855,6 +1861,8 @@
Optional[Enum['On', 'on', 'Off', 'off', 'DNS', 'dns']] $use_canonical_name = undef,
Optional[Variant[String,Array[String]]] $comment = undef,
Hash $define = {},
Boolean $auth_oidc = false,
Optional[Apache::OIDCSettings] $oidc_settings = undef,
) {

# The base class must be included first because it is used by parameter defaults
Expand Down Expand Up @@ -1901,6 +1909,10 @@
include ::apache::mod::auth_kerb
}

if $auth_oidc and $ensure == 'present' {
include ::apache::mod::auth_openidc
}

if $virtual_docroot {
include ::apache::mod::vhost_alias
}
Expand Down Expand Up @@ -2716,6 +2728,17 @@
}
}

# Template uses:
# - $auth_oidc
# - $oidc_settings
if $auth_oidc {
concat::fragment { "${name}-auth_oidc":
target => "${priority_real}${filename}.conf",
order => 360,
content => template('apache/vhost/_auth_oidc.erb'),
}
}

# Template uses:
# - $shib_compat_valid_user
if $shibboleth_enabled {
Expand Down
89 changes: 89 additions & 0 deletions spec/classes/mod/auth_openidc_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
require 'spec_helper'

describe 'apache::mod::auth_openidc', type: :class do
it_behaves_like 'a mod class, without including apache'

context 'default configuration with parameters' do
context 'on a Debian OS', :compile do
let :facts do
{
id: 'root',
kernel: 'Linux',
lsbdistcodename: 'jessie',
osfamily: 'Debian',
operatingsystem: 'Debian',
operatingsystemrelease: '8',
path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
is_pe: false,
}
end

it { is_expected.to contain_class('apache::params') }
it { is_expected.to contain_apache__mod('auth_openidc') }
it { is_expected.to contain_package('libapache2-mod-auth-openidc') }
end
context 'on a RedHat OS', :compile do
let :facts do
{
id: 'root',
kernel: 'Linux',
osfamily: 'RedHat',
operatingsystem: 'RedHat',
operatingsystemrelease: '6',
path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
is_pe: false,
}
end

it { is_expected.to contain_class('apache::params') }
it { is_expected.to contain_apache__mod('auth_openidc') }
it { is_expected.to contain_package('mod_auth_openidc') }
end
context 'on a FreeBSD OS', :compile do
let :facts do
{
id: 'root',
kernel: 'FreeBSD',
osfamily: 'FreeBSD',
operatingsystem: 'FreeBSD',
operatingsystemrelease: '9',
path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
is_pe: false,
}
end

it { is_expected.to contain_class('apache::params') }
it { is_expected.to contain_apache__mod('auth_openidc') }
it { is_expected.to contain_package('www/mod_auth_openidc') }
end
end
context 'overriding mod_packages' do
context 'on a RedHat OS', :compile do
let :facts do
{
id: 'root',
kernel: 'Linux',
osfamily: 'RedHat',
operatingsystem: 'RedHat',
operatingsystemrelease: '6',
path: '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin',
is_pe: false,
}
end
let :pre_condition do
<<-MANIFEST
include apache::params
class { 'apache':
mod_packages => merge($::apache::params::mod_packages, {
'auth_openidc' => 'httpd24-mod_auth_openidc',
})
}
MANIFEST
end

it { is_expected.to contain_apache__mod('auth_openidc') }
it { is_expected.to contain_package('httpd24-mod_auth_openidc') }
it { is_expected.not_to contain_package('mod_auth_openidc') }
end
end
end
43 changes: 43 additions & 0 deletions spec/defines/vhost_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,14 @@
'max_keepalive_requests' => '1000',
'protocols' => ['h2', 'http/1.1'],
'protocols_honor_order' => true,
'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' },
}
end

Expand Down Expand Up @@ -1378,6 +1386,41 @@
content: %r{^\s+PassengerLveMinUid\s500$},
)
}
it {
is_expected.to contain_concat__fragment('rspec.example.com-auth_oidc').with(
content: %r{^\s+OIDCProviderMetadataURL\shttps:\/\/login.example.com\/\.well-known\/openid-configuration$},
)
}
it {
is_expected.to contain_concat__fragment('rspec.example.com-auth_oidc').with(
content: %r{^\s+OIDCClientID\stest$},
)
}
it {
is_expected.to contain_concat__fragment('rspec.example.com-auth_oidc').with(
content: %r{^\s+OIDCRedirectURI\shttps:\/\/login\.example.com\/redirect_uri$},
)
}
it {
is_expected.to contain_concat__fragment('rspec.example.com-auth_oidc').with(
content: %r{^\s+OIDCProviderTokenEndpointAuth\sclient_secret_basic$},
)
}
it {
is_expected.to contain_concat__fragment('rspec.example.com-auth_oidc').with(
content: %r{^\s+OIDCRemoteUserClaim\ssub$},
)
}
it {
is_expected.to contain_concat__fragment('rspec.example.com-auth_oidc').with(
content: %r{^\s+OIDCClientSecret\saae053a9-4abf-4824-8956-e94b2af335c8$},
)
}
it {
is_expected.to contain_concat__fragment('rspec.example.com-auth_oidc').with(
content: %r{^\s+OIDCCryptoPassphrase\s4ad1bb46-9979-450e-ae58-c696967df3cd$},
)
}
end
context 'vhost with multiple ip addresses' do
let :params do
Expand Down
5 changes: 5 additions & 0 deletions templates/vhost/_auth_oidc.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<% if @auth_oidc -%>
<% @oidc_settings.each do |key, value| %>
OIDC<%= key %> <%= value -%>
<% end %>
<% end -%>
112 changes: 112 additions & 0 deletions types/oidcsettings.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# https://github.com/zmartzone/mod_auth_openidc/blob/master/auth_openidc.conf
type Apache::OIDCSettings = Struct[
{
Optional['RedirectURI'] => Variant[Stdlib::HTTPSUrl,Stdlib::HttpUrl],
Optional['CryptoPassphrase'] => String,
Optional['MetadataDir'] => String,
Optional['ProviderMetadataURL'] => Stdlib::HTTPSUrl,
Optional['ProviderIssuer'] => String,
Optional['ProviderAuthorizationEndpoint'] => Stdlib::HTTPSUrl,
Optional['ProviderJwksUri'] => Stdlib::HTTPSUrl,
Optional['ProviderTokenEndpoint'] => Stdlib::HTTPSUrl,
Optional['ProviderTokenEndpointAuth'] => Enum['client_secret_basic','client_secret_post','client_secret_jwt','private_key_jwt','none'],
Optional['ProviderTokenEndpointParams'] => Pattern['/^[A-Za-z0-9\-\._%]+=[A-Za-z0-9\-\._%]+(&[A-Za-z0-9\-\._%]+=[A-Za-z0-9\-\._%]+)*$/'],
Optional['ProviderUserInfoEndpoint'] => Stdlib::HTTPSUrl,
Optional['ProviderCheckSessionIFrame'] => Stdlib::HTTPSUrl,
Optional['ProviderEndSessionEndpoint'] => Stdlib::HTTPSUrl,
Optional['ProviderRevocationEndpoint'] => Stdlib::HTTPSUrl,
Optional['ProviderBackChannelLogoutSupported'] => Enum['On','Off'],
Optional['ProviderRegistrationEndpointJson'] => String,
Optional['Scope'] => Pattern['/^[A-Za-z0-9\-\._\s]+$/'],
Optional['AuthRequestParams'] => Pattern['/^[A-Za-z0-9\-\._%]+=[A-Za-z0-9\-\._%]+(&[A-Za-z0-9\-\._%]+=[A-Za-z0-9\-\._%]+)*$/'],
Optional['SSLValidateServer'] => Enum['On','Off'],
Optional['UserInfoRefreshInterval'] => Integer,
Optional['JWKSRefreshInterval'] => Interger,
Optional['UserInfoTokenMethod'] => Enum['authz_header','post_param'],
Optional['ProviderAuthRequestMethod'] => Enum['GET','POST'],
Optional['PublicKeyFiles'] => String,
Optional['ResponseType'] => Enum['code','id_token','id_token token','code id_token','code token','code id_token token'],
Optional['ResponseMode'] => Enum['fragment','query','form_post'],
Optional['ClientID'] => String,
Optional['ClientSecret'] => String,
Optional['ClientTokenEndpointCert'] => String,
Optional['ClientTokenEndpointKey'] => String,
Optional['ClientName'] => String,
Optional['ClientContact'] => String,
Optional['PKCDMethod'] => Enum['plain','S256','referred_tb'],
Optional['TokenBindingPolicy'] => Enum['disabled','optional','required','enforced'],
Optional['ClientJwksUri'] => Stdlib::HTTPSUrl,
Optional['IDTokenSignedResponseAlg'] => Enum['RS256','RS384','RS512','PS256','PS384','PS512','HS256','HS384','HS512','ES256','ES384','ES512'],
Optional['IDTokenEncryptedResponseAlg'] => Enum['RSA1_5','A128KW','A256KW','RSA-OAEP'],
Optional['IDTokenEncryptedResponseAlg'] => Enum['A128CBC-HS256','A256CBC-HS512','A256GCM'],
Optional['UserInfoSignedResposeAlg'] => Enum['RS256','RS384','RS512','PS256','PS384','PS512','HS256','HS384','HS512','ES256','ES384','ES512'],
Optional['UserInfoEncryptedResponseAlg'] => Enum['RSA1_5','A128KW','A256KW','RSA-OAEP'],
Optional['UserInfoEncryptedResponseEnc'] => Enum['A128CBC-HS256','A256CBC-HS512','A256GCM'],
Optional['OAuthServerMetadataURL'] => Stdlib::HTTPSUrl,
Optional['AuthIntrospectionEndpoint'] => Stdlib::HTTPSUrl,
Optional['OAuthClientID'] => String,
Optional['OAuthClientSecret'] => String,
Optional['OAuthIntrospectionEndpointAuth'] => Enum['client_secret_basic','client_secret_post','client_secret_jwt','private_key_jwt','bearer_access_token','none'],
Optional['OAuthIntrospectionClientAuthBearerToken'] => String,
Optional['OAuthIntrospectionEndpointCert'] => String,
Optional['OAuthIntrospectionEndpointKey'] => String,
Optional['OAuthIntrospectionEndpointMethod'] => Enum['POST','GET'],
Optional['OAuthIntrospectionEndpointParams'] => Pattern['/^[A-Za-z0-9\-\._%]+=[A-Za-z0-9\-\._%]+(&[A-Za-z0-9\-\._%]+=[A-Za-z0-9\-\._%]+)*$/'],
Optional['OAuthIntrospectionTokenParamName'] => String,
Optional['OAuthTokenExpiryClaim'] => Pattern['/^[A-Za-z0-9\-\._]+\s(absolute|relative)\s(mandatory|optional)$/'],
Optional['OAuthSSLValidateServer'] => Enum['On','Off'],
Optional['OAuthVerifySharedKeys'] => String,
Optional['OAuthVerifyCertFiles'] => String,
Optional['OAuthVerifyJwksUri'] => Stdlib::HTTPSUrl,
Optional['OAuthRemoteUserClaim'] => String,
Optional['OAuthAcceptTokenAs'] => Pattern['/^((header|post|query|cookie\:[A-Za-z0-9\-\._]+|basic)\s?)+$/'],
Optional['OAuthAccessTokenBindingPolicy'] => Enum['disabled','optional','required','enforced'],
Optional['Cookie'] => String,
Optional['SessionCookieChunkSize'] => Integer,
Optional['CookieHTTPOnly'] => Enum['On','Off'],
Optional['CookieSameSite'] => Enum['On','Off'],
Optional['PassCookies'] => String,
Optional['StripCookies'] => String,
Optional['StateMaxNumberOfCookies'] => Pattern['/^[0-9]+\s(false|true)$/'],
Optional['SessionInactivityTimeout'] => Integer,
Optional['SessionMaxDuration'] => Integer,
Optional['SessionType'] => Pattern['/^(server-cache(:persistent)?|client-cookie(:persistent)?)$/'],
Optional['SessionCacheFallbackToCookie'] => Enum['On','Off'],
Optional['CacheType'] => Enum['shm','memcache','file','redis'],
Optional['CacheEncrypt'] => Enum['On','Off'],
Optional['CacheShmMax'] => Integer,
Optional['CacheShmEntrySizeMax'] => Integer,
Optional['CacheFileCleanInterval'] => Integer,
Optional['MemCacheServers'] => String,
Optional['RedisCacheServer'] => String,
Optional['RedisCachePassword'] => String,
Optional['DiscoverURL'] => Variant[Stdlib::HTTPSUrl,Stdlib::HttpUrl],
Optional['HTMLErrorTemplate'] => String,
Optional['DefaultURL'] => Variant[Stdlib::HTTPSUrl,Stdlib::HttpUrl],
Optional['PathScope'] => Pattern['/^[A-Za-z0-9\-\._\s]+$/'],
Optional['PathAuthRequestParams'] => Pattern['/^[A-Za-z0-9\-\._%]+=[A-Za-z0-9\-\._%]+(&[A-Za-z0-9\-\._%]+=[A-Za-z0-9\-\._%]+)*$/'],
Optional['IDTokenIatSlack'] => Integer,
Optional['ClaimPrefix'] => String,
Optional['ClaimDelimiter'] => Pattern['/^.$/'],
Optional['RemoteUserClaim'] => String,
Optional['PassIDTokenAs'] => Pattern['/^((claims|payload|serialized)\s?)+$/'],
Optional['PassUserInfoAs'] => Pattern['/^((claims|json|jwt)\s?)+$/'],
Optional['PassClaimsAs'] => Enum['none','headers','environment','both'],
Optional['AuthNHeader'] => String,
Optional['HTTPTimeoutLong'] => Integer,
Optional['HTTPTimeoutShort'] => Integer,
Optional['StateTimeout'] => Integer,
Optional['ScrubRequestHeaders'] => Enum['On','Off'],
Optional['OutgoingProxy'] => String,
Optional['UnAuthAction'] => Enum['auth','pass','401','410'],
Optional['UnAuthzAction'] => Enum['401','403','auth'],
Optional['PreservePost'] => Enum['On','Off'],
Optional['PassRefreshToken'] => Enum['On','Off'],
Optional['RequestObject'] => String,
Optional['ProviderMetadataRefreshInterval'] => Integer,
Optional['InfoHook'] => Pattern['/^((iat|access_token|access_token_expires|id_token|userinfo|refresh_token|session)\s?)+$/'],
Optional['BlackListedClaims'] => String,
Optional['WhiteListedClaims'] => String,
Optional['RefreshAccessTokenBeforeExpiry'] => Pattern['/^[0-9]+(\slogout_on_error)?$/'],
}
]

0 comments on commit 9f7f38f

Please sign in to comment.