From 2f2183e9d634c4d46834472ba221969ca4a88052 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Tue, 25 Jan 2022 09:58:14 +0900 Subject: [PATCH] Accept system scope credentials for Keystone API request This change is the first step to support secure RBAC and allows usage of system scope credentials for Keystone API request. This change covers the following three items. - assignment of system scope roles to system user - credential parameters for authtoken middleware - credential parameters for s3token middleware - credential parameters for ceilometer middleware Depends-on: https://review.opendev.org/804325 Change-Id: I1923a5aed12a503f450c7d2e4a7784e4746fb46c --- manifests/keystone/auth.pp | 18 +++++++++++ manifests/proxy/authtoken.pp | 32 +++++++++++++------ manifests/proxy/ceilometer.pp | 30 ++++++++++++----- manifests/proxy/s3token.pp | 30 ++++++++++++----- ...ystem_scope-keystone-30d9867d48b6ab11.yaml | 16 ++++++++++ spec/classes/swift_keystone_auth_spec.rb | 9 ++++++ spec/classes/swift_proxy_authtoken_spec.rb | 28 ++++++++++++---- spec/classes/swift_proxy_ceilometer_spec.rb | 18 +++++++++-- spec/classes/swift_proxy_s3token_spec.rb | 20 +++++++++--- 9 files changed, 163 insertions(+), 38 deletions(-) create mode 100644 releasenotes/notes/system_scope-keystone-30d9867d48b6ab11.yaml diff --git a/manifests/keystone/auth.pp b/manifests/keystone/auth.pp index 3a2de7fa..c93f7e8b 100644 --- a/manifests/keystone/auth.pp +++ b/manifests/keystone/auth.pp @@ -19,6 +19,18 @@ # (Optional) The tenant to use for the swift service user # Defaults to 'services' # +# [*roles*] +# (Optional) List of roles assigned to swift user. +# Defaults to ['admin'] +# +# [*system_scope*] +# (Optional) Scope for system operations. +# Defaults to 'all' +# +# [*system_roles*] +# (Optional) List of system roles assigned to swift user. +# Defaults to [] +# # [*email*] # (Optional) The email address for the swift service user # Defaults to 'swift@localhost' @@ -99,6 +111,9 @@ class swift::keystone::auth( $auth_name = 'swift', $password = undef, $tenant = 'services', + $roles = ['admin'], + $system_scope = 'all', + $system_roles = [], $email = 'swift@localhost', $region = 'RegionOne', $operator_roles = ['admin', 'SwiftOperator'], @@ -155,6 +170,9 @@ Please set password parameter') password => $password_real, email => $email, tenant => $tenant, + roles => $roles, + system_scope => $system_scope, + system_roles => $system_roles, public_url => $public_url, admin_url => $admin_url, internal_url => $internal_url, diff --git a/manifests/proxy/authtoken.pp b/manifests/proxy/authtoken.pp index c806f553..558abfbb 100644 --- a/manifests/proxy/authtoken.pp +++ b/manifests/proxy/authtoken.pp @@ -29,6 +29,10 @@ # (Optional) The name of the service user # Defaults to 'swift' # +# [*user_domain_id*] +# (Optional) id of domain for $username +# Defaults to 'default' +# # [*password*] # (Optional) The password for the user # Defaults to 'password' @@ -41,9 +45,9 @@ # (Optional) id of domain for $project_name # Defaults to 'default' # -# [*user_domain_id*] -# (Optional) id of domain for $username -# Defaults to 'default' +# [*system_scope*] +# (Optional) Scope for system operations +# Defaults to $::os_service_default # # [*region_name*] # (Optional) The region in which the identity server can be found. @@ -105,11 +109,12 @@ class swift::proxy::authtoken( $www_authenticate_uri = 'http://127.0.0.1:5000', $auth_url = 'http://127.0.0.1:5000', $auth_type = 'password', - $project_domain_id = 'default', - $user_domain_id = 'default', - $project_name = 'services', $username = 'swift', + $user_domain_id = 'default', $password = undef, + $project_name = 'services', + $project_domain_id = 'default', + $system_scope = $::os_service_default, $region_name = $::os_service_default, $include_service_catalog = false, $service_token_roles = $::os_service_default, @@ -142,17 +147,26 @@ Please set password parameter') $auth_type_real = $auth_type } + if is_service_default($system_scope) { + $project_name_real = $project_name + $project_domain_id_real = $project_domain_id + } else { + $project_name_real = $::os_service_default + $project_domain_id_real = $::os_service_default + } + swift_proxy_config { 'filter:authtoken/log_name': value => 'swift'; 'filter:authtoken/paste.filter_factory': value => 'keystonemiddleware.auth_token:filter_factory'; 'filter:authtoken/www_authenticate_uri': value => $www_authenticate_uri; 'filter:authtoken/auth_url': value => $auth_url; 'filter:authtoken/auth_type': value => $auth_type_real; - 'filter:authtoken/project_domain_id': value => $project_domain_id; - 'filter:authtoken/user_domain_id': value => $user_domain_id; - 'filter:authtoken/project_name': value => $project_name; 'filter:authtoken/username': value => $username; + 'filter:authtoken/user_domain_id': value => $user_domain_id; 'filter:authtoken/password': value => $password_real, secret => true; + 'filter:authtoken/project_name': value => $project_name_real; + 'filter:authtoken/project_domain_id': value => $project_domain_id_real; + 'filter:authtoken/system_scope': value => $system_scope; 'filter:authtoken/region_name': value => $region_name; 'filter:authtoken/delay_auth_decision': value => $delay_auth_decision; 'filter:authtoken/cache': value => $cache; diff --git a/manifests/proxy/ceilometer.pp b/manifests/proxy/ceilometer.pp index 46995340..44e429dd 100644 --- a/manifests/proxy/ceilometer.pp +++ b/manifests/proxy/ceilometer.pp @@ -59,14 +59,18 @@ # (Optional) name of domain for $project_name # Defaults to 'default' # -# [*user_domain_name*] -# (Optional) name of domain for $username -# Defaults to 'default' +# [*system_scope*] +# (Optional) Scope for system operations +# Defaults to $::os_service_default # # [*username*] # (Optional) The name of the service user # Defaults to 'swift' # +# [*user_domain_name*] +# (Optional) name of domain for $username +# Defaults to 'default' +# # [*password*] # (Optional) The password for the user # Defaults to 'password' @@ -129,10 +133,11 @@ class swift::proxy::ceilometer( $ignore_projects = ['services'], $auth_url = 'http://127.0.0.1:5000', $auth_type = 'password', - $project_domain_name = 'Default', - $user_domain_name = 'Default', $project_name = 'services', + $project_domain_name = 'Default', + $system_scope = $::os_service_default, $username = 'swift', + $user_domain_name = 'Default', $password = undef, $region_name = $::os_service_default, $notification_ssl_ca_file = $::os_service_default, @@ -169,6 +174,14 @@ Please set password parameter') $password_real = $password } + if is_service_default($system_scope) { + $project_name_real = $project_name + $project_domain_name_real = $project_domain_name + } else { + $project_name_real = $::os_service_default + $project_domain_name_real = $::os_service_default + } + swift_proxy_config { 'filter:ceilometer/topic': value => $topic; 'filter:ceilometer/driver': value => $driver; @@ -179,10 +192,11 @@ Please set password parameter') 'filter:ceilometer/ignore_projects': value => $ignore_projects; 'filter:ceilometer/auth_url': value => $auth_url; 'filter:ceilometer/auth_type': value => $auth_type; - 'filter:ceilometer/project_domain_name': value => $project_domain_name; - 'filter:ceilometer/user_domain_name': value => $user_domain_name; - 'filter:ceilometer/project_name': value => $project_name; + 'filter:ceilometer/project_name': value => $project_name_real; + 'filter:ceilometer/project_domain_name': value => $project_domain_name_real; + 'filter:ceilometer/system_scope': value => $system_scope; 'filter:ceilometer/username': value => $username; + 'filter:ceilometer/user_domain_name': value => $user_domain_name; 'filter:ceilometer/password': value => $password_real, secret => true; 'filter:ceilometer/region_name': value => $region_name; } diff --git a/manifests/proxy/s3token.pp b/manifests/proxy/s3token.pp index dbe32290..09da851b 100644 --- a/manifests/proxy/s3token.pp +++ b/manifests/proxy/s3token.pp @@ -45,6 +45,11 @@ # The name of the service user # Defaults to swift # +# [*user_domain_id*] +# (Optional) Keystone credentials used for secret caching +# id of domain for $username +# Defaults to default +# # [*password*] # (Optional) Keystone credentials used for secret caching # The password for the user @@ -60,10 +65,9 @@ # id of domain for $project_name # Defaults to default # -# [*user_domain_id*] -# (Optional) Keystone credentials used for secret caching -# id of domain for $username -# Defaults to default +# [*system_scope*] +# (Optional) Scope for system operations +# Defaults to $::os_service_default # # == Dependencies # @@ -86,10 +90,11 @@ class swift::proxy::s3token( $auth_url = 'http://127.0.0.1:5000', $auth_type = 'password', $username = 'swift', + $user_domain_id = 'default', $password = undef, $project_name = 'services', $project_domain_id = 'default', - $user_domain_id = 'default' + $system_scope = $::os_service_default, ) { include swift::deps @@ -102,6 +107,14 @@ Please set password parameter') $password_real = $password } + if is_service_default($system_scope) { + $project_name_real = $project_name + $project_domain_id_real = $project_domain_id + } else { + $project_name_real = $::os_service_default + $project_domain_id_real = $::os_service_default + } + swift_proxy_config { 'filter:s3token/use': value => 'egg:swift#s3token'; 'filter:s3token/auth_uri': value => $auth_uri; @@ -112,9 +125,10 @@ Please set password parameter') 'filter:s3token/auth_url': value => $auth_url; 'filter:s3token/auth_type': value => $auth_type; 'filter:s3token/username': value => $username; - 'filter:s3token/password': value => $password_real, secret => true; - 'filter:s3token/project_name': value => $project_name; - 'filter:s3token/project_domain_id': value => $project_domain_id; 'filter:s3token/user_domain_id': value => $user_domain_id; + 'filter:s3token/password': value => $password_real, secret => true; + 'filter:s3token/project_name': value => $project_name_real; + 'filter:s3token/project_domain_id': value => $project_domain_id_real; + 'filter:s3token/system_scope': value => $system_scope; } } diff --git a/releasenotes/notes/system_scope-keystone-30d9867d48b6ab11.yaml b/releasenotes/notes/system_scope-keystone-30d9867d48b6ab11.yaml new file mode 100644 index 00000000..e92aa8c8 --- /dev/null +++ b/releasenotes/notes/system_scope-keystone-30d9867d48b6ab11.yaml @@ -0,0 +1,16 @@ +--- +features: + - | + The ``system_scope`` parameter has been added to the following classes. + + - ``swift::proxy::authtoken`` + - ``swift::proxy::ceilometer`` + - ``swift::proxy::s3token`` + + - | + The ``swift::keystone::auth`` class now supports customizing roles + assigned to the swift service user. + + - | + The ``swift::keystone::auth`` class now supports defining assignmet of + system-scoped roles to the swift service user. diff --git a/spec/classes/swift_keystone_auth_spec.rb b/spec/classes/swift_keystone_auth_spec.rb index 5fd233c9..d8ca42c7 100644 --- a/spec/classes/swift_keystone_auth_spec.rb +++ b/spec/classes/swift_keystone_auth_spec.rb @@ -23,6 +23,9 @@ describe 'swift::keystone::auth' do :password => 'swift_password', :email => 'swift@localhost', :tenant => 'services', + :roles => ['admin'], + :system_scope => 'all', + :system_roles => [], :public_url => 'http://127.0.0.1:8080/v1/AUTH_%(tenant_id)s', :internal_url => 'http://127.0.0.1:8080/v1/AUTH_%(tenant_id)s', :admin_url => 'http://127.0.0.1:8080', @@ -55,6 +58,9 @@ describe 'swift::keystone::auth' do :auth_name => 'alt_swift', :email => 'alt_swift@alt_localhost', :tenant => 'alt_service', + :roles => ['admin', 'service'], + :system_scope => 'alt_all', + :system_roles => ['admin', 'member', 'reader'], :configure_endpoint => false, :configure_s3_endpoint => false, :configure_user => false, @@ -85,6 +91,9 @@ describe 'swift::keystone::auth' do :password => 'swift_password', :email => 'alt_swift@alt_localhost', :tenant => 'alt_service', + :roles => ['admin', 'service'], + :system_scope => 'alt_all', + :system_roles => ['admin', 'member', 'reader'], :public_url => 'https://10.10.10.10:80', :internal_url => 'http://10.10.10.11:81', :admin_url => 'http://10.10.10.12:81', diff --git a/spec/classes/swift_proxy_authtoken_spec.rb b/spec/classes/swift_proxy_authtoken_spec.rb index 48bf12a8..13f62f6e 100644 --- a/spec/classes/swift_proxy_authtoken_spec.rb +++ b/spec/classes/swift_proxy_authtoken_spec.rb @@ -8,11 +8,12 @@ describe 'swift::proxy::authtoken' do it { is_expected.to contain_swift_proxy_config('filter:authtoken/www_authenticate_uri').with_value('http://127.0.0.1:5000') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/auth_url').with_value('http://127.0.0.1:5000') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/auth_type').with_value('password') } - it { is_expected.to contain_swift_proxy_config('filter:authtoken/project_domain_id').with_value('default') } - it { is_expected.to contain_swift_proxy_config('filter:authtoken/user_domain_id').with_value('default') } - it { is_expected.to contain_swift_proxy_config('filter:authtoken/project_name').with_value('services') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/username').with_value('swift') } + it { is_expected.to contain_swift_proxy_config('filter:authtoken/user_domain_id').with_value('default') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/password').with_value('password').with_secret(true) } + it { is_expected.to contain_swift_proxy_config('filter:authtoken/project_name').with_value('services') } + it { is_expected.to contain_swift_proxy_config('filter:authtoken/project_domain_id').with_value('default') } + it { is_expected.to contain_swift_proxy_config('filter:authtoken/system_scope').with_value('') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/region_name').with_value('') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/delay_auth_decision').with_value('1') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/cache').with_value('swift.cache') } @@ -27,9 +28,9 @@ describe 'swift::proxy::authtoken' do describe "when overriding parameters" do let :params do { - :project_name => 'admin', :username => 'swiftuser', :password => 'swiftpassword', + :project_name => 'admin', :region_name => 'region2', :cache => 'foo', :delay_auth_decision => '0', @@ -45,11 +46,12 @@ describe 'swift::proxy::authtoken' do it { is_expected.to contain_swift_proxy_config('filter:authtoken/www_authenticate_uri').with_value('http://127.0.0.1:5000') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/auth_url').with_value('http://127.0.0.1:5000') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/auth_type').with_value('password') } - it { is_expected.to contain_swift_proxy_config('filter:authtoken/project_domain_id').with_value('default') } - it { is_expected.to contain_swift_proxy_config('filter:authtoken/user_domain_id').with_value('default') } - it { is_expected.to contain_swift_proxy_config('filter:authtoken/project_name').with_value('admin') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/username').with_value('swiftuser') } + it { is_expected.to contain_swift_proxy_config('filter:authtoken/user_domain_id').with_value('default') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/password').with_value('swiftpassword').with_secret(true) } + it { is_expected.to contain_swift_proxy_config('filter:authtoken/project_name').with_value('admin') } + it { is_expected.to contain_swift_proxy_config('filter:authtoken/project_domain_id').with_value('default') } + it { is_expected.to contain_swift_proxy_config('filter:authtoken/system_scope').with_value('') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/region_name').with_value('region2') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/delay_auth_decision').with_value('0') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/cache').with_value('foo') } @@ -90,6 +92,18 @@ describe 'swift::proxy::authtoken' do it { is_expected.to contain_swift_proxy_config('filter:authtoken/www_authenticate_uri').with_value('https://foo.bar:5000/v3/') } it { is_expected.to contain_swift_proxy_config('filter:authtoken/auth_url').with_value('https://foo.bar:5000/') } end + + describe 'when system_scope is set' do + let :params do + { + :system_scope => 'all' + } + end + + it { is_expected.to contain_swift_proxy_config('filter:authtoken/project_name').with_value('') } + it { is_expected.to contain_swift_proxy_config('filter:authtoken/project_domain_id').with_value('') } + it { is_expected.to contain_swift_proxy_config('filter:authtoken/system_scope').with_value('all') } + end end on_supported_os({ diff --git a/spec/classes/swift_proxy_ceilometer_spec.rb b/spec/classes/swift_proxy_ceilometer_spec.rb index 013048bf..57b8c251 100644 --- a/spec/classes/swift_proxy_ceilometer_spec.rb +++ b/spec/classes/swift_proxy_ceilometer_spec.rb @@ -60,10 +60,11 @@ describe 'swift::proxy::ceilometer' do it { is_expected.to contain_swift_proxy_config('filter:ceilometer/ignore_projects').with_value(['services']) } it { is_expected.to contain_swift_proxy_config('filter:ceilometer/auth_url').with_value('http://127.0.0.1:5000') } it { is_expected.to contain_swift_proxy_config('filter:ceilometer/auth_type').with_value('password') } - it { is_expected.to contain_swift_proxy_config('filter:ceilometer/project_domain_name').with_value('Default') } - it { is_expected.to contain_swift_proxy_config('filter:ceilometer/user_domain_name').with_value('Default') } it { is_expected.to contain_swift_proxy_config('filter:ceilometer/project_name').with_value('services') } + it { is_expected.to contain_swift_proxy_config('filter:ceilometer/project_domain_name').with_value('Default') } + it { is_expected.to contain_swift_proxy_config('filter:ceilometer/system_scope').with_value('') } it { is_expected.to contain_swift_proxy_config('filter:ceilometer/username').with_value('swift') } + it { is_expected.to contain_swift_proxy_config('filter:ceilometer/user_domain_name').with_value('Default') } it { is_expected.to contain_swift_proxy_config('filter:ceilometer/password').with_value('mypassword').with_secret(true) } it { is_expected.to contain_swift_proxy_config('filter:ceilometer/region_name').with_value('region2') } end @@ -106,6 +107,19 @@ describe 'swift::proxy::ceilometer' do end end + + describe 'when system_scope is set' do + let :params do + { + :default_transport_url => 'rabbit://user_1:user_1_passw@1.1.1.1:5673/rabbit', + :system_scope => 'all' + } + end + + it { is_expected.to contain_swift_proxy_config('filter:ceilometer/project_name').with_value('') } + it { is_expected.to contain_swift_proxy_config('filter:ceilometer/project_domain_name').with_value('') } + it { is_expected.to contain_swift_proxy_config('filter:ceilometer/system_scope').with_value('all') } + end end on_supported_os({ diff --git a/spec/classes/swift_proxy_s3token_spec.rb b/spec/classes/swift_proxy_s3token_spec.rb index 6622c928..3929a5c3 100644 --- a/spec/classes/swift_proxy_s3token_spec.rb +++ b/spec/classes/swift_proxy_s3token_spec.rb @@ -12,11 +12,11 @@ describe 'swift::proxy::s3token' do it { is_expected.to contain_swift_proxy_config('filter:s3token/auth_url').with_value('http://127.0.0.1:5000') } it { is_expected.to contain_swift_proxy_config('filter:s3token/auth_type').with_value('password') } it { is_expected.to contain_swift_proxy_config('filter:s3token/username').with_value('swift') } + it { is_expected.to contain_swift_proxy_config('filter:s3token/user_domain_id').with_value('default') } it { is_expected.to contain_swift_proxy_config('filter:s3token/password').with_value('password').with_secret(true) } it { is_expected.to contain_swift_proxy_config('filter:s3token/project_name').with_value('services') } it { is_expected.to contain_swift_proxy_config('filter:s3token/project_domain_id').with_value('default') } - it { is_expected.to contain_swift_proxy_config('filter:s3token/user_domain_id').with_value('default') } - + it { is_expected.to contain_swift_proxy_config('filter:s3token/system_scope').with_value('') } end describe "when overriding default parameters" do @@ -34,7 +34,6 @@ describe 'swift::proxy::s3token' do :project_name => 'admin', :project_domain_id => '12345', :user_domain_id => '12345' - } end @@ -46,10 +45,23 @@ describe 'swift::proxy::s3token' do it { is_expected.to contain_swift_proxy_config('filter:s3token/auth_url').with_value('http://192.168.24.11:5000') } it { is_expected.to contain_swift_proxy_config('filter:s3token/auth_type').with_value('password') } it { is_expected.to contain_swift_proxy_config('filter:s3token/username').with_value('swift') } + it { is_expected.to contain_swift_proxy_config('filter:s3token/user_domain_id').with_value('12345') } it { is_expected.to contain_swift_proxy_config('filter:s3token/password').with_value('swift').with_secret(true) } it { is_expected.to contain_swift_proxy_config('filter:s3token/project_name').with_value('admin') } it { is_expected.to contain_swift_proxy_config('filter:s3token/project_domain_id').with_value('12345') } - it { is_expected.to contain_swift_proxy_config('filter:s3token/user_domain_id').with_value('12345') } + it { is_expected.to contain_swift_proxy_config('filter:s3token/system_scope').with_value('') } + end + + describe 'when system_scope is set' do + let :params do + { + :system_scope => 'all' + } + end + + it { is_expected.to contain_swift_proxy_config('filter:s3token/project_name').with_value('') } + it { is_expected.to contain_swift_proxy_config('filter:s3token/project_domain_id').with_value('') } + it { is_expected.to contain_swift_proxy_config('filter:s3token/system_scope').with_value('all') } end end