httpd_configmap_generator 0.1.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.travis.yml +3 -2
- data/.yamllint +11 -0
- data/Dockerfile +3 -2
- data/Gemfile +4 -0
- data/README-active-directory.md +11 -15
- data/README-ipa.md +7 -12
- data/README-ldap.md +62 -0
- data/README-oidc.md +39 -0
- data/README-saml.md +9 -14
- data/README.md +37 -49
- data/bin/httpd_configmap_generator +36 -50
- data/httpd_configmap_generator.gemspec +5 -3
- data/lib/httpd_configmap_generator.rb +2 -0
- data/lib/httpd_configmap_generator/active_directory.rb +2 -2
- data/lib/httpd_configmap_generator/base.rb +10 -6
- data/lib/httpd_configmap_generator/base/command.rb +19 -17
- data/lib/httpd_configmap_generator/base/config_helper.rb +15 -0
- data/lib/httpd_configmap_generator/base/config_map.rb +43 -26
- data/lib/httpd_configmap_generator/base/file_helper.rb +67 -0
- data/lib/httpd_configmap_generator/base/kerberos.rb +10 -8
- data/lib/httpd_configmap_generator/base/network.rb +27 -25
- data/lib/httpd_configmap_generator/base/pam.rb +6 -4
- data/lib/httpd_configmap_generator/base/sssd.rb +1 -1
- data/lib/httpd_configmap_generator/ipa.rb +12 -1
- data/lib/httpd_configmap_generator/ldap.rb +186 -0
- data/lib/httpd_configmap_generator/oidc.rb +48 -0
- data/lib/httpd_configmap_generator/saml.rb +16 -14
- data/lib/httpd_configmap_generator/version.rb +1 -1
- data/templates/httpd-scc-sysadmin.yaml +38 -0
- metadata +18 -14
- data/lib/httpd_configmap_generator/base/config.rb +0 -13
- data/lib/httpd_configmap_generator/base/file.rb +0 -65
- data/lib/httpd_configmap_generator/options.rb +0 -13
@@ -1,13 +1,15 @@
|
|
1
1
|
module HttpdConfigmapGenerator
|
2
2
|
class Base
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
module Kerberos
|
4
|
+
def enable_kerberos_dns_lookups
|
5
|
+
info_msg("Configuring Kerberos DNS Lookups")
|
6
|
+
config_file_backup(KERBEROS_CONFIG_FILE)
|
7
|
+
krb5config = File.read(KERBEROS_CONFIG_FILE)
|
8
|
+
krb5config[/(\s*)dns_lookup_kdc(\s*)=(\s*)(.*)/, 4] = 'true' if krb5config[/(\s*)dns_lookup_kdc(\s*)=/]
|
9
|
+
krb5config[/(\s*)dns_lookup_realm(\s*)=(\s*)(.*)/, 4] = 'true' if krb5config[/(\s*)dns_lookup_realm(\s*)=/]
|
10
|
+
debug_msg("- Updating #{KERBEROS_CONFIG_FILE}")
|
11
|
+
File.write(KERBEROS_CONFIG_FILE, krb5config)
|
12
|
+
end
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
@@ -1,37 +1,39 @@
|
|
1
1
|
module HttpdConfigmapGenerator
|
2
2
|
class Base
|
3
|
-
|
3
|
+
module Network
|
4
|
+
HOSTNAME_COMMAND = "/usr/bin/hostname".freeze
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
def realm
|
7
|
+
domain.upcase
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def domain
|
11
|
+
domain_from_host(opts[:host])
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
def domain_from_host(host)
|
15
|
+
host.gsub(/^([^.]+\.)/, '') if host.present? && host.include?('.')
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
def host_reachable?(host)
|
19
|
+
require "net/ping"
|
20
|
+
Net::Ping::External.new(host).ping
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
def update_hostname(host)
|
24
|
+
command_run!(HOSTNAME_COMMAND, :params => [host]) if command_run(HOSTNAME_COMMAND).output.strip != host
|
25
|
+
end
|
25
26
|
|
26
|
-
|
27
|
-
|
27
|
+
def fetch_network_file(source_file, target_file)
|
28
|
+
require "net/http"
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
delete_target_file(target_file)
|
31
|
+
create_target_directory(target_file)
|
32
|
+
info_msg("Downloading #{source_file} ...")
|
33
|
+
result = Net::HTTP.get_response(URI(source_file))
|
34
|
+
raise "Failed to fetch URL file source #{source_file}" unless result.kind_of?(Net::HTTPSuccess)
|
35
|
+
File.write(target_file, result.body)
|
36
|
+
end
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
module HttpdConfigmapGenerator
|
2
2
|
class Base
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Pam
|
4
|
+
def configure_pam
|
5
|
+
info_msg("Configuring PAM")
|
6
|
+
debug_msg("- Creating #{PAM_CONFIG}")
|
7
|
+
cp_template(PAM_CONFIG, template_directory)
|
8
|
+
end
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -43,7 +43,7 @@ module HttpdConfigmapGenerator
|
|
43
43
|
|
44
44
|
def section(key)
|
45
45
|
if key =~ /^domain\/.*$/
|
46
|
-
key = sssd.entries.collect(&:key).select { |k| k.downcase == key.downcase }.first
|
46
|
+
key = sssd.entries.collect(&:key).select { |k| k.downcase == key.downcase }.first || key
|
47
47
|
end
|
48
48
|
sssd.section(key)
|
49
49
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "socket"
|
2
|
+
|
1
3
|
module HttpdConfigmapGenerator
|
2
4
|
class Ipa < Base
|
3
5
|
IPA_INSTALL_COMMAND = "/usr/sbin/ipa-client-install".freeze
|
@@ -9,7 +11,9 @@ module HttpdConfigmapGenerator
|
|
9
11
|
|
10
12
|
def required_options
|
11
13
|
super.merge(
|
12
|
-
:
|
14
|
+
:host => { :description => "Application Domain",
|
15
|
+
:short => "-h" },
|
16
|
+
:ipa_server => { :description => "IPA Server FQDN" },
|
13
17
|
:ipa_password => { :description => "IPA Server Password" }
|
14
18
|
)
|
15
19
|
end
|
@@ -49,6 +53,7 @@ module HttpdConfigmapGenerator
|
|
49
53
|
end
|
50
54
|
|
51
55
|
def configure(opts)
|
56
|
+
opts[:host] = get_canonical_hostname(opts[:host])
|
52
57
|
update_hostname(opts[:host])
|
53
58
|
command_run!(IPA_INSTALL_COMMAND,
|
54
59
|
:params => [
|
@@ -118,5 +123,11 @@ module HttpdConfigmapGenerator
|
|
118
123
|
FileUtils.chown(APACHE_USER, nil, HTTP_KEYTAB)
|
119
124
|
FileUtils.chmod(0o600, HTTP_KEYTAB)
|
120
125
|
end
|
126
|
+
|
127
|
+
def get_canonical_hostname(hostname)
|
128
|
+
Socket.gethostbyname(hostname)[0]
|
129
|
+
rescue SocketError
|
130
|
+
hostname
|
131
|
+
end
|
121
132
|
end
|
122
133
|
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
module HttpdConfigmapGenerator
|
2
|
+
class Ldap < Base
|
3
|
+
AUTHCONFIG_COMMAND = "/usr/sbin/authconfig".freeze
|
4
|
+
LDAP_MODES = %w(ldap ldaps).freeze
|
5
|
+
|
6
|
+
AUTH = {
|
7
|
+
:type => "external",
|
8
|
+
:subtype => "ldap"
|
9
|
+
}.freeze
|
10
|
+
|
11
|
+
def required_options
|
12
|
+
super.merge(
|
13
|
+
:host => { :description => "Application Domain",
|
14
|
+
:short => "-h" },
|
15
|
+
:cert_file => { :description => "Cert File" },
|
16
|
+
:ldap_host => { :description => "LDAP Directory Host FQDN" },
|
17
|
+
:ldap_mode => { :description => "ldap | ldaps" },
|
18
|
+
:ldap_basedn => { :description => "LDAP Directory Base DN" },
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def optional_options
|
23
|
+
super.merge(
|
24
|
+
:ldap_group_name => { :description => "LDAP Directory Group Name",
|
25
|
+
:default => "cn" },
|
26
|
+
:ldap_group_member => { :description => "Attribute containing the names of the group's members",
|
27
|
+
:default => "member" },
|
28
|
+
:ldap_group_object_class => { :description => "The object class of a group entry in LDAP",
|
29
|
+
:default => "groupOfNames" },
|
30
|
+
:ldap_id_use_start_tls => { :description => "Connection use tls?",
|
31
|
+
:default => true },
|
32
|
+
:ldap_port => { :description => "LDAP Directory Port" },
|
33
|
+
:ldap_tls_reqcert => { :description => "The checks to perform on server certificates.",
|
34
|
+
:default => "allow" },
|
35
|
+
:ldap_user_gid_number => { :description => "LDAP attribute corresponding to the user's gid",
|
36
|
+
:default => "gidNumber" },
|
37
|
+
:ldap_user_name => { :description => "LDAP Directory User Name",
|
38
|
+
:default => "cn"},
|
39
|
+
:ldap_user_object_class => { :description => "Object class of a user entry in LDAP",
|
40
|
+
:default => "posixAccount" },
|
41
|
+
:ldap_user_uid_number => { :description => "LDAP attribute corresponding to the user's id",
|
42
|
+
:default => "uidNumber" },
|
43
|
+
:ldap_user_search_base => { :description => "The user DN search scope" },
|
44
|
+
:ldap_group_search_base => { :description => "The group DN search scope" },
|
45
|
+
:support_non_posix => { :description => "Suppoert non-posix user records",
|
46
|
+
:default => false },
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def persistent_files
|
51
|
+
%w(/etc/nsswitch.conf
|
52
|
+
/etc/openldap/ldap.conf
|
53
|
+
/etc/pam.d/fingerprint-auth-ac
|
54
|
+
/etc/pam.d/httpd-auth
|
55
|
+
/etc/pam.d/password-auth-ac
|
56
|
+
/etc/pam.d/postlogin-ac
|
57
|
+
/etc/pam.d/smartcard-auth-ac
|
58
|
+
/etc/pam.d/system-auth-ac
|
59
|
+
/etc/sssd/sssd.conf
|
60
|
+
/etc/sysconfig/authconfig) + [opts[:cert_file]]
|
61
|
+
end
|
62
|
+
|
63
|
+
def configure(opts)
|
64
|
+
update_hostname(opts[:host])
|
65
|
+
|
66
|
+
init_search_base
|
67
|
+
run_auth_config
|
68
|
+
configure_pam
|
69
|
+
configure_sssd
|
70
|
+
chmod_chown_cert_file
|
71
|
+
config_map = ConfigMap.new(opts)
|
72
|
+
config_map.generate(AUTH[:type], realm, persistent_files)
|
73
|
+
config_map.save(opts[:output])
|
74
|
+
rescue => err
|
75
|
+
log_command_error(err)
|
76
|
+
raise err
|
77
|
+
end
|
78
|
+
|
79
|
+
def unconfigure
|
80
|
+
return unless configured?
|
81
|
+
raise "Unable to unconfigure authentication against LDAP"
|
82
|
+
end
|
83
|
+
|
84
|
+
def configured?
|
85
|
+
File.exist?(SSSD_CONFIG)
|
86
|
+
end
|
87
|
+
|
88
|
+
def domain
|
89
|
+
opts[:ldap_basedn].split(",").collect do |p|
|
90
|
+
p.split('dc=')[1]
|
91
|
+
end.compact.join('.')
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def ldapserver_url
|
97
|
+
opts[:ldap_port] ||= opts[:ldap_mode].downcase == "ldaps" ? 636 : 389
|
98
|
+
"#{opts[:ldap_mode]}://#{opts[:ldap_host]}:#{opts[:ldap_port]}"
|
99
|
+
end
|
100
|
+
|
101
|
+
def init_search_base
|
102
|
+
opts[:ldap_user_search_base] = opts[:ldap_basedn] if opts[:ldap_user_search_base] == ""
|
103
|
+
opts[:ldap_group_search_base] = opts[:ldap_basedn] if opts[:ldap_group_search_base] == ""
|
104
|
+
end
|
105
|
+
|
106
|
+
def configure_sssd
|
107
|
+
info_msg("Configuring SSSD Service")
|
108
|
+
sssd = Sssd.new(opts)
|
109
|
+
sssd.load(SSSD_CONFIG)
|
110
|
+
|
111
|
+
sssd.configure_domain("default")
|
112
|
+
domain_section = sssd.section("domain/default")
|
113
|
+
domain_section["ldap_group_member"] = opts[:ldap_group_member]
|
114
|
+
domain_section["ldap_group_name"] = opts[:ldap_group_name]
|
115
|
+
domain_section["ldap_group_object_class"] = opts[:ldap_group_object_class]
|
116
|
+
domain_section["ldap_group_search_base"] = opts[:ldap_group_search_base]
|
117
|
+
domain_section["ldap_id_use_start_tls"] = opts[:ldap_id_use_start_tls]
|
118
|
+
domain_section["ldap_network_timeout"] = "3"
|
119
|
+
domain_section["ldap_pwd_policy"] = "none"
|
120
|
+
domain_section["ldap_tls_cacert"] = opts[:cert_file]
|
121
|
+
domain_section["ldap_tls_reqcert"] = opts[:ldap_tls_reqcert]
|
122
|
+
domain_section["ldap_user_gid_number"] = opts[:ldap_user_gid_number]
|
123
|
+
domain_section["ldap_user_name"] = opts[:ldap_user_name]
|
124
|
+
domain_section["ldap_user_object_class"] = opts[:ldap_user_object_class]
|
125
|
+
domain_section["ldap_user_search_base"] = opts[:ldap_user_search_base]
|
126
|
+
domain_section["ldap_user_uid_number"] = opts[:ldap_user_uid_number]
|
127
|
+
domain_section.delete("ldap_tls_cacertdir")
|
128
|
+
|
129
|
+
sssd_section = sssd.section("sssd")
|
130
|
+
sssd_section["config_file_version"] = "2"
|
131
|
+
sssd_section["domains"] = domain
|
132
|
+
sssd_section["default_domain_suffix"] = domain
|
133
|
+
sssd_section["sbus_timeout"] = "30"
|
134
|
+
sssd_section["services"] = "nss, pam, ifp"
|
135
|
+
|
136
|
+
sssd.add_service("pam")
|
137
|
+
|
138
|
+
sssd.configure_ifp
|
139
|
+
|
140
|
+
if opts[:support_non_posix]
|
141
|
+
sssd.section("pam")["pam_app_services"] = "httpd-auth"
|
142
|
+
|
143
|
+
debug_msg("- Setting application section to [application/#{domain}]")
|
144
|
+
domain_section.key = "application/#{domain}"
|
145
|
+
|
146
|
+
debug_msg("- Adding domain section to [domain/#{domain}]")
|
147
|
+
sssd.section("domain/#{domain}")
|
148
|
+
else
|
149
|
+
debug_msg("- Setting domain section to [domain/#{domain}]")
|
150
|
+
domain_section.key = "domain/#{domain}"
|
151
|
+
end
|
152
|
+
|
153
|
+
debug_msg("- Creating #{SSSD_CONFIG}")
|
154
|
+
sssd.save(SSSD_CONFIG)
|
155
|
+
end
|
156
|
+
|
157
|
+
def chmod_chown_cert_file
|
158
|
+
FileUtils.chown('root', 'root', opts[:cert_file])
|
159
|
+
FileUtils.chmod(0o600, opts[:cert_file])
|
160
|
+
end
|
161
|
+
|
162
|
+
def run_auth_config
|
163
|
+
params = {
|
164
|
+
:ldapserver= => ldapserver_url,
|
165
|
+
:ldapbasedn= => opts[:ldap_basedn],
|
166
|
+
:enablesssd => nil,
|
167
|
+
:enablesssdauth => nil,
|
168
|
+
:enablelocauthorize => nil,
|
169
|
+
:enableldap => nil,
|
170
|
+
:enableldapauth => nil,
|
171
|
+
:disableldaptls => nil,
|
172
|
+
:enablerfc2307bis => nil,
|
173
|
+
:enablecachecreds => nil,
|
174
|
+
:update => nil
|
175
|
+
}
|
176
|
+
|
177
|
+
command_run!(AUTHCONFIG_COMMAND, :params => params)
|
178
|
+
end
|
179
|
+
|
180
|
+
def validate_options(opts)
|
181
|
+
super(opts)
|
182
|
+
raise "ldap-mode must be one of #{LDAP_MODES.join(", ")}" unless LDAP_MODES.include?(opts[:ldap_mode].downcase)
|
183
|
+
raise "TLS certificate File #{opts[:cert_file]} not found" unless File.exist?(opts[:cert_file])
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module HttpdConfigmapGenerator
|
2
|
+
class Oidc < Base
|
3
|
+
|
4
|
+
AUTH = {
|
5
|
+
:type => "openid-connect",
|
6
|
+
:subtype => "oidc"
|
7
|
+
}.freeze
|
8
|
+
|
9
|
+
def required_options
|
10
|
+
super.merge(
|
11
|
+
:oidc_url => { :description => "OpenID-Connect Provider URL",
|
12
|
+
:short => "-u" },
|
13
|
+
:oidc_client_id => { :description => "OpenID-Connect Provider Client ID",
|
14
|
+
:short => "-i" },
|
15
|
+
:oidc_client_secret => { :description => "OpenID-Connect Provider Client Secret",
|
16
|
+
:short => "-s" },
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def configure(opts)
|
21
|
+
auth_oidc_data = {}
|
22
|
+
auth_oidc_data["auth-oidc-provider-metadata-url"] = opts[:oidc_url]
|
23
|
+
auth_oidc_data["auth-oidc-client-id"] = opts[:oidc_client_id]
|
24
|
+
auth_oidc_data["auth-oidc-client-secret"] = opts[:oidc_client_secret]
|
25
|
+
|
26
|
+
config_map = ConfigMap.new(opts)
|
27
|
+
config_map.generate(AUTH[:type], nil, nil, auth_oidc_data )
|
28
|
+
config_map.save(opts[:output])
|
29
|
+
rescue => err
|
30
|
+
log_command_error(err)
|
31
|
+
raise err
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate_options(opts)
|
35
|
+
super(opts)
|
36
|
+
end
|
37
|
+
|
38
|
+
def configured?
|
39
|
+
false
|
40
|
+
end
|
41
|
+
|
42
|
+
def unconfigure
|
43
|
+
return unless configured?
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
@@ -2,7 +2,7 @@ module HttpdConfigmapGenerator
|
|
2
2
|
class Saml < Base
|
3
3
|
MELLON_CREATE_METADATA_COMMAND = "/usr/libexec/mod_auth_mellon/mellon_create_metadata.sh".freeze
|
4
4
|
SAML2_CONFIG_DIRECTORY = "/etc/httpd/saml2".freeze
|
5
|
-
|
5
|
+
SP_METADATA_FILE = "#{SAML2_CONFIG_DIRECTORY}/sp-metadata.xml".freeze
|
6
6
|
IDP_METADATA_FILE = "#{SAML2_CONFIG_DIRECTORY}/idp-metadata.xml".freeze
|
7
7
|
AUTH = {
|
8
8
|
:type => "saml",
|
@@ -10,23 +10,25 @@ module HttpdConfigmapGenerator
|
|
10
10
|
}.freeze
|
11
11
|
|
12
12
|
def required_options
|
13
|
-
super
|
13
|
+
super.merge(
|
14
|
+
:host => { :description => "Application Domain", :short => "-h" },
|
15
|
+
)
|
14
16
|
end
|
15
17
|
|
16
18
|
def optional_options
|
17
19
|
super.merge(
|
18
20
|
:keycloak_add_metadata => { :description => "Download and add the Keycloak metadata file",
|
19
21
|
:default => false },
|
20
|
-
:keycloak_server => { :description => "Keycloak Server
|
22
|
+
:keycloak_server => { :description => "Keycloak Server FQDN or IP" },
|
21
23
|
:keycloak_realm => { :description => "Keycloak Realm for this client"}
|
22
24
|
)
|
23
25
|
end
|
24
26
|
|
25
27
|
def persistent_files
|
26
28
|
file_list = %w(
|
27
|
-
/etc/httpd/saml2/
|
28
|
-
/etc/httpd/saml2/
|
29
|
-
/etc/httpd/saml2/
|
29
|
+
/etc/httpd/saml2/sp-key.key
|
30
|
+
/etc/httpd/saml2/sp-cert.cert
|
31
|
+
/etc/httpd/saml2/sp-metadata.xml
|
30
32
|
)
|
31
33
|
file_list += [IDP_METADATA_FILE] if opts[:keycloak_add_metadata]
|
32
34
|
file_list
|
@@ -53,7 +55,7 @@ module HttpdConfigmapGenerator
|
|
53
55
|
end
|
54
56
|
|
55
57
|
def configured?
|
56
|
-
File.exist?(
|
58
|
+
File.exist?(SP_METADATA_FILE)
|
57
59
|
end
|
58
60
|
|
59
61
|
def unconfigure
|
@@ -76,18 +78,18 @@ module HttpdConfigmapGenerator
|
|
76
78
|
info_msg("Renaming mellon config files")
|
77
79
|
Dir.chdir(SAML2_CONFIG_DIRECTORY) do
|
78
80
|
Dir.glob("https_*.*") do |mellon_file|
|
79
|
-
|
81
|
+
saml2_file = nil
|
80
82
|
case mellon_file
|
81
83
|
when /^https_.*\.key$/
|
82
|
-
|
84
|
+
saml2_file = "sp-key.key"
|
83
85
|
when /^https_.*\.cert$/
|
84
|
-
|
86
|
+
saml2_file = "sp-cert.cert"
|
85
87
|
when /^https_.*\.xml$/
|
86
|
-
|
88
|
+
saml2_file = "sp-metadata.xml"
|
87
89
|
end
|
88
|
-
if
|
89
|
-
debug_msg("- renaming #{mellon_file} to #{
|
90
|
-
File.rename(mellon_file,
|
90
|
+
if saml2_file
|
91
|
+
debug_msg("- renaming #{mellon_file} to #{saml2_file}")
|
92
|
+
File.rename(mellon_file, saml2_file)
|
91
93
|
end
|
92
94
|
end
|
93
95
|
end
|