-
Notifications
You must be signed in to change notification settings - Fork 271
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
Add oidc config parameters #1201
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exposing these makes sense to me. In hindsight I'm not happy with how we (I) have implemented Keycloak integration. It relies a lot on keycloak-httpd-client-install
and that's problematic. This lower level "expose the parameters" approach is IMHO better, but I have some implementation notes.
I'd prefer to avoid exposing those authorize_login_delegation
. At first I thought about a more specific Boolean $oidc
, but prefer a more generic auth parameter like Enum['internal', 'ipa', 'keycloak', 'oidc'] $auth = 'internal'
. We have places where we could then use a case
statement to handle it. This makes it obvious to users they need to select a single auth mechanism.
This is where we handle external auth on the Foreman side:
puppet-foreman/manifests/config.pp
Lines 188 to 283 in dbfdc94
if $foreman::ipa_authentication { | |
if $facts['os']['selinux']['enabled'] { | |
selboolean { ['allow_httpd_mod_auth_pam', 'httpd_dbus_sssd']: | |
persistent => true, | |
value => 'on', | |
} | |
} | |
if $foreman::ipa_manage_sssd { | |
service { 'sssd': | |
ensure => running, | |
enable => true, | |
require => Package['sssd-dbus'], | |
} | |
} | |
file { "/etc/pam.d/${foreman::pam_service}": | |
ensure => file, | |
owner => root, | |
group => root, | |
mode => '0644', | |
content => template('foreman/pam_service.erb'), | |
} | |
$http_keytab = pick($foreman::http_keytab, "${apache::conf_dir}/http.keytab") | |
exec { 'ipa-getkeytab': | |
command => "/bin/echo Get keytab \ | |
&& KRB5CCNAME=KEYRING:session:get-http-service-keytab kinit -k \ | |
&& KRB5CCNAME=KEYRING:session:get-http-service-keytab /usr/sbin/ipa-getkeytab -k ${http_keytab} -p HTTP/${facts['networking']['fqdn']} \ | |
&& kdestroy -c KEYRING:session:get-http-service-keytab", | |
creates => $http_keytab, | |
} | |
-> file { $http_keytab: | |
ensure => file, | |
owner => $apache::user, | |
mode => '0600', | |
} | |
$gssapi_local_name = bool2str($foreman::gssapi_local_name, 'On', 'Off') | |
foreman::config::apache::fragment { 'intercept_form_submit': | |
ssl_content => template('foreman/intercept_form_submit.conf.erb'), | |
} | |
foreman::config::apache::fragment { 'lookup_identity': | |
ssl_content => template('foreman/lookup_identity.conf.erb'), | |
} | |
foreman::config::apache::fragment { 'auth_gssapi': | |
ssl_content => template('foreman/auth_gssapi.conf.erb'), | |
} | |
foreman::config::apache::fragment { 'external_auth_api': | |
ssl_content => template('foreman/external_auth_api.conf.erb'), | |
} | |
if $foreman::ipa_manage_sssd { | |
$sssd = pick(fact('foreman_sssd'), {}) | |
$sssd_services = join(unique(pick($sssd['services'], []) + ['ifp']), ', ') | |
$sssd_ldap_user_extra_attrs = join(unique(pick($sssd['ldap_user_extra_attrs'], []) + ['email:mail', 'lastname:sn', 'firstname:givenname']), ', ') | |
$sssd_allowed_uids = join(unique(pick($sssd['allowed_uids'], []) + [$apache::user, 'root']), ', ') | |
$sssd_user_attributes = join(unique(pick($sssd['user_attributes'], []) + ['+email', '+firstname', '+lastname']), ', ') | |
$sssd_ifp_extra_attributes = [ | |
"set target[.=~regexp('domain/.*')]/ldap_user_extra_attrs '${sssd_ldap_user_extra_attrs}'", | |
"set target[.='sssd']/services '${sssd_services}'", | |
'set target[.=\'ifp\'] \'ifp\'', | |
"set target[.='ifp']/allowed_uids '${sssd_allowed_uids}'", | |
"set target[.='ifp']/user_attributes '${sssd_user_attributes}'", | |
] | |
$sssd_changes = $sssd_ifp_extra_attributes + ($foreman::ipa_sssd_default_realm ? { | |
undef => [], | |
default => ["set target[.='sssd']/default_domain_suffix '${$foreman::ipa_sssd_default_realm}'"], | |
}) | |
augeas { 'sssd-ifp-extra-attributes': | |
context => '/files/etc/sssd/sssd.conf', | |
changes => $sssd_changes, | |
notify => Service['sssd'], | |
} | |
} | |
foreman::settings_fragment { 'authorize_login_delegation.yaml': | |
content => template('foreman/settings-external-auth.yaml.erb'), | |
order => '02', | |
} | |
foreman::settings_fragment { 'authorize_login_delegation_api.yaml': | |
content => template('foreman/settings-external-auth-api.yaml.erb'), | |
order => '03', | |
} | |
} | |
} else { | |
$foreman_socket_override = undef | |
} |
And this is where we configure Apache:
puppet-foreman/manifests/config/apache.pp
Lines 239 to 264 in dbfdc94
if $ipa_authentication { | |
include apache::mod::authnz_pam | |
include apache::mod::auth_basic | |
include apache::mod::intercept_form_submit | |
include apache::mod::lookup_identity | |
include apache::mod::auth_gssapi | |
} elsif $keycloak { | |
include apache::mod::auth_openidc | |
# This file is generated by keycloak-httpd-client-install and that manages | |
# the content. The command would be: | |
# | |
# keycloak-httpd-client-install --app-name ${keycloak_app_name} --keycloak-server-url $KEYCLOAK_URL --keycloak-admin-username $KEYCLOAK_USER --keycloak-realm ${keycloak_realm} --keycloak-admin-realm master --keycloak-auth-role root-admin --client-type openidc --client-hostname ${servername} --protected-locations /users/extlogin | |
# | |
# If $suburi is used, --location-root should also be passed in | |
# | |
# By defining it here we avoid purging it and also tighten the | |
# permissions so the world can't read its secrets. | |
# This is functionally equivalent to apache::custom_config without content/source | |
file { "${apache::confd_dir}/${keycloak_app_name}_oidc_keycloak_${keycloak_realm}.conf": | |
ensure => file, | |
owner => 'root', | |
group => 'root', | |
mode => '0640', | |
} | |
} |
As you can see, this part relies on
keycloak-http-client-install
but I'd prefer to configure Apache's mod_auth_openidc ourselves and I think the parameters you expose can do that. You can do so by passing oidc parameters to the vhost: https://github.com/puppetlabs/puppetlabs-apache/blob/97449e4a0a9f395a2765a3100336070e8298f1dc/manifests/vhost.pp#L1649-L1653 and see https://github.com/puppetlabs/puppetlabs-apache/blob/main/types/oidcsettings.pp for the specific types. You'd probably add them very similar to vhost_https_internal_options
.
In #1172 I started some refactoring in the auth area that you might find interesting as well. In general I want to move to EPP templates instead of ERB but haven't fully pursued it.
Lastly, I would really like to see some tests before we merge this, but I can imagine you first want to get the design right to avoid rewriting those all the time.
<% if scope.lookupvar('foreman::authorize_login_delegation') -%> | ||
# The following values are used for oidc authentication | ||
:authorize_login_delegation: <%= scope.lookupvar("foreman::authorize_login_delegation") %> | ||
:authorize_login_delegation_auth_source_user_autocreate: <%= scope.lookupvar("foreman::authorize_login_delegation_auth_source_user_autocreate") %> | ||
:login_delegation_logout_url: <%= scope.lookupvar("foreman::login_delegation_logout_url") %> | ||
:oidc_jwks_url: <%= scope.lookupvar("foreman::oidc_jwks_url") %> | ||
:oidc_audience: <%= scope.lookupvar("foreman::oidc_audience") %> | ||
:oidc_issuer: <%= scope.lookupvar("foreman::oidc_issuer") %> | ||
:oidc_algorithm: <%= scope.lookupvar("foreman::oidc_algorithm") %> | ||
|
||
<% end -%> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd prefer to have this as a separate fragment. Possibly reuse the existing one: https://github.com/theforeman/puppet-foreman/blob/master/templates/settings-external-auth.yaml.erb
If it helps, https://github.com/latchset/keycloak-httpd-client-install/blob/master/templates/oidc_httpd.conf is what's used today in keycloak-httpd-client-install. Some of those values ( |
cc @adamruzicka this might interest you |
For context, this would make the sections https://docs.theforeman.org/nightly/Configuring_User_Authentication/index-katello.html#configuring-a-foreman-client-to-provide-foreman_web_UI-authentication-with-keycloak_keycloak-wildfly and https://docs.theforeman.org/nightly/Configuring_User_Authentication/index-katello.html#configuring-a-foreman-client-to-provide-hammer-cli-authentication-with-keycloak_keycloak-wildfly obsolete by adding the options to the installer command. Bonus value of putting it in the YAML files is that users can't override them at all, even if they wanted to. |
An incomplete version of what I suggested is in #1203. |
This PR adds a oidc parameters, to allow enabling oidc authentication with for example keycloak completely from config as code. The parameters get added to settings.yml config.