From e7aae87d1b8c96713bf402947ee7973c1707c4b7 Mon Sep 17 00:00:00 2001 From: Jerzy Mikolajczak Date: Thu, 8 Sep 2016 15:46:21 +0200 Subject: [PATCH] Initial version of plugin This plugin: - installs sssd deamon on all OpenStack nodes - sets sssd configuration - makes changes to: * /etc/ssh/sshd_config * /etc/pam.d/common-session This plugin enables SSH authentication with keys stored in LDAP directory Change-Id: I1cdde2f8d16d2a0a5327b9c5f965258640866dd3 --- README.md | 11 ++- components.yaml | 12 --- deployment_scripts/deploy.sh | 4 - .../puppet/manifests/ldap-slaves.pp | 3 + .../provider/sssd_config/ini_setting.rb | 22 +++++ .../lib/puppet/type/sssd_config.rb | 13 +++ .../modules/ldap_slaves/manifests/init.pp | 96 +++++++++++++++++++ .../ldap_slaves/templates/sssd_conf.erb | 24 +++++ deployment_tasks.yaml | 66 ++----------- environment_config.yaml | 89 +++++++++++++++-- metadata.yaml | 33 ++----- network_roles.yaml | 15 --- node_roles.yaml | 13 --- pre_build_hook | 5 - tasks.yaml | 26 ----- volumes.yaml | 7 -- 16 files changed, 262 insertions(+), 177 deletions(-) delete mode 100644 components.yaml delete mode 100755 deployment_scripts/deploy.sh create mode 100644 deployment_scripts/puppet/manifests/ldap-slaves.pp create mode 100644 deployment_scripts/puppet/modules/ldap_slaves/lib/puppet/provider/sssd_config/ini_setting.rb create mode 100644 deployment_scripts/puppet/modules/ldap_slaves/lib/puppet/type/sssd_config.rb create mode 100644 deployment_scripts/puppet/modules/ldap_slaves/manifests/init.pp create mode 100644 deployment_scripts/puppet/modules/ldap_slaves/templates/sssd_conf.erb delete mode 100644 network_roles.yaml delete mode 100644 node_roles.yaml delete mode 100755 pre_build_hook delete mode 100644 tasks.yaml delete mode 100644 volumes.yaml diff --git a/README.md b/README.md index c767768..b9e1f42 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,11 @@ -fuel-plugin-ldap-slaves +LDAP Slaves plugin for Fuel ============ -Plugin description \ No newline at end of file +Fuel plugin that provides the functionality to use external LDAP directory as source for authentication on OpenStack nodes. + +Requirements +------------ + +| Requirement | Version/Comment | +|:---------------------------------|:----------------| +| Mirantis OpenStack compatibility | 9.0 | diff --git a/components.yaml b/components.yaml deleted file mode 100644 index ea90f9f..0000000 --- a/components.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# This file contains wizard components descriptions that are pretty similar to -# the `environment_config.yaml`. -# Please, take a look at following link for the details: -# - https://blueprints.launchpad.net/fuel/+spec/component-registry -# - https://specs.openstack.org/openstack/fuel-specs/specs/8.0/component-registry.html - -- name: additional_service:fuel-plugin-ldap-slaves - compatible: [] - requires: [] - incompatible: [] - label: "Plugin label, that will be shown on UI" - description: "Component description (optional)" diff --git a/deployment_scripts/deploy.sh b/deployment_scripts/deploy.sh deleted file mode 100755 index 7fcbe49..0000000 --- a/deployment_scripts/deploy.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash - -# It's a script which deploys your plugin -echo fuel-plugin-ldap-slaves > /tmp/fuel-plugin-ldap-slaves diff --git a/deployment_scripts/puppet/manifests/ldap-slaves.pp b/deployment_scripts/puppet/manifests/ldap-slaves.pp new file mode 100644 index 0000000..39e89fb --- /dev/null +++ b/deployment_scripts/puppet/manifests/ldap-slaves.pp @@ -0,0 +1,3 @@ +$plugin_settings = parseyaml($astute_settings_yaml) +notice('MODULAR: ldap-slaves') +class {'ldap_slaves': } \ No newline at end of file diff --git a/deployment_scripts/puppet/modules/ldap_slaves/lib/puppet/provider/sssd_config/ini_setting.rb b/deployment_scripts/puppet/modules/ldap_slaves/lib/puppet/provider/sssd_config/ini_setting.rb new file mode 100644 index 0000000..65e7312 --- /dev/null +++ b/deployment_scripts/puppet/modules/ldap_slaves/lib/puppet/provider/sssd_config/ini_setting.rb @@ -0,0 +1,22 @@ +Puppet::Type.type(:sssd_config).provide( + :ini_setting, + :parent => Puppet::Type.type(:ini_setting).provider(:ruby) +) do + def section + if resource[:name].start_with?("domain/") + resource[:name].split('/', 3)[0] + '/' + resource[:name].split('/', 3)[1] + else + resource[:name].split('/', 2).first + end + end + def setting + if resource[:name].start_with?("domain/") + resource[:name].split('/', 3)[2] + else + resource[:name].split('/', 2).last + end + end + def self.file_path + '/etc/sssd/sssd.conf' + end +end \ No newline at end of file diff --git a/deployment_scripts/puppet/modules/ldap_slaves/lib/puppet/type/sssd_config.rb b/deployment_scripts/puppet/modules/ldap_slaves/lib/puppet/type/sssd_config.rb new file mode 100644 index 0000000..a39baac --- /dev/null +++ b/deployment_scripts/puppet/modules/ldap_slaves/lib/puppet/type/sssd_config.rb @@ -0,0 +1,13 @@ +Puppet::Type.newtype(:sssd_config) do + ensurable + newparam(:name, :namevar => true) do + desc 'Section/setting name to manage from sssd.conf' + newvalues(/\S+\/\S+/) + end + newproperty(:value) do + desc 'The value of the setting to define' + munge do |v| + v.to_s.strip + end + end +end \ No newline at end of file diff --git a/deployment_scripts/puppet/modules/ldap_slaves/manifests/init.pp b/deployment_scripts/puppet/modules/ldap_slaves/manifests/init.pp new file mode 100644 index 0000000..465c2d3 --- /dev/null +++ b/deployment_scripts/puppet/modules/ldap_slaves/manifests/init.pp @@ -0,0 +1,96 @@ +class ldap_slaves { + $domain_name = $::plugin_settings['ldap-slaves']['domain_name'] + $uri = $::plugin_settings['ldap-slaves']['uri'] + $binduser = $::plugin_settings['ldap-slaves']['binduser'] + $bindpass = $::plugin_settings['ldap-slaves']['bindpass'] + $use_tls = $::plugin_settings['ldap-slaves']['use_tls'] + $search_base = $::plugin_settings['ldap-slaves']['search_base'] + $access_filter = $::plugin_settings['ldap-slaves']['access_filter'] + $home_directory_attr = $::plugin_settings['ldap-slaves']['home_directory_attr'] + $ssh_key_attr = $::plugin_settings['ldap-slaves']['ssh_key_attr'] + + package { 'libpam-sss': + ensure => 'installed', + } -> + + package { 'libnss-sss': + ensure => 'installed', + } -> + + package { 'libnss-ldap': + ensure => 'installed', + } -> + + package { 'sssd': + ensure => 'installed', + } + + file { '/etc/sssd/sssd.conf': + ensure => present, + content => template('ldap_slaves/sssd_conf.erb'), + mode => 0600, + require => Package['sssd'], + } + + service { 'sssd': + enable => true, + ensure => running, + require => File['/etc/sssd/sssd.conf'], + } + + service { 'ssh': + ensure => running, + } + + $ldap_uri = join(any2array($uri), ',') + + sssd_config { + "domain/${domain_name}/ldap_uri": value => $ldap_uri; + "domain/${domain_name}/ldap_default_bind_dn": value => $binduser; + "domain/${domain_name}/ldap_default_authtok": value => $bindpass; + "domain/${domain_name}/ldap_search_base": value => $search_base; + "domain/${domain_name}/ldap_user_home_directory": value => $home_directory_attr; + "domain/${domain_name}/ldap_user_ssh_public_key": value => $ssh_key_attr; + } + + if $use_tls { + $tls_cacert = $::plugin_settings['ldap-slaves']['tls_cacert'] + $tls_capath = "/etc/ssl/certs/sssd-ldap-ca.crt" + + file { $tls_capath: + ensure => file, + mode => 0644, + content => $tls_cacert, + } + + sssd_config { + "domain/${domain_name}/ldap_tls_cacert": value => $tls_capath; + } + } + + unless empty($ldap_access_filter) { + sssd_config { + "domain/${domain_name}/ldap_access_filter": value => $access_filter; + } + } + + file_line {'sshd_keyscommand': + line => "AuthorizedKeysCommand /usr/bin/sss_ssh_authorizedkeys", + path => '/etc/ssh/sshd_config', + } -> + + file_line {'sshd_keyscommanduser': + line => "AuthorizedKeysCommandUser nobody", + path => '/etc/ssh/sshd_config', + } + + file_line {'sssd_pam': + line => "session\trequired\tpam_mkhomedir.so\tskel=/etc/skel/\tumask=0022", + path => '/etc/pam.d/common-session', + after => "session\trequired\tpam_unix.so ", + } + + File_line['sshd_keyscommanduser'] ~> Service['ssh'] + File['/etc/sssd/sssd.conf'] -> Sssd_config <||> + Sssd_config <||> ~> Service['sssd'] +} \ No newline at end of file diff --git a/deployment_scripts/puppet/modules/ldap_slaves/templates/sssd_conf.erb b/deployment_scripts/puppet/modules/ldap_slaves/templates/sssd_conf.erb new file mode 100644 index 0000000..8c16a33 --- /dev/null +++ b/deployment_scripts/puppet/modules/ldap_slaves/templates/sssd_conf.erb @@ -0,0 +1,24 @@ +[sssd] +config_file_version = 2 +services = nss,pam,sudo,ssh +domains = <%= @domain_name %> + +[nss] +filter_users = root,lightdm,nslcd,dnsmasq,dbus,avahi +filter_groups = root + +[pam] + +[ssh] +debug_level = 6 + +[domain/<%= @domain_name %>] +ldap_schema = rfc2307 +id_provider = ldap +auth_provider = ldap +chpass_provider = ldap +cache_credentials = True +enumerate = false +debug_level = 6 +fallback_homedir = /home/%u +ldap_default_authtok_type = password diff --git a/deployment_tasks.yaml b/deployment_tasks.yaml index 7e7baff..c0fbb68 100644 --- a/deployment_tasks.yaml +++ b/deployment_tasks.yaml @@ -1,62 +1,10 @@ -# These tasks will be merged into deployment graph. Here you -# can specify new tasks for any roles, even built-in ones. - -- id: fuel-plugin-ldap-slaves_role - type: group - role: [fuel-plugin-ldap-slaves_role] - parameters: - strategy: - type: parallel - -- id: fuel-plugin-ldap-slaves-deployment-puppet +- id: ldap-slaves type: puppet - role: [fuel-plugin-ldap-slaves_role] - -# If you do not want to use task-based deployment that is introduced as experimental -# in fuel v8.0 comment code section below this comment, uncomment two lines below it -# and do the same for tasks below. - + role: ['/.*/'] version: 2.0.0 - cross-depends: - - name: deploy_start - cross-depended-by: - - name: deploy_end -# requires: [deploy_start] # version 1.0.0 -# required_for: [deploy_end] - + requires: [tools] + required_for: [netconfig] parameters: - puppet_manifest: "deploy.pp" - puppet_modules: "." - timeout: 3600 - -#- id: fuel-plugin-ldap-slaves-post-deployment-sh -# type: shell -# role: [fuel-plugin-ldap-slaves_role] -# version: 2.0.0 -# cross-depends: -# - name: post_deployment_start -# cross-depended-by: -# - name: post_deployment_end -# # requires: [post_deployment_start] -# # required_for: [post_deployment_end] -# parameters: -# cmd: echo post_deployment_task_executed > /tmp/post_deployment -# retries: 3 -# interval: 20 -# timeout: 180 - -#- id: fuel-plugin-ldap-slaves-pre-deployment-sh -# type: shell -# role: [fuel-plugin-ldap-slaves_role] -# version: 2.0.0 -# cross-depends: -# - name: pre_deployment_start -# cross-depended-by: -# - name: pre_deployment_end -# # requires: [pre_deployment_start] -# # required_for: [pre_deployment_end] -# parameters: -# cmd: echo pre_deployment_task_executed > /tmp/pre_deployment -# retries: 3 -# interval: 20 -# timeout: 180 + puppet_manifest: "puppet/manifests/ldap-slaves.pp" + puppet_modules: "puppet/modules:/etc/puppet/modules" + timeout: 3600 \ No newline at end of file diff --git a/environment_config.yaml b/environment_config.yaml index b0f0848..f0260f4 100644 --- a/environment_config.yaml +++ b/environment_config.yaml @@ -1,11 +1,82 @@ attributes: - metadata: - # Settings group can be one of "general", "security", "compute", "network", - # "storage", "logging", "openstack_services" and "other". - group: 'other' - fuel-plugin-ldap-slaves_text: - value: 'Set default value' - label: 'Text field' - description: 'Description for text field' + domain_name: + value: 'example.com' + label: 'LDAP Domain name' + description: 'Domain name' + weight: 5 + type: text + regex: + source: '^[a-zA-Z0-9._-]+$' + error: 'Domain name contains invalid characters' + uri: + value: + - 'ldaps://example.com' + label: 'LDAP URI' + description: 'LDAP URI' + weight: 10 + type: text_list + min: 1 + max: 64 + regex: + source: '^ldap[s]?:\/\/([a-zA-Z0-9._-]+)(:[0-9]+)?$' + error: 'Not a valid LDAP URI. Should be e.g. ldap://example.com' + binduser: + value: 'cn=ldapreader,ou=ServiceAccounts,dc=example,dc=com' + label: 'LDAP User' + description: 'Account to query LDAP server' + weight: 11 + type: text + regex: + source: '^[a-zA-Z0-9_,=\S\\]+$' + error: "Account name contains invalid character or is empty" + bindpass: + value: 'password' + label: 'LDAP Password' + description: 'Password to query LDAP server' + weight: 12 + type: password + regex: + source: '^\S+$' + error: "Password can't be empty or contain spaces" + use_tls: + value: false + label: 'Use TLS' + description: 'Use TLS when communicating with LDAP server' + weight: 14 + type: checkbox + tls_cacert: + value: '' + label: 'CA Cerificate' + description: 'CA Certificate that signed LDAP server certificate' + weight: 15 + type: textarea + restrictions: + - condition: 'settings:ldap-slaves.use_tls.value == false' + action: 'disable' + regex: + source: '^(-----BEGIN CERTIFICATE-----)(.*[\r\n])+(-----END CERTIFICATE-----[\s\S]*?)$|^$' + error: 'The certificate is not in valid PEM format' + search_base: + value: 'dc=example,dc=com' + label: 'Search base' + description: 'Search base defines the location in the LDAP directory where to start looking for objects' + weight: 20 + type: text + access_filter: + value: '' + label: 'LDAP Access filter' + description: 'Access filter allows to limit access to Openstack Servers to specified group' weight: 25 - type: "text" + type: text + home_directory_attr: + value: 'homeDirectory' + label: 'Home Directory Attribute' + description: 'Attribute name in user object, that holds path to user home directory, that should be created during first login' + weight: 30 + type: text + ssh_key_attr: + value: 'sshPublicKey' + label: 'SSH Public Key Attribute' + description: 'Attribute name in user object, that holds users public key' + weight: 35 + type: text \ No newline at end of file diff --git a/metadata.yaml b/metadata.yaml index 4b41c67..e50c3f6 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -1,34 +1,17 @@ -# Plugin name -name: fuel-plugin-ldap-slaves -# Human-readable name for your plugin -title: Title for fuel-plugin-ldap-slaves plugin -# Plugin version +name: ldap-slaves +title: LDAP Authentication plugin for OpenStack nodes version: '1.0.0' -# Description -description: Please describe your plugin here -# Required fuel version -fuel_version: ['8.0'] -# Specify license of your plugin -licenses: ['Apache License Version 2.0'] -# Specify author or company name -authors: ['Specify author or company name'] -# A link to the plugin's page -homepage: 'https://github.com/openstack/fuel-plugins' -# Specify a group which your plugin implements, possible options: -# network, storage, storage::cinder, storage::glance, hypervisor, -# equipment -groups: [] -# Change `false` to `true` if the plugin can be installed in the environment -# after the deployment. +description: LDAP Slaves plugin for Fuel provides the functionality to use external LDAP directory as source for authentication on OpenStack nodes +fuel_version: ['9.0'] is_hotpluggable: false - -# The plugin is compatible with releases in the list +groups: [network] releases: - os: ubuntu version: mitaka-9.0 mode: ['ha'] deployment_scripts_path: deployment_scripts/ repository_path: repositories/ubuntu - -# Version of plugin package package_version: '4.0.0' +licenses: ['Apache License Version 2.0'] +authors: ['Mirantis'] +homepage: 'https://github.com/openstack/fuel-plugin-ldap-slaves' diff --git a/network_roles.yaml b/network_roles.yaml deleted file mode 100644 index d9d5565..0000000 --- a/network_roles.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# Unique network role name -- id: "example_net_role" - # Role mapping to network - default_mapping: "public" - properties: - # Should be true if network role requires subnet being set - subnet: true - # Should be true if network role requires gateway being set - gateway: false - # List of VIPs to be allocated - vip: - # Unique VIP name - - name: "vip_name" - # Optional linux namespace for VIP - namespace: "haproxy" diff --git a/node_roles.yaml b/node_roles.yaml deleted file mode 100644 index cea2b93..0000000 --- a/node_roles.yaml +++ /dev/null @@ -1,13 +0,0 @@ -fuel-plugin-ldap-slaves_role: - # Role name - name: "Set here the name for the role. This name will be displayed in the Fuel web UI" - # Role description - description: "Write description for your role" - # If primary then during orchestration this role will be - # separated into primary-role and role - has_primary: false - # Assign public IP to node if true - public_ip_required: false - # Weight that will be used to sort out the - # roles on the Fuel web UI - weight: 1000 diff --git a/pre_build_hook b/pre_build_hook deleted file mode 100755 index dc05e98..0000000 --- a/pre_build_hook +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -# Add here any the actions which are required before plugin build -# like packages building, packages downloading from mirrors and so on. -# The script should return 0 if there were no errors. diff --git a/tasks.yaml b/tasks.yaml deleted file mode 100644 index f051697..0000000 --- a/tasks.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# WARNING: `tasks.yaml` will be deprecated in further releases. -# Please, use `deployment_tasks.yaml` to describe tasks instead. - -# This tasks will be applied on controller nodes, -# here you can also specify several roles, for example -# ['cinder', 'compute'] will be applied only on -# cinder and compute nodes -- role: ['controller'] - stage: post_deployment - type: shell - parameters: - cmd: bash deploy.sh - timeout: 42 -# Task is applied for all roles -- role: '*' - stage: pre_deployment - type: shell - parameters: - cmd: echo all > /tmp/plugin.all - timeout: 42 -# "reboot" task reboots the nodes and waits until they get back online -# - role: '*' -# stage: pre_deployment -# type: reboot -# parameters: -# timeout: 600 diff --git a/volumes.yaml b/volumes.yaml deleted file mode 100644 index 70e377f..0000000 --- a/volumes.yaml +++ /dev/null @@ -1,7 +0,0 @@ -volumes_roles_mapping: - # Default role mapping - fuel-plugin-ldap-slaves_role: - - {allocate_size: "min", id: "os"} - -# Set here new volumes for your role -volumes: []