1 From 2c51d6f4ccf4a473089c08857262e769f7a8fc3a Mon Sep 17 00:00:00 2001
2 From: Al Bailey <Al.Bailey@windriver.com>
3 Date: Thu, 7 Mar 2019 13:43:40 -0600
4 Subject: [PATCH 1/4] WRS: Patch1:
5 0001-pike-rebase-squash-titanium-patches.patch
8 lib/puppet/provider/keystone.rb | 79 ++++++++++++++++++++++-
9 manifests/db/sync.pp | 3 +
10 manifests/init.pp | 76 +++++++++++++++++-----
11 manifests/ldap.pp | 7 ++
12 manifests/logging.pp | 2 +-
13 manifests/resource/service_identity.pp | 7 ++
14 manifests/security_compliance.pp | 45 +++++++++++++
15 spec/classes/keystone_security_compliance_spec.rb | 19 ++++++
16 8 files changed, 220 insertions(+), 18 deletions(-)
17 create mode 100644 manifests/security_compliance.pp
18 create mode 100644 spec/classes/keystone_security_compliance_spec.rb
20 diff --git a/lib/puppet/provider/keystone.rb b/lib/puppet/provider/keystone.rb
21 index 3841418..0857ac1 100644
22 --- a/lib/puppet/provider/keystone.rb
23 +++ b/lib/puppet/provider/keystone.rb
24 @@ -3,6 +3,7 @@ require 'puppet/provider/openstack'
25 require 'puppet/provider/openstack/auth'
26 require 'puppet/provider/openstack/credentials'
27 require File.join(File.dirname(__FILE__), '..','..', 'puppet/provider/keystone/util')
28 +require 'hiera_puppet'
30 class Puppet::Provider::Keystone < Puppet::Provider::Openstack
32 @@ -230,12 +231,88 @@ class Puppet::Provider::Keystone < Puppet::Provider::Openstack
36 + ### WRS Modifications (Start) ###
38 + def self.hiera_lookup(key)
39 + HieraPuppet.lookup(key, :undef, self, nil, :priority)
42 + def self.initial_config_primary?
43 + return true if ENV['INITIAL_CONFIG_PRIMARY'] == "true"
48 + return true if hiera_lookup('platform::params::controller_upgrade') == true
51 def self.request(service, action, properties=nil, options={})
53 rescue Puppet::Error::OpenstackAuthInputError, Puppet::Error::OpenstackUnauthorizedError => error
54 - request_by_service_token(service, action, error, properties, options=options)
55 + if initial_config_primary?
56 + # admin user account might not have been created
57 + request_by_service_token(service, action, error, properties)
60 + # when running the Keystone manifest during an upgrade
61 + # (on controller-1), we need to use an AUTH token and
62 + # a bypass URL since using the default AUTL URL will
63 + # send the Request to the service catalog URL (internalURL),
64 + # running on the non-upgraded controller-0 which cannot
65 + # service this request
66 + request_by_upgrading_token(service, action, error, properties)
68 + request_by_admin_credential(service, action, error, properties)
73 + def self.request_by_admin_credential(service, action, error, properties=nil)
75 + @credentials.username = hiera_lookup('platform::client::params::admin_username')
76 + @credentials.password = hiera_lookup('keystone::admin_password')
77 + @credentials.project_name = 'admin'
78 + @credentials.auth_url = service_url
79 + @credentials.identity_api_version = @credentials.version
80 + if @credentials.version == '3'
81 + @credentials.user_domain_name = hiera_lookup('platform::client::params::admin_user_domain')
82 + @credentials.project_domain_name = hiera_lookup('platform::client::params::admin_project_domain')
84 + raise error unless @credentials.set?
85 + Puppet::Provider::Openstack.request(service, action, properties, @credentials)
88 + def self.get_upgrade_token
89 + upgrade_token_file = hiera_lookup('openstack::keystone::upgrade::upgrade_token_file')
90 + # the upgrade token file may get refreshed by the same Puppet event
91 + # that triggered this call, and therefore may not be available
92 + # immediately. Try for timeout before quitting with error
93 + timeout = 10 # 10 seconds
94 + 1.upto(timeout) do |iter|
95 + if File.exists?(upgrade_token_file)
96 + upgrade_token = File.read(upgrade_token_file).strip
97 + notice("Found #{upgrade_token_file} token file and upgrade token #{upgrade_token}.")
98 + return upgrade_token
100 + Puppet.debug("#{upgrade_token_file} not found. Retrying for #{iter} more seconds.")
104 + raise(Puppet::ExecutionFailure, "Can't retrieve #{upgrade_token_file} in #{timeout}s retry attempts.")
108 + def self.request_by_upgrading_token(service, action, error, properties=nil, options={})
110 + @credentials.token = get_upgrade_token
111 + @credentials.url = hiera_lookup('openstack::keystone::upgrade::url')
112 + raise error unless @credentials.service_token_set?
113 + Puppet::Provider::Openstack.request(service, action, properties, @credentials, options)
116 + ### WRS Additions (End) ###
119 def self.request_by_service_token(service, action, error, properties=nil, options={})
121 @credentials.token = admin_token
122 diff --git a/manifests/db/sync.pp b/manifests/db/sync.pp
123 index cee869b..cea217c 100644
124 --- a/manifests/db/sync.pp
125 +++ b/manifests/db/sync.pp
126 @@ -36,5 +36,8 @@ class keystone::db::sync(
128 notify => Anchor['keystone::dbsync::end'],
129 tag => 'keystone-exec',
130 + # Only do the db sync if both controllers are running the same software
131 + # version. Avoids impacting mate controller during an upgrade.
132 + onlyif => "test $::controller_sw_versions_match = true",
135 diff --git a/manifests/init.pp b/manifests/init.pp
136 index 2adc685..4d79d30 100644
137 --- a/manifests/init.pp
138 +++ b/manifests/init.pp
140 # The admin_token has been deprecated by the Keystone service and this
141 # will be deprecated in a future changeset. Required.
143 +# [*upgrade_token_cmd*]
144 +# (optional) WRS - if we are in an upgrade scenario, an upgrade token
145 +# will be required to bypass authentication.
148 +# [*upgrade_token_file*]
149 +# (optional) WRS - the file where the upgrade token will be stowed
153 # Keystone password for the admin user. This is not the admin_token.
154 # This is the password that the admin user signs into keystone with.
159 + $upgrade_token_cmd = undef,
160 + $upgrade_token_file = undef,
161 $admin_password = undef,
162 $package_ensure = 'present',
163 $client_package_ensure = 'present',
164 @@ -857,10 +868,13 @@ admin_token will be removed in a later release")
167 'DEFAULT/admin_token': value => $admin_token, secret => true;
168 + # WRS: the following options are deprecated for removal
169 + # however public_bind_host and admin_bind_host are still required as long as
170 + # keystone is running under eventlet
171 'DEFAULT/public_bind_host': value => $public_bind_host;
172 'DEFAULT/admin_bind_host': value => $admin_bind_host;
173 - 'DEFAULT/public_port': value => $public_port;
174 - 'DEFAULT/admin_port': value => $admin_port;
175 + #'DEFAULT/public_port': value => $public_port;
176 + #'DEFAULT/admin_port': value => $admin_port;
177 'DEFAULT/member_role_id': value => $member_role_id;
178 'DEFAULT/member_role_name': value => $member_role_name;
179 'paste_deploy/config_file': value => $paste_config;
180 @@ -897,18 +911,21 @@ admin_token will be removed in a later release")
184 - 'ssl/enable': value => true;
185 + # WRS ssl/enable is deprecated for removal
186 + #'ssl/enable': value => true;
187 'ssl/certfile': value => $ssl_certfile;
188 'ssl/keyfile': value => $ssl_keyfile;
189 'ssl/ca_certs': value => $ssl_ca_certs;
190 'ssl/ca_key': value => $ssl_ca_key;
191 'ssl/cert_subject': value => $ssl_cert_subject;
195 - 'ssl/enable': value => false;
198 + # WRS ssl/enable is deprecated for removal
200 + # keystone_config {
201 + # 'ssl/enable': value => false;
205 if !is_service_default($memcache_servers) or !is_service_default($cache_memcache_servers) {
206 Service<| title == 'memcached' |> -> Anchor['keystone::service::begin']
207 @@ -1016,14 +1033,15 @@ Fernet or UUID tokens are recommended.")
208 Fernet or UUID tokens are recommended.")
212 - 'signing/certfile': value => $signing_certfile;
213 - 'signing/keyfile': value => $signing_keyfile;
214 - 'signing/ca_certs': value => $signing_ca_certs;
215 - 'signing/ca_key': value => $signing_ca_key;
216 - 'signing/cert_subject': value => $signing_cert_subject;
217 - 'signing/key_size': value => $signing_key_size;
219 + # WRS: the following signing options are deprecated for removal
221 + # 'signing/certfile': value => $signing_certfile;
222 + # 'signing/keyfile': value => $signing_keyfile;
223 + # 'signing/ca_certs': value => $signing_ca_certs;
224 + # 'signing/ca_key': value => $signing_ca_key;
225 + # 'signing/cert_subject': value => $signing_cert_subject;
226 + # 'signing/key_size': value => $signing_key_size;
229 # Only do pki_setup if we were asked to do so. This is needed
230 # regardless of the token provider since token revocation lists
231 @@ -1089,6 +1107,9 @@ Fernet or UUID tokens are recommended.")
232 heartbeat_rate => $rabbit_heartbeat_rate,
235 + # WRS: The following options are deprecated for removal
236 + # however they are still required as long as keystone
237 + # is running under eventlet
239 'eventlet_server/admin_workers': value => $admin_workers;
240 'eventlet_server/public_workers': value => $public_workers;
241 @@ -1135,7 +1156,8 @@ Fernet or UUID tokens are recommended.")
245 - warning("Keystone under Eventlet has been deprecated during the Kilo cycle. \
246 + # Drop this to info.
247 + info("Keystone under Eventlet has been deprecated during the Kilo cycle. \
248 Support for deploying under eventlet will be dropped as of the M-release of OpenStack.")
249 } elsif $service_name == 'httpd' {
250 include ::apache::params
251 @@ -1280,6 +1302,27 @@ running as a standalone service, or httpd for being run by a httpd server")
255 + # WRS: Now that the keystone service has started,
256 + # check if we are in an Upgrade scenario, and generate
257 + # an upgrade token which will be used to bypass Keystone
258 + # authentication (specifically the service catalog) for
259 + # all operations during upgrades.
260 + # This operation is similar to the keystone bootstrap
261 + # operation (above) which would generate an admin
262 + # token, and therefore also requires the database to
263 + # be up and running and configured and is only run once,
264 + # so we don't need to notify the service
265 + if $upgrade_token_cmd and $upgrade_token_file {
266 + exec { 'upgrade token issue':
267 + command => "${upgrade_token_cmd} > ${upgrade_token_file}",
268 + path => '/usr/bin',
269 + creates => $upgrade_token_file,
270 + subscribe => Service[$service_name],
271 + notify => Anchor['keystone::service::end'],
272 + tag => 'keystone-exec',
276 if $using_domain_config {
277 validate_absolute_path($domain_config_directory)
278 # Better than ensure resource. We don't want to conflict with any
279 @@ -1311,4 +1354,5 @@ running as a standalone service, or httpd for being run by a httpd server")
280 {'value' => $domain_config_directory}
285 diff --git a/manifests/ldap.pp b/manifests/ldap.pp
286 index 11620bf..728ca40 100644
287 --- a/manifests/ldap.pp
288 +++ b/manifests/ldap.pp
294 +# LDAP debugging level for LDAP calls; a value of zero("0") disables
295 +# debugging. (integer value)
296 +# Defaults to 'undef'
299 # URL for connecting to the LDAP server. (string value)
300 # Defaults to 'undef'
302 # Copyright 2012 Puppetlabs Inc, unless otherwise noted.
304 class keystone::ldap(
305 + $debug_level = undef,
309 @@ -494,6 +500,7 @@ class keystone::ldap(
313 + 'ldap/debug_level': value => $debug_level;
314 'ldap/url': value => $url;
315 'ldap/user': value => $user;
316 'ldap/password': value => $password, secret => true;
317 diff --git a/manifests/logging.pp b/manifests/logging.pp
318 index e737c4f..3d8df63 100644
319 --- a/manifests/logging.pp
320 +++ b/manifests/logging.pp
321 @@ -110,7 +110,7 @@ class keystone::logging(
322 $log_file = $::os_service_default,
323 $debug = $::os_service_default,
324 $logging_context_format_string = $::os_service_default,
325 - $logging_default_format_string = $::os_service_default,
326 + $logging_default_format_string = 'keystone:log %(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s',
327 $logging_debug_format_suffix = $::os_service_default,
328 $logging_exception_prefix = $::os_service_default,
329 $logging_user_identity_format = $::os_service_default,
330 diff --git a/manifests/resource/service_identity.pp b/manifests/resource/service_identity.pp
331 index 09e7d94..243c9ec 100644
332 --- a/manifests/resource/service_identity.pp
333 +++ b/manifests/resource/service_identity.pp
334 @@ -187,6 +187,8 @@ define keystone::resource::service_identity(
336 ensure_resource('keystone_service', "${service_name_real}::${service_type}", {
338 + 'name' => $service_name_real,
339 + 'type' => $service_type,
340 'description' => $service_description,
343 @@ -199,6 +201,9 @@ define keystone::resource::service_identity(
344 if $public_url and $admin_url and $internal_url {
345 ensure_resource('keystone_endpoint', "${region}/${service_name_real}::${service_type}", {
347 + 'name' => $service_name_real,
348 + 'type' => $service_type,
349 + 'region' => $region,
350 'public_url' => $public_url,
351 'admin_url' => $admin_url,
352 'internal_url' => $internal_url,
353 @@ -210,6 +215,8 @@ define keystone::resource::service_identity(
354 if $public_url and $admin_url and $internal_url {
355 ensure_resource('keystone_endpoint', "${region}/${service_name_real}", {
357 + 'name' => $service_name_real,
358 + 'region' => $region,
359 'public_url' => $public_url,
360 'admin_url' => $admin_url,
361 'internal_url' => $internal_url,
362 diff --git a/manifests/security_compliance.pp b/manifests/security_compliance.pp
364 index 0000000..64830ec
366 +++ b/manifests/security_compliance.pp
368 +# == class: keystone::security_compliance
370 +# Implements security compliance configuration for keystone.
374 +# [*unique_last_password_count*]
375 +# This controls the number of previous user password iterations
376 +# to keep in history, in order to enforce that newly created passwords
377 +# are unique. Setting the value to 1 (the default) disables this feature.
379 +# Defaults to 'undef'
381 +# [*password_regex*]
382 +# The regular expression used to validate password strength
383 +# requirements. By default, the regular expression will match
384 +# any password. (string value)
385 +# Defaults to 'undef'
387 +# [*password_regex_description*]
388 +# If a password fails to match the regular expression (*password_regex*),
389 +# the contents of this configuration will be returned to users to explain
390 +# why their requested password was insufficient. (string value)
391 +# Defaults to 'undef'
393 +# === DEPRECATED group/name
397 +# Copyright 2017 Wind River Systems, unless otherwise noted.
399 +class keystone::security_compliance(
400 + $unique_last_password_count = undef,
401 + $password_regex = undef,
402 + $password_regex_description = undef,
405 + include ::keystone::deps
408 + 'security_compliance/unique_last_password_count': value => $unique_last_password_count;
409 + 'security_compliance/password_regex': value => $password_regex;
410 + 'security_compliance/password_regex_description': value => $password_regex_description;
413 diff --git a/spec/classes/keystone_security_compliance_spec.rb b/spec/classes/keystone_security_compliance_spec.rb
415 index 0000000..d0d4724
417 +++ b/spec/classes/keystone_security_compliance_spec.rb
419 +require 'spec_helper'
421 +describe 'keystone::security_compliance' do
422 + describe 'with basic params' do
425 + :unique_last_password_count => 2,
426 + :password_regex => '^(?=.*\d)(?=.*[a-zA-Z]).{7,}$',
427 + :password_regex_description => 'password must be at least 7 characters long and contain 1 digit',
430 + it 'should have basic params' do
432 + is_expected.to contain_keystone_config('security_compliance/unique_last_password_count').with_value('2')
433 + is_expected.to contain_keystone_config('security_compliance/password_regex').with_value('^(?=.*\d)(?=.*[a-zA-Z]).{7,}$')
434 + is_expected.to contain_keystone_config('security_compliance/password_regex_description').with_value('password must be at least 7 characters long and contain 1 digit')