Skip to content

Commit

Permalink
enable application credential authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
fmoehler committed May 15, 2024
1 parent beb8b2d commit 2813d65
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 19 deletions.
8 changes: 6 additions & 2 deletions jobs/openstack_cpi/spec
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@ properties:
- description: Keystone V3 endpoint
value: http://192.168.0.1:5000/v3
openstack.username:
description: OpenStack user name (required)
description: OpenStack user name (required, if application_credential_id and application_credential_secret are not provided)
openstack.api_key:
description: OpenStack API key (required)
description: OpenStack API key (required, if application_credential_id and application_credential_secret are not provided)
openstack.application_credential_id:
description: OpenStack application credential id (required, if username and api_key are not provided)
openstack.application_credential_secret:
description: OpenStack application credential secret (required, if username and api_key are not provided)
openstack.tenant:
description: OpenStack tenant name (required for Keystone API V2)
openstack.project:
Expand Down
36 changes: 19 additions & 17 deletions jobs/openstack_cpi/templates/cpi.json.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
'properties' => {
'openstack' => {
'auth_url' => p('openstack.auth_url'),
'username' => p('openstack.username'),
'api_key' => p('openstack.api_key'),
'default_key_name' => p('openstack.default_key_name'),
'default_security_groups' => p('openstack.default_security_groups'),
'default_volume_type' => p('openstack.default_volume_type', nil),
Expand All @@ -19,21 +17,25 @@
}

openstack_params = params['cloud']['properties']['openstack']
if_p('openstack.region') { |value| openstack_params['region'] = value }
if_p('openstack.endpoint_type') { |value| openstack_params['endpoint_type'] = value }
if_p('openstack.state_timeout') { |value| openstack_params['state_timeout'] = value }
if_p('openstack.stemcell_public_visibility') { |value| openstack_params['stemcell_public_visibility'] = value }
if_p('openstack.connection_options') { |value| openstack_params['connection_options'] = value }
if_p('openstack.boot_from_volume') { |value| openstack_params['boot_from_volume'] = value }
if_p('openstack.config_drive') { |value| openstack_params['config_drive'] = value }
if_p('openstack.use_dhcp') { |value| openstack_params['use_dhcp'] = value }
if_p('openstack.domain') { |value| openstack_params['domain'] = value }
if_p('openstack.user_domain_name') { |value| openstack_params['user_domain_name'] = value }
if_p('openstack.project_domain_name') { |value| openstack_params['project_domain_name'] = value }
if_p('openstack.project') { |value| openstack_params['project'] = value }
if_p('openstack.project_id') { |value| openstack_params['project_id'] = value }
if_p('openstack.tenant') { |value| openstack_params['tenant'] = value }
if_p('openstack.human_readable_vm_names') { |value| openstack_params['human_readable_vm_names'] = value }
if_p('openstack.application_credential_id') { |value| openstack_params['application_credential_id'] = value }
if_p('openstack.application_credential_secret') { |value| openstack_params['application_credential_secret'] = value }
if_p('openstack.username') { |value| openstack_params['username'] = value }
if_p('openstack.api_key') { |value| openstack_params['api_key'] = value }
if_p('openstack.region') { |value| openstack_params['region'] = value }
if_p('openstack.endpoint_type') { |value| openstack_params['endpoint_type'] = value }
if_p('openstack.state_timeout') { |value| openstack_params['state_timeout'] = value }
if_p('openstack.stemcell_public_visibility') { |value| openstack_params['stemcell_public_visibility'] = value }
if_p('openstack.connection_options') { |value| openstack_params['connection_options'] = value }
if_p('openstack.boot_from_volume') { |value| openstack_params['boot_from_volume'] = value }
if_p('openstack.config_drive') { |value| openstack_params['config_drive'] = value }
if_p('openstack.use_dhcp') { |value| openstack_params['use_dhcp'] = value }
if_p('openstack.domain') { |value| openstack_params['domain'] = value }
if_p('openstack.user_domain_name') { |value| openstack_params['user_domain_name'] = value }
if_p('openstack.project_domain_name') { |value| openstack_params['project_domain_name'] = value }
if_p('openstack.project') { |value| openstack_params['project'] = value }
if_p('openstack.project_id') { |value| openstack_params['project_id'] = value }
if_p('openstack.tenant') { |value| openstack_params['tenant'] = value }
if_p('openstack.human_readable_vm_names') { |value| openstack_params['human_readable_vm_names'] = value }

if_p('openstack.enable_auto_anti_affinity') do
raise "Property 'enable_auto_anti_affinity' is no longer supported. Please remove it from your configuration."
Expand Down
18 changes: 18 additions & 0 deletions src/bosh_openstack_cpi/lib/cloud/openstack/cloud.rb
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,10 @@ def validate_options
user_domain_name = @options['openstack']['user_domain_name']
project_domain_name = @options['openstack']['project_domain_name']
project_id = @options['openstack']['project_id']
username = @options['openstack']['username']
api_key = @options['openstack']['api_key']
application_credential_id = @options['openstack']['application_credential_id']
application_credential_secret = @options['openstack']['application_credential_secret']
schema = Membrane::SchemaParser.parse do
openstack_options_schema = {
'openstack' => {
Expand Down Expand Up @@ -778,6 +782,20 @@ def validate_options
},
optional('agent') => Hash,
}

unless ((username && api_key) || (application_credential_id && application_credential_secret)) ||
(username && api_key && application_credential_id && application_credential_secret)
raise ArgumentError, "Invalid OpenStack cloud properties: '#{username} and #{api_key}' or '#{application_credential_id} and #{application_credential_secret}' is required."
end

if username && api_key
openstack_options_schema['openstack']['username'] = String
openstack_options_schema['openstack']['api_key'] = String
elsif application_credential_id && application_credential_secret
openstack_options_schema['openstack']['application_credential_id'] = String
openstack_options_schema['openstack']['application_credential_secret'] = String
end

if Bosh::OpenStackCloud::Openstack.is_v3(auth_url)
if project_id
openstack_options_schema['openstack']['project_id'] = String
Expand Down
2 changes: 2 additions & 0 deletions src/bosh_openstack_cpi/lib/cloud/openstack/openstack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ def openstack_params(options)
openstack_auth_url: auth_url,
openstack_username: options['username'],
openstack_api_key: options['api_key'],
openstack_application_credential_id: options['application_credential_id'],
openstack_application_credential_secret: options['application_credential_secret'],
openstack_tenant: options['tenant'],
openstack_project_name: options['project'],
openstack_project_id: options['project_id'],
Expand Down
51 changes: 51 additions & 0 deletions src/bosh_openstack_cpi/spec/unit/cloud_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,57 @@
end
end

context 'when checking authentication' do
before do
options['openstack']['auth_url'] = 'http://fake-auth-url/v2.0'
options['openstack']['tenant'] = 'fake-tenant'
end

it 'raises ArgumentError if there are no authentication credentials provided' do
options['openstack']['username'] = nil
options['openstack']['api_key'] = nil

expect { subject }.to raise_error(ArgumentError, /Invalid OpenStack cloud properties/)
end

it 'raises ArgumentError if only api_key is provided' do
options['openstack']['api_key'] = nil

expect { subject }.to raise_error(ArgumentError, /Invalid OpenStack cloud properties/)
end

it 'raises ArgumentError if only username is provided' do
options['openstack']['username'] = nil

expect { subject }.to raise_error(ArgumentError, /Invalid OpenStack cloud properties/)
end

it 'does not raise an error if application credential id and secret are provided' do
options['openstack']['api_key'] = nil
options['openstack']['username'] = nil
options['openstack']['application_credential_id'] = 'fake-application-credential-id'
options['openstack']['application_credential_secret'] = 'fake-application-credential-secret'

expect { subject }.to_not raise_error
end

it 'raises ArgumentError if only application credential id is provided' do
options['openstack']['api_key'] = nil
options['openstack']['username'] = nil
options['openstack']['application_credential_id'] = 'fake-application-credential-id'

expect { subject }.to raise_error(ArgumentError, /Invalid OpenStack cloud properties/)
end

it 'raises ArgumentError if only application credential secret is provided' do
options['openstack']['api_key'] = nil
options['openstack']['username'] = nil
options['openstack']['application_credential_secret'] = 'fake-application-credential-secret'

expect { subject }.to raise_error(ArgumentError, /Invalid OpenStack cloud properties/)
end
end

end

context 'when options are empty' do
Expand Down

0 comments on commit 2813d65

Please sign in to comment.