Support clouds.yaml to manage keystone user credentials
Recent openstack cli supports loading user credentials from clouds.yaml
instead of passing each parameters by environment variables or command
options.
This allows us to manage user credentials more flexibly. The biggest
benefit of the clouds.yaml file is that it supports managing multiple
credentials in a single file. When SRBAC is enforced, each API request
should be made with the proper scope credential, and we need to switch
credentials for different scopes(project, domain and system) according.
Usage of clouds.yaml helps this use case hugely because it allows us to
store credentials for each scope in a single file and switch them by
the single OS_CLOUD environment variable(or the --os-cloud option).
Change-Id: Ie8246aa18d90ba506fe708be13c9a5afa3e5d2fd
(cherry picked from commit 522d06ba8b
)
This commit is contained in:
parent
cb51302e01
commit
369c516bd6
|
@ -88,7 +88,9 @@ class Puppet::Provider::Openstack::CredentialsV3 < Puppet::Provider::Openstack::
|
|||
:trust_id,
|
||||
:user_domain_id,
|
||||
:user_domain_name,
|
||||
:user_id
|
||||
:user_id,
|
||||
:cloud,
|
||||
:client_config_file,
|
||||
]
|
||||
|
||||
KEYS.each { |var| attr_accessor var }
|
||||
|
@ -113,12 +115,14 @@ class Puppet::Provider::Openstack::CredentialsV3 < Puppet::Provider::Openstack::
|
|||
elsif @system_scope
|
||||
return 'system'
|
||||
else
|
||||
# When clouds.yaml is used, parameters are not directly passed to puppet
|
||||
# so the scope can't be detected.
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
def user_password_set?
|
||||
return true if user_set? && @password && scope_set? && @auth_url
|
||||
return true if (user_set? && @password && scope_set? && @auth_url) || @cloud
|
||||
end
|
||||
|
||||
def initialize
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
# == Class: openstacklib::clouds
|
||||
#
|
||||
# Generates clouds.yaml for openstack CLI
|
||||
#
|
||||
# == Parameters
|
||||
#
|
||||
# [*username*]
|
||||
# (Required) The name of the keystone user.
|
||||
#
|
||||
# [*password*]
|
||||
# (Required) Password of the keystone user.
|
||||
#
|
||||
# [*auth_url*]
|
||||
# (Required) The URL to use for authentication.
|
||||
#
|
||||
# [*path*]
|
||||
# (Optional) Path to the clouds.yaml file.
|
||||
# Defaults to $name
|
||||
#
|
||||
# [*user_domain_name*]
|
||||
# (Optional) Name of domain for $username.
|
||||
# Defaults to 'Default'
|
||||
#
|
||||
# [*project_name*]
|
||||
# (Optional) The name of the keystone project.
|
||||
# Defaults to undef
|
||||
#
|
||||
# [*project_domain_name*]
|
||||
# (Optional) Name of domain for $project_name.
|
||||
# Defaults to 'Default'
|
||||
#
|
||||
# [*system_scope*]
|
||||
# (Optional) Scope for system operations.
|
||||
# Defaults to undef
|
||||
#
|
||||
# [*interface*]
|
||||
# (Optional) Determine the endpoint to be used.
|
||||
# Defaults to undef
|
||||
#
|
||||
# [*region_name*]
|
||||
# (Optional) The region in which the service can be found.
|
||||
# Defaults to undef
|
||||
#
|
||||
# [*api_versions*]
|
||||
# (Optional) Hash of service type and version to determine API version
|
||||
# for that service to use.
|
||||
# Example: { 'identity' => '3', 'compute' => '2.latest' }
|
||||
# Defaults to {}
|
||||
#
|
||||
define openstacklib::clouds(
|
||||
$username,
|
||||
$password,
|
||||
$auth_url,
|
||||
$path = $name,
|
||||
$user_domain_name = 'Default',
|
||||
$project_name = undef,
|
||||
$project_domain_name = 'Default',
|
||||
$system_scope = undef,
|
||||
$interface = undef,
|
||||
$region_name = undef,
|
||||
$api_versions = {},
|
||||
) {
|
||||
|
||||
if !$project_name and !$system_scope {
|
||||
fail('One of project_name and system_scope should be set')
|
||||
}
|
||||
|
||||
file { $path:
|
||||
ensure => 'present',
|
||||
mode => '0600',
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
content => template('openstacklib/clouds.yaml.erb'),
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
The new ``openstacklib::clouds`` resource type has been added, which
|
||||
manages the ``clouds.yaml`` file to store credentials for the ``openstack``
|
||||
cli.
|
||||
|
||||
- |
|
||||
Now ``Puppet::Provider::Openstack::CredentialsV3`` supports loading
|
||||
credentials from the ``clouds.yaml`` file.
|
|
@ -0,0 +1,41 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe 'openstacklib::clouds' do
|
||||
shared_examples 'openstacklib::clouds' do
|
||||
let :title do
|
||||
'/etc/openstack/clouds.yaml'
|
||||
end
|
||||
|
||||
context 'with the required parameters' do
|
||||
let :params do
|
||||
{
|
||||
:username => 'admin',
|
||||
:password => 'secrete',
|
||||
:auth_url => 'http://127.0.0.1:5000/',
|
||||
:project_name => 'demo',
|
||||
}
|
||||
end
|
||||
|
||||
it 'creates a clouds.yaml file' do
|
||||
should contain_file('/etc/openstack/clouds.yaml').with(
|
||||
:mode => '0600',
|
||||
:owner => 'root',
|
||||
:group => 'root',
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
on_supported_os({
|
||||
:supported_os => OSDefaults.get_supported_os
|
||||
}).each do |os,facts|
|
||||
context "on #{os}" do
|
||||
let (:facts) do
|
||||
facts.merge!(OSDefaults.get_facts())
|
||||
end
|
||||
|
||||
it_behaves_like 'openstacklib::clouds'
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -74,6 +74,12 @@ describe Puppet::Provider::Openstack::Credentials do
|
|||
expect(creds.service_token_set?).to be_falsey
|
||||
end
|
||||
|
||||
it 'is successful with cloud' do
|
||||
creds.cloud = 'openstack'
|
||||
expect(creds.user_password_set?).to be_truthy
|
||||
expect(creds.service_token_set?).to be_falsey
|
||||
end
|
||||
|
||||
it 'fails' do
|
||||
creds.auth_url = 'auth_url'
|
||||
creds.password = 'password'
|
||||
|
@ -111,6 +117,8 @@ describe Puppet::Provider::Openstack::Credentials do
|
|||
creds.endpoint = 'endpoint'
|
||||
creds.region_name = 'region_name'
|
||||
creds.identity_api_version = 'identity_api_version'
|
||||
creds.cloud = 'openstack'
|
||||
creds.client_config_file = '/etc/openstack/clouds.yaml'
|
||||
creds.unset
|
||||
expect(creds.auth_url).to eq('')
|
||||
expect(creds.password).to eq('')
|
||||
|
@ -122,6 +130,8 @@ describe Puppet::Provider::Openstack::Credentials do
|
|||
expect(creds.endpoint).to eq('')
|
||||
expect(creds.region_name).to eq('')
|
||||
expect(creds.identity_api_version).to eq('identity_api_version')
|
||||
expect(creds.cloud).to eq('')
|
||||
expect(creds.client_config_file).to eq('')
|
||||
newcreds = Puppet::Provider::Openstack::CredentialsV3.new
|
||||
expect(newcreds.identity_api_version).to eq('3')
|
||||
end
|
||||
|
@ -141,6 +151,8 @@ describe Puppet::Provider::Openstack::Credentials do
|
|||
creds.endpoint = 'endpoint'
|
||||
creds.region_name = 'Region1'
|
||||
creds.identity_api_version = 'identity_api_version'
|
||||
creds.cloud = 'openstack'
|
||||
creds.client_config_file = '/etc/openstack/clouds.yaml'
|
||||
expect(creds.to_env).to eq({
|
||||
'OS_USERNAME' => 'username',
|
||||
'OS_PASSWORD' => 'password',
|
||||
|
@ -152,6 +164,8 @@ describe Puppet::Provider::Openstack::Credentials do
|
|||
'OS_ENDPOINT' => 'endpoint',
|
||||
'OS_REGION_NAME' => 'Region1',
|
||||
'OS_IDENTITY_API_VERSION' => 'identity_api_version',
|
||||
'OS_CLOUD' => 'openstack',
|
||||
'OS_CLIENT_CONFIG_FILE' => '/etc/openstack/clouds.yaml',
|
||||
})
|
||||
end
|
||||
end
|
||||
|
@ -173,6 +187,7 @@ describe Puppet::Provider::Openstack::Credentials do
|
|||
creds.project_name = 'project_name'
|
||||
creds.username = 'username'
|
||||
expect(creds.user_password_set?).to be_truthy
|
||||
expect(creds.scope).to eq('project')
|
||||
end
|
||||
end
|
||||
describe '#password_set? with username and domain_name' do
|
||||
|
@ -182,6 +197,7 @@ describe Puppet::Provider::Openstack::Credentials do
|
|||
creds.domain_name = 'domain_name'
|
||||
creds.username = 'username'
|
||||
expect(creds.user_password_set?).to be_truthy
|
||||
expect(creds.scope).to eq('domain')
|
||||
end
|
||||
end
|
||||
describe '#password_set? with username and system_scope' do
|
||||
|
@ -191,6 +207,14 @@ describe Puppet::Provider::Openstack::Credentials do
|
|||
creds.system_scope = 'all'
|
||||
creds.username = 'username'
|
||||
expect(creds.user_password_set?).to be_truthy
|
||||
expect(creds.scope).to eq('system')
|
||||
end
|
||||
end
|
||||
describe '#password_set? with cloud' do
|
||||
it 'is successful' do
|
||||
creds.cloud = 'openstack'
|
||||
expect(creds.user_password_set?).to be_truthy
|
||||
expect(creds.scope).to eq(nil)
|
||||
end
|
||||
end
|
||||
describe '#password_set? with user_id and project_id' do
|
||||
|
@ -200,6 +224,7 @@ describe Puppet::Provider::Openstack::Credentials do
|
|||
creds.project_id = 'projid'
|
||||
creds.user_id = 'userid'
|
||||
expect(creds.user_password_set?).to be_truthy
|
||||
expect(creds.scope).to eq('project')
|
||||
end
|
||||
end
|
||||
describe '#password_set? with user_id and domain_id' do
|
||||
|
@ -209,6 +234,7 @@ describe Puppet::Provider::Openstack::Credentials do
|
|||
creds.domain_id = 'domid'
|
||||
creds.user_id = 'userid'
|
||||
expect(creds.user_password_set?).to be_truthy
|
||||
expect(creds.scope).to eq('domain')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
clouds:
|
||||
<% if @project_name -%>
|
||||
project:
|
||||
auth:
|
||||
auth_url: <%= @auth_url %>
|
||||
password: <%= @password %>
|
||||
username: <%= @username %>
|
||||
user_domain_name: <%= @user_domain_name %>
|
||||
project_name: <%= @project_name %>
|
||||
project_domain_name: <%= @project_domain_name %>
|
||||
<%- @api_versions.sort.each do |opt_name,opt_val| -%>
|
||||
<%= opt_name %>_api_version: <%= opt_val %>
|
||||
<%- end -%>
|
||||
<%- if !(@interface.nil?) -%>
|
||||
interface: <%= @interface %>
|
||||
<%- end -%>
|
||||
<%- if !(@region_name.nil?) -%>
|
||||
region_name: <%= @region_name %>
|
||||
<%- end -%>
|
||||
<% end -%>
|
||||
<% if @system_scope -%>
|
||||
system:
|
||||
auth:
|
||||
auth_url: <%= @auth_url %>
|
||||
password: <%= @password %>
|
||||
username: <%= @username %>
|
||||
user_domain_name: <%= @user_domain_name %>
|
||||
system_scope: <%= @system_scope %>
|
||||
<%- @api_versions.sort.each do |opt_name,opt_val| -%>
|
||||
<%= opt_name %>_api_version: <%= opt_val %>
|
||||
<%- end -%>
|
||||
<%- if !(@interface.nil?) -%>
|
||||
interface: <%= @interface %>
|
||||
<%- end -%>
|
||||
<%- if !(@region_name.nil?) -%>
|
||||
region_name: <%= @region_name %>
|
||||
<%- end -%>
|
||||
<% end -%>
|
Loading…
Reference in New Issue