manageiq-appliance_console 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +47 -0
- data/.gitignore +12 -0
- data/.rspec +4 -0
- data/.rspec_ci +4 -0
- data/.rubocop.yml +4 -0
- data/.rubocop_cc.yml +5 -0
- data/.rubocop_local.yml +2 -0
- data/.travis.yml +19 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +202 -0
- data/README.md +45 -0
- data/Rakefile +6 -0
- data/bin/appliance_console +661 -0
- data/bin/appliance_console_cli +7 -0
- data/lib/manageiq-appliance_console.rb +51 -0
- data/lib/manageiq/appliance_console/certificate.rb +146 -0
- data/lib/manageiq/appliance_console/certificate_authority.rb +140 -0
- data/lib/manageiq/appliance_console/cli.rb +363 -0
- data/lib/manageiq/appliance_console/database_configuration.rb +286 -0
- data/lib/manageiq/appliance_console/database_maintenance.rb +35 -0
- data/lib/manageiq/appliance_console/database_maintenance_hourly.rb +58 -0
- data/lib/manageiq/appliance_console/database_maintenance_periodic.rb +84 -0
- data/lib/manageiq/appliance_console/database_replication.rb +146 -0
- data/lib/manageiq/appliance_console/database_replication_primary.rb +59 -0
- data/lib/manageiq/appliance_console/database_replication_standby.rb +166 -0
- data/lib/manageiq/appliance_console/date_time_configuration.rb +117 -0
- data/lib/manageiq/appliance_console/errors.rb +5 -0
- data/lib/manageiq/appliance_console/external_auth_options.rb +153 -0
- data/lib/manageiq/appliance_console/external_database_configuration.rb +34 -0
- data/lib/manageiq/appliance_console/external_httpd_authentication.rb +157 -0
- data/lib/manageiq/appliance_console/external_httpd_authentication/external_httpd_configuration.rb +249 -0
- data/lib/manageiq/appliance_console/internal_database_configuration.rb +187 -0
- data/lib/manageiq/appliance_console/key_configuration.rb +118 -0
- data/lib/manageiq/appliance_console/logfile_configuration.rb +117 -0
- data/lib/manageiq/appliance_console/logger.rb +23 -0
- data/lib/manageiq/appliance_console/logging.rb +102 -0
- data/lib/manageiq/appliance_console/logical_volume_management.rb +94 -0
- data/lib/manageiq/appliance_console/principal.rb +46 -0
- data/lib/manageiq/appliance_console/prompts.rb +211 -0
- data/lib/manageiq/appliance_console/scap.rb +53 -0
- data/lib/manageiq/appliance_console/temp_storage_configuration.rb +79 -0
- data/lib/manageiq/appliance_console/timezone_configuration.rb +58 -0
- data/lib/manageiq/appliance_console/utilities.rb +67 -0
- data/lib/manageiq/appliance_console/version.rb +5 -0
- data/locales/appliance/en.yml +42 -0
- data/locales/container/en.yml +30 -0
- data/manageiq-appliance_console.gemspec +40 -0
- data/zanata.xml +7 -0
- metadata +317 -0
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module ManageIQ
|
5
|
+
module ApplianceConsole
|
6
|
+
class ExternalAuthOptions
|
7
|
+
AUTH_PATH = "/authentication".freeze
|
8
|
+
|
9
|
+
EXT_AUTH_OPTIONS = {
|
10
|
+
"#{AUTH_PATH}/sso_enabled" => {:label => "Single Sign-On", :logic => true},
|
11
|
+
"#{AUTH_PATH}/saml_enabled" => {:label => "SAML", :logic => true},
|
12
|
+
"#{AUTH_PATH}/local_login_disabled" => {:label => "Local Login", :logic => false}
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
include ManageIQ::ApplianceConsole::Logging
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@updates = {}
|
19
|
+
@current_config = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def ask_questions
|
23
|
+
@current_config = load_current
|
24
|
+
apply = EXT_AUTH_OPTIONS.keys.count + 1
|
25
|
+
skip = apply + 1
|
26
|
+
selection = 0
|
27
|
+
while selection < apply
|
28
|
+
say("\nExternal Authentication Options:")
|
29
|
+
cnt = 1
|
30
|
+
EXT_AUTH_OPTIONS.keys.each do |key|
|
31
|
+
current_state = selected_value(key)
|
32
|
+
say("#{cnt}) #{selected_verb(key, !current_state)} #{EXT_AUTH_OPTIONS[key][:label]}")
|
33
|
+
cnt += 1
|
34
|
+
end
|
35
|
+
say("#{apply}) Apply updates")
|
36
|
+
say("#{skip}) Skip updates")
|
37
|
+
show_updates
|
38
|
+
selection = ask_for_integer("option number to apply", 1..skip)
|
39
|
+
if selection < apply
|
40
|
+
key = EXT_AUTH_OPTIONS.keys[selection - 1]
|
41
|
+
@updates[key] = !selected_value(key)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
@updates = {} if selection == skip
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def show_updates
|
49
|
+
updates_todo = ""
|
50
|
+
EXT_AUTH_OPTIONS.keys.each do |key|
|
51
|
+
next unless @updates.key?(key)
|
52
|
+
updates_todo << ", " if updates_todo.present?
|
53
|
+
updates_todo << " #{selected_verb(key, @updates[key])} #{EXT_AUTH_OPTIONS[key][:label]}"
|
54
|
+
end
|
55
|
+
updates_to_apply = updates_todo.present? ? "Updates to apply: #{updates_todo}" : ""
|
56
|
+
say("\n#{updates_to_apply}")
|
57
|
+
end
|
58
|
+
|
59
|
+
def selected_value(key)
|
60
|
+
return @updates[key] if @updates.key?(key)
|
61
|
+
return @current_config[key] if @current_config.key?(key)
|
62
|
+
false
|
63
|
+
end
|
64
|
+
|
65
|
+
def selected_verb(key, flag)
|
66
|
+
if EXT_AUTH_OPTIONS[key][:logic]
|
67
|
+
flag ? "Enable" : "Disable"
|
68
|
+
else
|
69
|
+
flag ? "Disable" : "Enable"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def any_updates?
|
74
|
+
@updates.present?
|
75
|
+
end
|
76
|
+
|
77
|
+
def update_configuration(update_hash = nil)
|
78
|
+
update_hash ||= @updates
|
79
|
+
if update_hash.present?
|
80
|
+
say("\nUpdating external authentication options on appliance ...")
|
81
|
+
params = update_hash.collect { |key, value| "#{key}=#{value}" }
|
82
|
+
result = ManageIQ::ApplianceConsole::Utilities.rake_run("evm:settings:set", params)
|
83
|
+
raise parse_errors(result).join(', ') if result.failure?
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# extauth_opts option parser: syntax is key=value,key=value
|
88
|
+
# key is one of the EXT_AUTH_OPTIONS keys.
|
89
|
+
# value is one of 1, true, 0 or false.
|
90
|
+
#
|
91
|
+
def parse(options)
|
92
|
+
parsed_updates = {}
|
93
|
+
options.split(",").each do |keyval|
|
94
|
+
key, val = keyval.split('=')
|
95
|
+
key, val = normalize_key(key.to_s.strip), val.to_s.strip
|
96
|
+
unless EXT_AUTH_OPTIONS.key?(key)
|
97
|
+
message = "Unknown external authentication option #{key} specified"
|
98
|
+
message << ", supported options are #{EXT_AUTH_OPTIONS.keys.join(', ')}"
|
99
|
+
raise message
|
100
|
+
end
|
101
|
+
|
102
|
+
value = option_value(val)
|
103
|
+
raise("Invalid #{key} option value #{val} specified, must be true or false") if value.nil?
|
104
|
+
parsed_updates[key] = value
|
105
|
+
end
|
106
|
+
parsed_updates
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.configured?
|
110
|
+
# DB Up and running
|
111
|
+
true
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def load_current
|
117
|
+
say("\nFetching external authentication options from appliance ...")
|
118
|
+
result = ManageIQ::ApplianceConsole::Utilities.rake_run("evm:settings:get", EXT_AUTH_OPTIONS.keys)
|
119
|
+
|
120
|
+
if result.success?
|
121
|
+
return parse_response(result)
|
122
|
+
else
|
123
|
+
raise parse_errors(result).join(', ')
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def parse_errors(result)
|
128
|
+
result.error.split("\n").collect { |line| line if line =~ /^error: /i }.compact
|
129
|
+
end
|
130
|
+
|
131
|
+
def normalize_key(key)
|
132
|
+
key.include?('/') ? key : "#{AUTH_PATH}/#{key}"
|
133
|
+
end
|
134
|
+
|
135
|
+
def parse_response(result)
|
136
|
+
result.output.split("\n").each_with_object({}) do |line, hash|
|
137
|
+
key, val = line.split("=")
|
138
|
+
hash[key] = parse_value(val)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def option_value(value)
|
143
|
+
return true if value == '1' || value =~ /true/i
|
144
|
+
return false if value == '0' || value =~ /false/i
|
145
|
+
nil
|
146
|
+
end
|
147
|
+
|
148
|
+
def parse_value(value)
|
149
|
+
value.present? ? option_value(value) : false
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ManageIQ
|
2
|
+
module ApplianceConsole
|
3
|
+
class ExternalDatabaseConfiguration < DatabaseConfiguration
|
4
|
+
attr_accessor :action
|
5
|
+
|
6
|
+
def initialize(hash = {})
|
7
|
+
set_defaults
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def set_defaults
|
12
|
+
self.username = "root"
|
13
|
+
self.port = DEFAULT_PORT
|
14
|
+
self.database = "vmdb_production"
|
15
|
+
end
|
16
|
+
|
17
|
+
def activate
|
18
|
+
ask_questions if host.nil?
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def ask_questions
|
23
|
+
create_new_region_questions if action == :create
|
24
|
+
clear_screen
|
25
|
+
say("Database Configuration\n")
|
26
|
+
ask_for_database_credentials(false)
|
27
|
+
end
|
28
|
+
|
29
|
+
def post_activation
|
30
|
+
start_evm
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require "manageiq/appliance_console/external_httpd_authentication/external_httpd_configuration"
|
2
|
+
|
3
|
+
module ManageIQ
|
4
|
+
module ApplianceConsole
|
5
|
+
class ExternalHttpdAuthentication
|
6
|
+
include ExternalHttpdConfiguration
|
7
|
+
|
8
|
+
def initialize(host = nil, options = {})
|
9
|
+
@ipaserver, @domain, @password = nil
|
10
|
+
@host = host
|
11
|
+
@domain = options[:domain] || domain_from_host(host)
|
12
|
+
@realm = options[:realm]
|
13
|
+
@ipaserver = options[:ipaserver]
|
14
|
+
@principal = options[:principal] || "admin"
|
15
|
+
@password = options[:password]
|
16
|
+
@timestamp = Time.now.strftime(TIMESTAMP_FORMAT)
|
17
|
+
|
18
|
+
@ipaserver = fqdn(@ipaserver, @domain)
|
19
|
+
end
|
20
|
+
|
21
|
+
def ask_for_parameters
|
22
|
+
say("\nIPA Server Parameters:\n\n")
|
23
|
+
@ipaserver = ask_for_hostname("IPA Server Hostname", @ipaserver)
|
24
|
+
@domain = ask_for_domain("IPA Server Domain", @domain)
|
25
|
+
@realm = ask_for_string("IPA Server Realm", realm)
|
26
|
+
@principal = ask_for_string("IPA Server Principal", @principal)
|
27
|
+
@password = ask_for_password("IPA Server Principal Password", @password)
|
28
|
+
|
29
|
+
@ipaserver = fqdn(@ipaserver, @domain)
|
30
|
+
end
|
31
|
+
|
32
|
+
def show_parameters
|
33
|
+
say("\nExternal Authentication (httpd) Configuration:\n")
|
34
|
+
say("IPA Server Details:\n")
|
35
|
+
say(" Hostname: #{@ipaserver}\n")
|
36
|
+
say(" Domain: #{@domain}\n")
|
37
|
+
say(" Realm: #{realm}\n")
|
38
|
+
say(" Naming Context: #{domain_naming_context}\n")
|
39
|
+
say(" Principal: #{@principal}\n")
|
40
|
+
end
|
41
|
+
|
42
|
+
def show_current_configuration
|
43
|
+
return unless ipa_client_configured?
|
44
|
+
config = config_file_read(SSSD_CONFIG)
|
45
|
+
say("\nCurrent External Authentication (httpd) Configuration:\n")
|
46
|
+
say("IPA Server Details:\n")
|
47
|
+
say(" Hostname: #{fetch_ipa_configuration("ipa_server", config)}\n")
|
48
|
+
say(" Domain: #{fetch_ipa_configuration("ipa_domain", config)}\n")
|
49
|
+
end
|
50
|
+
|
51
|
+
def ask_questions
|
52
|
+
return false unless valid_environment?
|
53
|
+
ask_for_parameters
|
54
|
+
show_parameters
|
55
|
+
return false unless agree("\nProceed? (Y/N): ")
|
56
|
+
return false unless valid_parameters?(@ipaserver)
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
def activate
|
61
|
+
begin
|
62
|
+
configure_ipa
|
63
|
+
configure_pam
|
64
|
+
configure_sssd
|
65
|
+
configure_ipa_http_service
|
66
|
+
configure_httpd
|
67
|
+
configure_selinux
|
68
|
+
rescue AwesomeSpawn::CommandResultError => e
|
69
|
+
say e.result.output
|
70
|
+
say e.result.error
|
71
|
+
say ""
|
72
|
+
say("Failed to Configure External Authentication - #{e}")
|
73
|
+
return false
|
74
|
+
rescue => e
|
75
|
+
say("Failed to Configure External Authentication - #{e}")
|
76
|
+
return false
|
77
|
+
end
|
78
|
+
true
|
79
|
+
end
|
80
|
+
|
81
|
+
def post_activation
|
82
|
+
say("\nRestarting httpd, if running ...")
|
83
|
+
httpd_service = LinuxAdmin::Service.new("httpd")
|
84
|
+
httpd_service.restart if httpd_service.running?
|
85
|
+
|
86
|
+
say("Restarting sssd and configure it to start on reboots ...")
|
87
|
+
LinuxAdmin::Service.new("sssd").restart.enable
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
def domain_naming_context
|
93
|
+
@domain.split(".").collect { |s| "dc=#{s}" }.join(",")
|
94
|
+
end
|
95
|
+
|
96
|
+
def domain_from_host(host)
|
97
|
+
host.gsub(/^([^.]+\.)/, '') if host && host.include?('.')
|
98
|
+
end
|
99
|
+
|
100
|
+
def fqdn(host, domain)
|
101
|
+
(host && domain && !host.include?(".")) ? "#{host}.#{domain}" : host
|
102
|
+
end
|
103
|
+
|
104
|
+
def realm
|
105
|
+
(@realm || @domain).upcase
|
106
|
+
end
|
107
|
+
|
108
|
+
def configure_ipa
|
109
|
+
say("\nConfiguring IPA (may take a minute) ...")
|
110
|
+
ipa_client_unconfigure if ipa_client_configured?
|
111
|
+
ipa_client_configure(realm, @domain, @ipaserver, @principal, @password)
|
112
|
+
enable_kerberos_dns_lookups
|
113
|
+
end
|
114
|
+
|
115
|
+
def configure_pam
|
116
|
+
say("Configuring pam ...")
|
117
|
+
cp_template(PAM_CONFIG, template_directory)
|
118
|
+
end
|
119
|
+
|
120
|
+
def configure_sssd
|
121
|
+
say("Configuring sssd ...")
|
122
|
+
config = config_file_read(SSSD_CONFIG)
|
123
|
+
configure_sssd_domain(config, @domain)
|
124
|
+
configure_sssd_service(config)
|
125
|
+
configure_sssd_ifp(config)
|
126
|
+
config_file_write(config, SSSD_CONFIG, @timestamp)
|
127
|
+
end
|
128
|
+
|
129
|
+
def configure_ipa_http_service
|
130
|
+
say("Configuring IPA HTTP Service and Keytab ...")
|
131
|
+
AwesomeSpawn.run!("/usr/bin/kinit", :params => [@principal], :stdin_data => @password)
|
132
|
+
service = Principal.new(:hostname => @host, :realm => realm, :service => "HTTP", :ca_name => "ipa")
|
133
|
+
service.register
|
134
|
+
AwesomeSpawn.run!(IPA_GETKEYTAB, :params => {"-s" => @ipaserver, "-k" => HTTP_KEYTAB, "-p" => service.name})
|
135
|
+
FileUtils.chown(APACHE_USER, nil, HTTP_KEYTAB)
|
136
|
+
FileUtils.chmod(0600, HTTP_KEYTAB)
|
137
|
+
end
|
138
|
+
|
139
|
+
def configure_httpd
|
140
|
+
say("Configuring httpd ...")
|
141
|
+
configure_httpd_application
|
142
|
+
end
|
143
|
+
|
144
|
+
def configure_selinux
|
145
|
+
say("Configuring SELinux ...")
|
146
|
+
get_enforce = AwesomeSpawn.run!(GETENFORCE_COMMAND)
|
147
|
+
if get_enforce.output.downcase.include?("disabled")
|
148
|
+
say("SELinux is Disabled")
|
149
|
+
else
|
150
|
+
AwesomeSpawn.run!("#{SETSEBOOL_COMMAND} -P allow_httpd_mod_auth_pam on")
|
151
|
+
result = AwesomeSpawn.run("#{GETSEBOOL_COMMAND} httpd_dbus_sssd")
|
152
|
+
AwesomeSpawn.run!("#{SETSEBOOL_COMMAND} -P httpd_dbus_sssd on") if result.exit_status == 0
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
data/lib/manageiq/appliance_console/external_httpd_authentication/external_httpd_configuration.rb
ADDED
@@ -0,0 +1,249 @@
|
|
1
|
+
require 'active_support/core_ext/module/delegation'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
module ManageIQ
|
5
|
+
module ApplianceConsole
|
6
|
+
class ExternalHttpdAuthentication
|
7
|
+
module ExternalHttpdConfiguration
|
8
|
+
#
|
9
|
+
# External Authentication Definitions
|
10
|
+
#
|
11
|
+
IPA_COMMAND = "/usr/bin/ipa".freeze
|
12
|
+
IPA_INSTALL_COMMAND = "/usr/sbin/ipa-client-install".freeze
|
13
|
+
IPA_GETKEYTAB = "/usr/sbin/ipa-getkeytab".freeze
|
14
|
+
|
15
|
+
KERBEROS_CONFIG_FILE = "/etc/krb5.conf".freeze
|
16
|
+
|
17
|
+
SSSD_CONFIG = "/etc/sssd/sssd.conf".freeze
|
18
|
+
PAM_CONFIG = "/etc/pam.d/httpd-auth".freeze
|
19
|
+
HTTP_KEYTAB = "/etc/http.keytab".freeze
|
20
|
+
HTTP_REMOTE_USER = "/etc/httpd/conf.d/manageiq-remote-user.conf".freeze
|
21
|
+
HTTP_EXTERNAL_AUTH = "/etc/httpd/conf.d/manageiq-external-auth.conf".freeze
|
22
|
+
HTTP_EXTERNAL_AUTH_TEMPLATE = "#{HTTP_EXTERNAL_AUTH}.erb".freeze
|
23
|
+
|
24
|
+
GETSEBOOL_COMMAND = "/usr/sbin/getsebool".freeze
|
25
|
+
SETSEBOOL_COMMAND = "/usr/sbin/setsebool".freeze
|
26
|
+
GETENFORCE_COMMAND = "/usr/sbin/getenforce".freeze
|
27
|
+
|
28
|
+
APACHE_USER = "apache".freeze
|
29
|
+
|
30
|
+
TIMESTAMP_FORMAT = "%Y%m%d_%H%M%S".freeze
|
31
|
+
|
32
|
+
LDAP_ATTRS = {
|
33
|
+
"mail" => "REMOTE_USER_EMAIL",
|
34
|
+
"givenname" => "REMOTE_USER_FIRSTNAME",
|
35
|
+
"sn" => "REMOTE_USER_LASTNAME",
|
36
|
+
"displayname" => "REMOTE_USER_FULLNAME",
|
37
|
+
"domainname" => "REMOTE_USER_DOMAIN"
|
38
|
+
}.freeze
|
39
|
+
|
40
|
+
def template_directory
|
41
|
+
Pathname.new(ENV.fetch("APPLIANCE_TEMPLATE_DIRECTORY"))
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# IPA Configuration Methods
|
46
|
+
#
|
47
|
+
def ipa_client_configure(realm, domain, server, principal, password)
|
48
|
+
say("Configuring the IPA Client ...")
|
49
|
+
AwesomeSpawn.run!(IPA_INSTALL_COMMAND,
|
50
|
+
:params => [
|
51
|
+
"-N", :force_join, :fixed_primary, :unattended, {
|
52
|
+
:realm= => realm,
|
53
|
+
:domain= => domain,
|
54
|
+
:server= => server,
|
55
|
+
:principal= => principal,
|
56
|
+
:password= => password
|
57
|
+
}
|
58
|
+
])
|
59
|
+
end
|
60
|
+
|
61
|
+
def deactivate
|
62
|
+
ipa_client_unconfigure
|
63
|
+
unconfigure_httpd
|
64
|
+
end
|
65
|
+
|
66
|
+
def ipa_client_unconfigure
|
67
|
+
say("Un-Configuring the IPA Client ...")
|
68
|
+
AwesomeSpawn.run(IPA_INSTALL_COMMAND, :params => [:uninstall, :unattended])
|
69
|
+
end
|
70
|
+
|
71
|
+
def unconfigure_httpd
|
72
|
+
say("Unconfiguring httpd ...")
|
73
|
+
unconfigure_httpd_application
|
74
|
+
|
75
|
+
say("Restarting httpd ...")
|
76
|
+
LinuxAdmin::Service.new("httpd").restart
|
77
|
+
end
|
78
|
+
|
79
|
+
def configure_httpd_application
|
80
|
+
cp_template(HTTP_EXTERNAL_AUTH_TEMPLATE, template_directory)
|
81
|
+
cp_template(HTTP_REMOTE_USER, template_directory)
|
82
|
+
end
|
83
|
+
|
84
|
+
def unconfigure_httpd_application
|
85
|
+
rm_file(HTTP_EXTERNAL_AUTH)
|
86
|
+
rm_file(HTTP_REMOTE_USER)
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
# Kerberos KRB5 File Methods
|
91
|
+
#
|
92
|
+
def enable_kerberos_dns_lookups
|
93
|
+
FileUtils.copy(KERBEROS_CONFIG_FILE, "#{KERBEROS_CONFIG_FILE}.miqbkp")
|
94
|
+
krb5config = File.read(KERBEROS_CONFIG_FILE)
|
95
|
+
krb5config[/(\s*)dns_lookup_kdc(\s*)=(\s*)(.*)/, 4] = 'true'
|
96
|
+
krb5config[/(\s*)dns_lookup_realm(\s*)=(\s*)(.*)/, 4] = 'true'
|
97
|
+
File.write(KERBEROS_CONFIG_FILE, krb5config)
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# SSSD File Methods
|
102
|
+
#
|
103
|
+
def configure_sssd_domain(config, domain)
|
104
|
+
ldap_user_extra_attrs = LDAP_ATTRS.keys.join(", ")
|
105
|
+
if config.include?("ldap_user_extra_attrs = ")
|
106
|
+
pattern = "[domain/#{Regexp.escape(domain)}](\n.*)+ldap_user_extra_attrs = (.*)"
|
107
|
+
config[/#{pattern}/, 2] = ldap_user_extra_attrs
|
108
|
+
else
|
109
|
+
pattern = "[domain/#{Regexp.escape(domain)}].*(\n)"
|
110
|
+
config[/#{pattern}/, 1] = "\nldap_user_extra_attrs = #{ldap_user_extra_attrs}\n"
|
111
|
+
end
|
112
|
+
|
113
|
+
pattern = "[domain/#{Regexp.escape(domain)}].*(\n)"
|
114
|
+
config[/#{pattern}/, 1] = "\nentry_cache_timeout = 600\n"
|
115
|
+
end
|
116
|
+
|
117
|
+
def configure_sssd_service(config)
|
118
|
+
services = config.match(/\[sssd\](\n.*)+services = (.*)/)[2]
|
119
|
+
services = "#{services}, ifp" unless services.include?("ifp")
|
120
|
+
config[/\[sssd\](\n.*)+services = (.*)/, 2] = services
|
121
|
+
end
|
122
|
+
|
123
|
+
def configure_sssd_ifp(config)
|
124
|
+
user_attributes = LDAP_ATTRS.keys.collect { |k| "+#{k}" }.join(", ")
|
125
|
+
ifp_config = "
|
126
|
+
allowed_uids = #{APACHE_USER}, root
|
127
|
+
user_attributes = #{user_attributes}
|
128
|
+
"
|
129
|
+
if config.include?("[ifp]")
|
130
|
+
if config[/\[ifp\](\n.*)+user_attributes = (.*)/]
|
131
|
+
config[/\[ifp\](\n.*)+user_attributes = (.*)/, 2] = user_attributes
|
132
|
+
else
|
133
|
+
config[/\[ifp\](\n)/, 1] = ifp_config
|
134
|
+
end
|
135
|
+
else
|
136
|
+
config << "\n[ifp]#{ifp_config}\n"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
#
|
141
|
+
# Validation Methods
|
142
|
+
#
|
143
|
+
def installation_valid?
|
144
|
+
installed_rpm_packages = LinuxAdmin::Rpm.list_installed.keys
|
145
|
+
rpm_packages = %w(ipa-client sssd-dbus mod_intercept_form_submit mod_authnz_pam mod_lookup_identity)
|
146
|
+
|
147
|
+
missing = rpm_packages.count do |package|
|
148
|
+
installed = installed_rpm_packages.include?(package)
|
149
|
+
say("#{package} RPM is not installed") unless installed
|
150
|
+
!installed
|
151
|
+
end
|
152
|
+
|
153
|
+
if missing > 0
|
154
|
+
say("\nAppliance Installation is not valid for enabling External Authentication\n")
|
155
|
+
return false
|
156
|
+
end
|
157
|
+
|
158
|
+
true
|
159
|
+
end
|
160
|
+
|
161
|
+
def valid_environment?
|
162
|
+
return false unless installation_valid?
|
163
|
+
if ipa_client_configured?
|
164
|
+
show_current_configuration
|
165
|
+
return false unless agree("\nIPA Client already configured on this Appliance, Un-Configure first? (Y/N): ")
|
166
|
+
deactivate
|
167
|
+
return false unless agree("\nProceed with External Authentication Configuration? (Y/N): ")
|
168
|
+
end
|
169
|
+
true
|
170
|
+
end
|
171
|
+
|
172
|
+
def valid_parameters?(ipaserver)
|
173
|
+
host_reachable?(ipaserver, "IPA Server")
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
# Config File I/O Methods
|
178
|
+
#
|
179
|
+
def config_file_write(config, path, timestamp)
|
180
|
+
FileUtils.copy(path, "#{path}.#{timestamp}") if File.exist?(path)
|
181
|
+
File.open(path, "w") { |f| f.write(config) }
|
182
|
+
end
|
183
|
+
|
184
|
+
#
|
185
|
+
# Network validation
|
186
|
+
#
|
187
|
+
def host_reachable?(host, what = "Server")
|
188
|
+
require 'net/ping'
|
189
|
+
say("Checking connectivity to #{host} ... ")
|
190
|
+
unless Net::Ping::External.new(host).ping
|
191
|
+
say("Failed.\nCould not connect to #{host},")
|
192
|
+
say("the #{what} must be reachable by name.")
|
193
|
+
return false
|
194
|
+
end
|
195
|
+
say("Succeeded.")
|
196
|
+
true
|
197
|
+
end
|
198
|
+
|
199
|
+
def cp_template(file, src_dir, dest_dir = "/")
|
200
|
+
src_path = path_join(src_dir, file)
|
201
|
+
dest_path = path_join(dest_dir, file.gsub(".erb", ""))
|
202
|
+
if src_path.to_s.include?(".erb")
|
203
|
+
File.write(dest_path, ERB.new(File.read(src_path), nil, '-').result(binding))
|
204
|
+
else
|
205
|
+
FileUtils.cp src_path, dest_path
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def rm_file(file, dir = "/")
|
210
|
+
path = path_join(dir, file)
|
211
|
+
File.delete(path) if File.exist?(path)
|
212
|
+
end
|
213
|
+
|
214
|
+
def path_join(*args)
|
215
|
+
path = Pathname.new(args.shift)
|
216
|
+
args.each { |path_seg| path = path.join("./#{path_seg}") }
|
217
|
+
path
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def self.config_status
|
222
|
+
fetch_ipa_configuration("ipa_server") || fetch_sssd_domain || "not configured"
|
223
|
+
end
|
224
|
+
|
225
|
+
def self.ipa_client_configured?
|
226
|
+
File.exist?(SSSD_CONFIG)
|
227
|
+
end
|
228
|
+
|
229
|
+
def self.config_file_read(path)
|
230
|
+
File.read(path)
|
231
|
+
end
|
232
|
+
|
233
|
+
def self.fetch_ipa_configuration(what, config = nil)
|
234
|
+
unless config
|
235
|
+
return nil unless ipa_client_configured?
|
236
|
+
config = config_file_read(SSSD_CONFIG)
|
237
|
+
end
|
238
|
+
pattern = "[domain/.*].*(\n.*)+#{Regexp.escape(what)} = (.*)"
|
239
|
+
config[/#{pattern}/, 2]
|
240
|
+
end
|
241
|
+
|
242
|
+
def self.fetch_sssd_domain
|
243
|
+
config_file_read(SSSD_CONFIG)[/\[domain\/(.*)\]/, 1] if File.exist?(SSSD_CONFIG)
|
244
|
+
end
|
245
|
+
|
246
|
+
delegate :ipa_client_configured?, :config_file_read, :fetch_ipa_configuration, :config_status, :to => self
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|