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
This commit is contained in:
parent
0027bf6893
commit
8a9c4a4dd8
|
@ -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,99 @@
|
|||
# == 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
|
||||
#
|
||||
# [*compute_api_version*]
|
||||
# (Optional) Compute API version to use.
|
||||
# Defaults to 2
|
||||
#
|
||||
# [*identity_api_version*]
|
||||
# (Optional) Identity API version to use.
|
||||
# Defaults to 3
|
||||
#
|
||||
# [*image_api_version*]
|
||||
# (Optional) Image API version to use.
|
||||
# Defaults to 2
|
||||
#
|
||||
# [*network_api_version*]
|
||||
# (Optional) Network API version to use.
|
||||
# Defaults to 2
|
||||
#
|
||||
# [*object_store_api_version*]
|
||||
# (Optional) Object Storage API version to use.
|
||||
# Defaults to 1
|
||||
#
|
||||
# [*volume_api_version*]
|
||||
# (Optional) Volume API version to use.
|
||||
# Defaults to 3
|
||||
#
|
||||
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
|
||||
$compute_api_version = 2,
|
||||
$identity_api_version = 3,
|
||||
$image_api_version = 2,
|
||||
$network_api_version = 2,
|
||||
$object_store_api_version = 1,
|
||||
$volume_api_version = 3,
|
||||
) {
|
||||
|
||||
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,44 @@
|
|||
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 %>
|
||||
compute_api_version: <%= @compute_api_version.to_s %>
|
||||
identity_api_version: <%= @identity_api_version.to_s %>
|
||||
image_api_version: <%= @image_api_version.to_s %>
|
||||
network_api_version: <%= @network_api_version.to_s %>
|
||||
object_store_api_version: <%= @object_store_api_version.to_s %>
|
||||
volume_api_version: <%= @volume_api_version.to_s %>
|
||||
<% if @interface -%>
|
||||
interface: <%= @interface %>
|
||||
<% end -%>
|
||||
<% if @region_name -%>
|
||||
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 %>
|
||||
compute_api_version: <%= @compute_api_version.to_s %>
|
||||
identity_api_version: <%= @identity_api_version.to_s %>
|
||||
image_api_version: <%= @image_api_version.to_s %>
|
||||
network_api_version: <%= @network_api_version.to_s %>
|
||||
object_store_api_version: <%= @object_store_api_version.to_s %>
|
||||
volume_api_version: <%= @volume_api_version.to_s %>
|
||||
<% if @interface -%>
|
||||
interface: <%= @interface %>
|
||||
<% end -%>
|
||||
<% if @region_name -%>
|
||||
region_name: <%= @region_name %>
|
||||
<% end -%>
|
||||
<% end -%>
|
Loading…
Reference in New Issue