httpd_configmap_generator 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|