Manage updates to keystone user password with keystone_user
Fix bug 1170380 o Test if the current password works and if not reset it allowing users to reset passwords with puppet o Also move admin token from command line of keystone command in favour of using a env variable o Note : this will break folsom support Change-Id: I4bae9cad767cdd141ae76343298f7ac43c2a1f90
This commit is contained in:
@@ -53,13 +53,33 @@ class Puppet::Provider::Keystone < Puppet::Provider
|
|||||||
@keystone_file = nil
|
@keystone_file = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# the path to withenv changes between versions of puppet, so redefining this function here,
|
||||||
|
# Run some code with a specific environment. Resets the environment at the end of the code.
|
||||||
|
def self.withenv(hash, &block)
|
||||||
|
saved = ENV.to_hash
|
||||||
|
hash.each do |name, val|
|
||||||
|
ENV[name.to_s] = val
|
||||||
|
end
|
||||||
|
block.call
|
||||||
|
ensure
|
||||||
|
ENV.clear
|
||||||
|
saved.each do |name, val|
|
||||||
|
ENV[name] = val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def self.auth_keystone(*args)
|
def self.auth_keystone(*args)
|
||||||
|
authenv = {:OS_SERVICE_TOKEN => admin_token}
|
||||||
begin
|
begin
|
||||||
remove_warnings(keystone('--token', admin_token, '--endpoint', admin_endpoint, args))
|
withenv authenv do
|
||||||
|
remove_warnings(keystone('--endpoint', admin_endpoint, args))
|
||||||
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
if (e.message =~ /\[Errno 111\] Connection refused/) or (e.message =~ /\(HTTP 400\)/)
|
if (e.message =~ /\[Errno 111\] Connection refused/) or (e.message =~ /\(HTTP 400\)/)
|
||||||
sleep 10
|
sleep 10
|
||||||
remove_warnings(keystone('--token', admin_token, '--endpoint', admin_endpoint, args))
|
withenv authenv do
|
||||||
|
remove_warnings(keystone('--endpoint', admin_endpoint, args))
|
||||||
|
end
|
||||||
else
|
else
|
||||||
raise(e)
|
raise(e)
|
||||||
end
|
end
|
||||||
@@ -70,6 +90,29 @@ class Puppet::Provider::Keystone < Puppet::Provider
|
|||||||
self.class.auth_keystone(args)
|
self.class.auth_keystone(args)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.creds_keystone(name, tenant, password, *args)
|
||||||
|
authenv = {:OS_USERNAME => name, :OS_TENANT_NAME => tenant, :OS_PASSWORD => password}
|
||||||
|
begin
|
||||||
|
withenv authenv do
|
||||||
|
remove_warnings(keystone('--os-auth-url', admin_endpoint, args))
|
||||||
|
end
|
||||||
|
rescue Exception => e
|
||||||
|
if (e.message =~ /\[Errno 111\] Connection refused/) or (e.message =~ /\(HTTP 400\)/)
|
||||||
|
sleep 10
|
||||||
|
withenv authenv do
|
||||||
|
remove_warnings(keystone('--os-auth-url', admin_endpoint, args))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
raise(e)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def creds_keystone(name, tenant, password, *args)
|
||||||
|
self.class.creds_keystone(name, tenant, password, args)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def self.list_keystone_objects(type, number_columns, *args)
|
def self.list_keystone_objects(type, number_columns, *args)
|
||||||
|
|||||||
@@ -80,20 +80,23 @@ Puppet::Type.type(:keystone_user).provide(
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# def password
|
def password
|
||||||
# Puppet.warning("Cannot retrieve password")
|
# if we don't know a password we can't test it
|
||||||
# user_hash[resource[:name]][:password]
|
return nil if resource[:password] == nil
|
||||||
# end
|
# we can't get the value of the password but we can test to see if the one we know
|
||||||
#
|
# about works, if it doesn't then return nil, causing it to be reset
|
||||||
# def password=(value)
|
begin
|
||||||
# Puppet.warning('Cannot update password')
|
token_out = creds_keystone(resource[:name], resource[:tenant], resource[:password], "token-get")
|
||||||
# # user-password-update does not support the ability know what the
|
rescue Exception => e
|
||||||
# # current value is
|
return nil if e.message =~ /Not Authorized/
|
||||||
# #auth_keystone(
|
raise e
|
||||||
# # 'user-password-update',
|
end
|
||||||
# # '--pass', value,
|
return resource[:password]
|
||||||
# # user_hash[resource[:name]][:id]
|
end
|
||||||
# end
|
|
||||||
|
def password=(value)
|
||||||
|
auth_keystone('user-password-update', '--pass', value, user_hash[resource[:name]][:id])
|
||||||
|
end
|
||||||
|
|
||||||
def tenant
|
def tenant
|
||||||
user_hash[resource[:name]][:tenant]
|
user_hash[resource[:name]][:tenant]
|
||||||
|
|||||||
@@ -24,8 +24,23 @@ Puppet::Type.newtype(:keystone_user) do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
newparam(:password) do
|
newproperty(:password) do
|
||||||
newvalues(/\S+/)
|
newvalues(/\S+/)
|
||||||
|
def change_to_s(currentvalue, newvalue)
|
||||||
|
if currentvalue == :absent
|
||||||
|
return "created password"
|
||||||
|
else
|
||||||
|
return "changed password"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_to_s( currentvalue )
|
||||||
|
return '[old password redacted]'
|
||||||
|
end
|
||||||
|
|
||||||
|
def should_to_s( newvalue )
|
||||||
|
return '[new password redacted]'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
newproperty(:tenant) do
|
newproperty(:tenant) do
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ describe Puppet::Provider::Keystone do
|
|||||||
Puppet::Util::IniConfig::File.expects(:new).returns(mock)
|
Puppet::Util::IniConfig::File.expects(:new).returns(mock)
|
||||||
mock.expects(:read).with('/etc/keystone/keystone.conf')
|
mock.expects(:read).with('/etc/keystone/keystone.conf')
|
||||||
klass.expects(:sleep).with(10).returns(nil)
|
klass.expects(:sleep).with(10).returns(nil)
|
||||||
klass.expects(:keystone).twice.with('--token', 'foo', '--endpoint', 'http://127.0.0.1:35357/v2.0/', ['test_retries']).raises(Exception, valid_message).then.returns('')
|
klass.expects(:keystone).twice.with('--endpoint', 'http://127.0.0.1:35357/v2.0/', ['test_retries']).raises(Exception, valid_message).then.returns('')
|
||||||
klass.auth_keystone('test_retries')
|
klass.auth_keystone('test_retries')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -97,8 +97,6 @@ describe Puppet::Provider::Keystone do
|
|||||||
klass.expects(
|
klass.expects(
|
||||||
:keystone
|
:keystone
|
||||||
).with(
|
).with(
|
||||||
'--token',
|
|
||||||
'foo',
|
|
||||||
'--endpoint',
|
'--endpoint',
|
||||||
'http://127.0.0.1:35357/v2.0/',
|
'http://127.0.0.1:35357/v2.0/',
|
||||||
['test_retries']
|
['test_retries']
|
||||||
|
|||||||
44
spec/unit/provider/keystone_user/keystone_spec.rb
Normal file
44
spec/unit/provider/keystone_user/keystone_spec.rb
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
require 'puppet'
|
||||||
|
require 'spec_helper'
|
||||||
|
require 'puppet/provider/keystone_user/keystone'
|
||||||
|
|
||||||
|
provider_class = Puppet::Type.type(:keystone_user).provider(:keystone)
|
||||||
|
|
||||||
|
describe provider_class do
|
||||||
|
|
||||||
|
describe 'when updating a user' do
|
||||||
|
let :resource do
|
||||||
|
Puppet::Type::Keystone_user.new(
|
||||||
|
{
|
||||||
|
:name => 'foo',
|
||||||
|
:ensure => 'present',
|
||||||
|
:enabled => 'True',
|
||||||
|
:tenant => 'foo2',
|
||||||
|
:email => 'foo@foo.com',
|
||||||
|
:password => 'passwd'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
let :provider do
|
||||||
|
provider_class.new(resource)
|
||||||
|
end
|
||||||
|
|
||||||
|
before :each do
|
||||||
|
provider_class.expects(:build_user_hash).returns(
|
||||||
|
'foo' => {:id => 'id', :name => 'foo', :tenant => 'foo2', :password => 'passwd'}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
after :each do
|
||||||
|
# reset global state
|
||||||
|
provider_class.prefetch(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should call user-password-update to change password' do
|
||||||
|
provider.expects(:auth_keystone).with('user-password-update', '--pass', 'newpassword', 'id')
|
||||||
|
provider.password=('newpassword')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Reference in New Issue
Block a user