httpd_configmap_generator 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 97e1e062ab6b1f55d36ffe1de318f82892c78d8e
4
- data.tar.gz: 7a88bb96641736bb254238122b722547b61c5ec2
3
+ metadata.gz: 31a8b82ae49621578d09976757d636c2826580cc
4
+ data.tar.gz: a6621e89efda84c979e6635234382984a92dd258
5
5
  SHA512:
6
- metadata.gz: a2476f19b3e2ec40ce2a14cee8946850db609d2dbd5e215129fed1981d807cf34985bf13bc37c31277c0214ce3f97b10761ec4d13b17fb6ac757909acf9777d8
7
- data.tar.gz: 2b34b65675ab369a0821723e08259d06efa1619b168a3e80d019f696eb091dd8301e910454d14afe06611b6202afbdbfd884fe91360ffdbf128c0f584ed8dc05
6
+ metadata.gz: 7897d522c43687e7f0d29ae2519d7c0893d88fed0065e8e5158801a113e6a3af727e9418cf939117a506973eb4e53804b8b1fb890b57ad8e8f2478e62b0033cb
7
+ data.tar.gz: 19163527198bf275ed8990258796ba1f003386ff93ca323ff7a00d44bda2ba6852f25b5ab15698e1073704f37024636d4aff7739f84a4d8e1922ee352486fb8f
@@ -0,0 +1,62 @@
1
+ # Httpd Configmap Generator - LDAP
2
+
3
+ This documents how to run the httpd\_configmap\_generator tool to configure external authentication
4
+ for an LDAP server.
5
+
6
+
7
+ ## Usage for the `ldap` auth-type:
8
+
9
+ ```
10
+ $ httpd_configmap_generator ldap --help
11
+ Options:
12
+ -h, --host=<s> Application Domain
13
+ -o, --output=<s> Configuration map file to create
14
+ -c, --cert-file=<s> Cert File
15
+ -l, --ldap-host=<s> LDAP Directory Host FQDN
16
+ -a, --ldap-mode=<s> ldap | ldaps
17
+ -p, --ldap-basedn=<s> LDAP Directory Base DN
18
+ -f, --force Force configuration if configured already
19
+ -d, --debug Enable debugging
20
+ -g, --ldap-group-name=<s> LDAP Directory Group Name (default: cn)
21
+ -r, --ldap-group-member=<s> Attribute containing the names of the
22
+ group's members (default: member)
23
+ -u, --ldap-group-object-class=<s> The object class of a group entry in
24
+ LDAP (default: groupOfNames)
25
+ -i, --ldap-id-use-start-tls,
26
+ --no-ldap-id-use-start-tls Connection use tls? (default: true)
27
+ -t, --ldap-port=<s> LDAP Directory Port
28
+ -s, --ldap-tls-reqcert=<s> The checks to perform on server
29
+ certificates. (Default: allow)
30
+ -e, --ldap-user-gid-number=<s> LDAP attribute corresponding to the
31
+ user's gid (default: gidNumber)
32
+ -n, --ldap-user-name=<s> LDAP Directory User Name (default: cn)
33
+ -b, --ldap-user-object-class=<s> Object class of a user entry in LDAP
34
+ (default: posixAccount)
35
+ -m, --ldap-user-uid-number=<s> LDAP attribute corresponding to the
36
+ user's id (default: uidNumber)
37
+ --ldap-user-search-base=<s> The user DN search scope
38
+ --ldap-group-search-base=<s> The group DN search scope
39
+ -x, --support-non-posix Supports non-posix user records
40
+ --help Shows this message
41
+ ```
42
+
43
+ ### Example:
44
+
45
+ ```
46
+ $ httpd_configmap_generator ldap \
47
+ --force \
48
+ --host=application.example.com \
49
+ --ldap-mode=ldap \
50
+ --ldap-host=ldap-server.example.com \
51
+ --ldap-port=10389 \
52
+ --ldap-basedn=dc=example,dc=com \
53
+ --ldap-group-name=cn \
54
+ --ldap-group-search-base=ou=groups,dc=example,dc=com \
55
+ --ldap-group-object-class=groupOfNames \
56
+ --ldap-user-name=uid \
57
+ --ldap-user-search-base=ou=users,dc=example,dc=com \
58
+ --ldap-user-object-class=person \
59
+ --cert-file=/etc/openldap/cacerts/apacheds-cert.pem \
60
+ --debug \
61
+ -o /tmp/external-ldap.yaml
62
+ ```
@@ -56,10 +56,10 @@ $ httpd_configmap_generator saml \
56
56
  In the above example, the auth configmap file would include the following files:
57
57
 
58
58
  * /etc/httpd/saml2/
59
- - miqsp-metadata.xml
60
- - miqsp-cert.cert
61
- - miqsp-key.key
59
+ - sp-metadata.xml
60
+ - sp-cert.cert
61
+ - sp-key.key
62
62
  - idp-metadata.xml
63
63
 
64
- For Keycloak, the `miqsp-metadata.xml` file can be imported to create the Client ID for
64
+ For Keycloak, the `sp-metadata.xml` file can be imported to create the Client ID for
65
65
  the `application.example.com` application domain.
data/README.md CHANGED
@@ -28,7 +28,7 @@ httpd_configmap_generator 0.1.1 - External Authentication Configuration script
28
28
 
29
29
  Usage: httpd_configmap_generator auth_type | update | export [--help | options]
30
30
 
31
- supported auth_type: active-directory, ipa, saml
31
+ supported auth_type: active-directory, ipa, ldap, saml
32
32
 
33
33
  httpd_configmap_generator options are:
34
34
  -V, --version Version of the httpd_configmap_generator command
@@ -43,11 +43,12 @@ $ httpd_configmap_generator ipa --help
43
43
 
44
44
  ## Supported Authentication Types
45
45
 
46
- |auth-type | Identity Provider/Environment | for usage: |
47
- |------------------|------------------------------------------------|------------|
48
- | active-directory | Active Directory domain realm join | [README-active-directory](README-active-directory.md) |
49
- | ipa | IPA, IPA 2-factor authentication, IPA/AD Trust | [README-ipa](README-ipa.md) |
50
- | saml | Keycloak, etc. | [README-saml](README-saml.md) |
46
+ |auth-type | Identity Provider/Environment | for usage: |
47
+ |------------------|--------------------------------------------------|-------------------------------------------------------|
48
+ | active-directory | Active Directory domain realm join | [README-active-directory](README-active-directory.md) |
49
+ | ipa | IPA, IPA 2-factor authentication, IPA/AD Trust | [README-ipa](README-ipa.md) |
50
+ | ldap | Ldap directories | [README-ldap](README-ldap.md) |
51
+ | saml | Keycloak, etc. | [README-saml](README-saml.md) |
51
52
 
52
53
  ___
53
54
 
@@ -128,7 +129,7 @@ $ httpd_configmap_generator update \
128
129
  ```
129
130
  $ httpd_configmap_generator update \
130
131
  --input=/tmp/original-auth-configmap.yaml \
131
- --add-file=http://aab-keycloak:8080/auth/realms/miq/protocol/saml/description,/etc/httpd/saml2/idp-metadata.xml,644:root:root \
132
+ --add-file=http://aab-keycloak:8080/auth/realms/testrealm/protocol/saml/description,/etc/httpd/saml2/idp-metadata.xml,644:root:root \
132
133
  --output=/tmp/updated-auth-configmap.yaml
133
134
  ```
134
135
 
@@ -214,7 +215,7 @@ Example for generating a configuration map for IPA:
214
215
 
215
216
  ```
216
217
  $ docker exec $CONFIGMAP_GENERATOR_ID httpd_configmap_generator ipa \
217
- --host=miq-appliance.example.com \
218
+ --host=appliance.example.com \
218
219
  --ipa-server=ipaserver.example.com \
219
220
  --ipa-domain=example.com \
220
221
  --ipa-realm=EXAMPLE.COM \
@@ -261,18 +262,26 @@ ___
261
262
 
262
263
  #### If running without OCI systemd hooks (Minishift)
263
264
 
264
- The httpd-configmap-generator service account must be added to the miq-sysadmin SCC before the Httpd Auth Config pod can run.
265
+ The httpd-configmap-generator service account must be added to the httpd-scc-sysadmin SCC before the Httpd Configmap Generator can run.
265
266
 
266
267
  ##### As Admin
267
268
 
269
+ Create the httpd-scc-sysadmin SCC:
270
+
271
+ ```
272
+ $ oc create -f templates/httpd-scc-sysadmin.yaml
273
+ ```
274
+
275
+ Include the httpd-configmap-generator service account with the new SCC:
276
+
268
277
  ```
269
- $ oc adm policy add-scc-to-user miq-sysadmin system:serviceaccount:<your-namespace>:httpd-configmap-generator
278
+ $ oc adm policy add-scc-to-user httpd-scc-sysadmin system:serviceaccount:<your-namespace>:httpd-configmap-generator
270
279
  ```
271
280
 
272
- Verify that the httpd-configmap-generator service account is now included in the miq-sysadmin SCC:
281
+ Verify that the httpd-configmap-generator service account is now included in the httpd-scc-sysadmin SCC:
273
282
 
274
283
  ```
275
- $ oc describe scc miq-sysadmin | grep Users
284
+ $ oc describe scc httpd-scc-sysadmin | grep Users
276
285
  Users: system:serviceaccount:<your-namespace>:httpd-configmap-generator
277
286
  ```
278
287
 
@@ -284,7 +293,7 @@ Users: system:serviceaccount:<your-namespace>:httpd-configmap-generator
284
293
  $ oc adm policy add-scc-to-user anyuid system:serviceaccount:<your-namespace>:httpd-configmap-generator
285
294
  ```
286
295
 
287
- Verify that the httpd-configmap-generator service account is now included in the miq-sysadmin SCC:
296
+ Verify that the httpd-configmap-generator service account is included in the anyuid SCC:
288
297
 
289
298
  ```
290
299
  $ oc describe scc anyuid | grep Users
@@ -339,7 +348,7 @@ Example configuration:
339
348
 
340
349
  ```
341
350
  $ oc rsh $CONFIGMAP_GENERATOR_POD httpd_configmap_generator ipa \
342
- --host=miq-appliance.example.com \
351
+ --host=appliance.example.com \
343
352
  --ipa-server=ipaserver.example.com \
344
353
  --ipa-domain=example.com \
345
354
  --ipa-realm=EXAMPLE.COM \
@@ -2,6 +2,7 @@ require "httpd_configmap_generator/version"
2
2
  require "httpd_configmap_generator/base"
3
3
  require "httpd_configmap_generator/active_directory"
4
4
  require "httpd_configmap_generator/ipa"
5
+ require "httpd_configmap_generator/ldap"
5
6
  require "httpd_configmap_generator/saml"
6
7
  require "httpd_configmap_generator/update"
7
8
  require "httpd_configmap_generator/export"
@@ -1,8 +1,8 @@
1
1
  require "pathname"
2
2
  require "httpd_configmap_generator/base/command"
3
- require "httpd_configmap_generator/base/config"
3
+ require "httpd_configmap_generator/base/config_helper"
4
4
  require "httpd_configmap_generator/base/config_map"
5
- require "httpd_configmap_generator/base/file"
5
+ require "httpd_configmap_generator/base/file_helper"
6
6
  require "httpd_configmap_generator/base/kerberos"
7
7
  require "httpd_configmap_generator/base/network"
8
8
  require "httpd_configmap_generator/base/pam"
@@ -11,6 +11,13 @@ require "httpd_configmap_generator/base/sssd"
11
11
 
12
12
  module HttpdConfigmapGenerator
13
13
  class Base
14
+ include Command
15
+ include ConfigHelper
16
+ include FileHelper
17
+ include Kerberos
18
+ include Network
19
+ include Pam
20
+
14
21
  APACHE_USER = "apache".freeze
15
22
  HTTP_KEYTAB = "/etc/http.keytab".freeze
16
23
  IPA_COMMAND = "/usr/bin/ipa".freeze
@@ -2,27 +2,29 @@ require "awesome_spawn"
2
2
 
3
3
  module HttpdConfigmapGenerator
4
4
  class Base
5
- def command_run(executable, options = {})
6
- if opts && opts[:debug]
7
- debug_msg("Running Command: #{AwesomeSpawn.build_command_line(executable, options)}")
5
+ module Command
6
+ def command_run(executable, options = {})
7
+ if opts && opts[:debug]
8
+ debug_msg("Running Command: #{AwesomeSpawn.build_command_line(executable, options)}")
9
+ end
10
+ AwesomeSpawn.run(executable, options)
8
11
  end
9
- AwesomeSpawn.run(executable, options)
10
- end
11
12
 
12
- def command_run!(executable, options = {})
13
- if opts && opts[:debug]
14
- debug_msg("Running Command: #{AwesomeSpawn.build_command_line(executable, options)}")
13
+ def command_run!(executable, options = {})
14
+ if opts && opts[:debug]
15
+ debug_msg("Running Command: #{AwesomeSpawn.build_command_line(executable, options)}")
16
+ end
17
+ AwesomeSpawn.run!(executable, options)
15
18
  end
16
- AwesomeSpawn.run!(executable, options)
17
- end
18
19
 
19
- def log_command_error(err)
20
- err_msg("Command Error: #{err}")
21
- if err.kind_of?(AwesomeSpawn::CommandResultError)
22
- err_msg("stdout: #{err.result.output}")
23
- err_msg("stderr: #{err.result.error}")
24
- else
25
- err_msg(err.backtrace)
20
+ def log_command_error(err)
21
+ err_msg("Command Error: #{err}")
22
+ if err.kind_of?(AwesomeSpawn::CommandResultError)
23
+ err_msg("stdout: #{err.result.output}")
24
+ err_msg("stderr: #{err.result.error}")
25
+ else
26
+ err_msg(err.backtrace)
27
+ end
26
28
  end
27
29
  end
28
30
  end
@@ -0,0 +1,15 @@
1
+ require "active_support"
2
+ require "active_support/core_ext" # for Time.current
3
+
4
+ module HttpdConfigmapGenerator
5
+ class Base
6
+ module ConfigHelper
7
+ def config_file_backup(path)
8
+ if File.exist?(path)
9
+ timestamp = Time.current.strftime(TIMESTAMP_FORMAT)
10
+ FileUtils.copy(path, "#{path}.#{timestamp}")
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -84,30 +84,42 @@ module HttpdConfigmapGenerator
84
84
  file_specs = []
85
85
  file_list.each do |file_to_add|
86
86
  file_spec = file_to_add.split(",").map(&:strip)
87
- case file_spec.length
88
- when 1
89
- file = file_spec.first
90
- file_entry = file_entry_spec(file)
91
- when 2
92
- source_file, target_file = file_spec
93
- raise "Must specify a mode for URL file sources" if source_file =~ URI.regexp(%w(http https))
94
- file_entry = file_entry_spec(source_file, target_file)
95
- when 3
96
- source_file, target_file, mode = file_spec
97
- if source_file =~ URI.regexp(%w(http https))
98
- fetch_network_file(source_file, target_file)
99
- file_entry = file_entry_spec(target_file, target_file, mode)
87
+ file_entry =
88
+ case file_spec.length
89
+ when 1
90
+ file_entry_spec(file_spec.first)
91
+ when 2
92
+ source_file, target_file = file_spec
93
+ file_entry_for_source_target(source_file, target_file)
94
+ when 3
95
+ source_file, target_file, mode = file_spec
96
+ file_entry_for_source_target_mode(source_file, target_file, mode)
100
97
  else
101
- file_entry = file_entry_spec(source_file, target_file, mode)
98
+ raise "Invalid file specification #{file_to_add}"
102
99
  end
103
- else
104
- raise "Invalid file specification #{file_to_add}"
105
- end
106
100
  file_specs << file_entry
107
101
  end
108
102
  file_specs.sort_by { |file_spec| file_spec[:basename] }
109
103
  end
110
104
 
105
+ def file_entry_for_source_target(source_file, target_file)
106
+ raise "Must specify a mode for URL file sources" if source_file =~ URI.regexp(%w(http https))
107
+ file_entry = file_entry_spec(source_file, target_file)
108
+ file_entry[:source_file] = source_file
109
+ file_entry
110
+ end
111
+
112
+ def file_entry_for_source_target_mode(source_file, target_file, mode)
113
+ if source_file =~ URI.regexp(%w(http https))
114
+ fetch_network_file(source_file, target_file)
115
+ file_entry = file_entry_spec(target_file, target_file, mode)
116
+ else
117
+ file_entry = file_entry_spec(source_file, target_file, mode)
118
+ file_entry[:source_file] = source_file
119
+ end
120
+ file_entry
121
+ end
122
+
111
123
  def file_entry_spec(source_file, target_file = nil, mode = nil)
112
124
  target_file = source_file.dup unless target_file
113
125
  unless mode
@@ -152,7 +164,7 @@ module HttpdConfigmapGenerator
152
164
 
153
165
  def include_files(file_specs)
154
166
  file_specs.each do |file_spec|
155
- content = File.read(file_spec[:target])
167
+ content = File.read(file_spec[:source_file] || file_spec[:target])
156
168
  content = Base64.encode64(content) if file_spec[:binary]
157
169
  # encode(:universal_newline => true) will convert \r\n to \n, necessary for to_yaml to render properly.
158
170
  config_map[DATA_SECTION].merge!(file_basename(file_spec) => content.encode(:universal_newline => true))
@@ -0,0 +1,67 @@
1
+ require "pathname"
2
+
3
+ module HttpdConfigmapGenerator
4
+ class Base
5
+ module FileHelper
6
+ def template_directory
7
+ @template_directory ||=
8
+ Pathname.new(Gem::Specification.find_by_name("httpd_configmap_generator").full_gem_path).join("templates")
9
+ end
10
+
11
+ def cp_template(file, src_dir, dest_dir = "/")
12
+ src_path = path_join(src_dir, file)
13
+ dest_path = path_join(dest_dir, file.gsub(".erb", ""))
14
+ if src_path.to_s.include?(".erb")
15
+ File.write(dest_path, ERB.new(File.read(src_path), nil, '-').result(binding))
16
+ else
17
+ FileUtils.cp(src_path, dest_path)
18
+ end
19
+ end
20
+
21
+ def delete_target_file(file_path)
22
+ if File.exist?(file_path)
23
+ if opts[:force]
24
+ info_msg("File #{file_path} exists, forcing a delete")
25
+ File.delete(file_path)
26
+ else
27
+ raise "File #{file_path} already exist"
28
+ end
29
+ end
30
+ end
31
+
32
+ def create_target_directory(file_path)
33
+ dirname = File.dirname(file_path)
34
+ return if File.exist?(dirname)
35
+ debug_msg("Creating directory #{dirname} ...")
36
+ FileUtils.mkdir_p(dirname)
37
+ end
38
+
39
+ def rm_file(file, dir = "/")
40
+ path = path_join(dir, file)
41
+ File.delete(path) if File.exist?(path)
42
+ end
43
+
44
+ def path_join(*args)
45
+ path = Pathname.new(args.shift)
46
+ args.each { |path_seg| path = path.join("./#{path_seg}") }
47
+ path
48
+ end
49
+
50
+ def file_binary?(file)
51
+ data = File.read(file)
52
+ ascii = control = binary = total = 0
53
+ data[0..512].each_byte do |c|
54
+ total += 1
55
+ if c < 32
56
+ control += 1
57
+ elsif c >= 32 && c <= 128
58
+ ascii += 1
59
+ else
60
+ binary += 1
61
+ end
62
+ end
63
+ control.to_f / ascii > 0.1 || binary.to_f / ascii > 0.05
64
+ end
65
+ end
66
+ end
67
+ end
@@ -1,13 +1,15 @@
1
1
  module HttpdConfigmapGenerator
2
2
  class Base
3
- def enable_kerberos_dns_lookups
4
- info_msg("Configuring Kerberos DNS Lookups")
5
- config_file_backup(KERBEROS_CONFIG_FILE)
6
- krb5config = File.read(KERBEROS_CONFIG_FILE)
7
- krb5config[/(\s*)dns_lookup_kdc(\s*)=(\s*)(.*)/, 4] = 'true' if krb5config[/(\s*)dns_lookup_kdc(\s*)=/]
8
- krb5config[/(\s*)dns_lookup_realm(\s*)=(\s*)(.*)/, 4] = 'true' if krb5config[/(\s*)dns_lookup_realm(\s*)=/]
9
- debug_msg("- Updating #{KERBEROS_CONFIG_FILE}")
10
- File.write(KERBEROS_CONFIG_FILE, krb5config)
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
- HOSTNAME_COMMAND = "/usr/bin/hostname".freeze
3
+ module Network
4
+ HOSTNAME_COMMAND = "/usr/bin/hostname".freeze
4
5
 
5
- def realm
6
- domain.upcase
7
- end
6
+ def realm
7
+ domain.upcase
8
+ end
8
9
 
9
- def domain
10
- domain_from_host(opts[:host])
11
- end
10
+ def domain
11
+ domain_from_host(opts[:host])
12
+ end
12
13
 
13
- def domain_from_host(host)
14
- host.gsub(/^([^.]+\.)/, '') if host.present? && host.include?('.')
15
- end
14
+ def domain_from_host(host)
15
+ host.gsub(/^([^.]+\.)/, '') if host.present? && host.include?('.')
16
+ end
16
17
 
17
- def host_reachable?(host)
18
- require "net/ping"
19
- Net::Ping::External.new(host).ping
20
- end
18
+ def host_reachable?(host)
19
+ require "net/ping"
20
+ Net::Ping::External.new(host).ping
21
+ end
21
22
 
22
- def update_hostname(host)
23
- command_run!(HOSTNAME_COMMAND, :params => [host]) if command_run(HOSTNAME_COMMAND).output.strip != host
24
- end
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
- def fetch_network_file(source_file, target_file)
27
- require "net/http"
27
+ def fetch_network_file(source_file, target_file)
28
+ require "net/http"
28
29
 
29
- delete_target_file(target_file)
30
- create_target_directory(target_file)
31
- info_msg("Downloading #{source_file} ...")
32
- result = Net::HTTP.get_response(URI(source_file))
33
- raise "Failed to fetch URL file source #{source_file}" unless result.kind_of?(Net::HTTPSuccess)
34
- File.write(target_file, result.body)
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
- def configure_pam
4
- info_msg("Configuring PAM")
5
- debug_msg("- Creating #{PAM_CONFIG}")
6
- cp_template(PAM_CONFIG, template_directory)
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
@@ -0,0 +1,185 @@
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
+ :cert_file => { :description => "Cert File" },
14
+ :ldap_host => { :description => "LDAP Directory Host FQDN" },
15
+ :ldap_mode => { :description => "ldap | ldaps" },
16
+ :ldap_basedn => { :description => "LDAP Directory Base DN" },
17
+ )
18
+ end
19
+
20
+ def optional_options
21
+ super.merge(
22
+ :ldap_group_name => { :description => "LDAP Directory Group Name",
23
+ :default => "cn" },
24
+ :ldap_group_member => { :description => "Attribute containing the names of the group's members",
25
+ :default => "member" },
26
+ :ldap_group_object_class => { :description => "The object class of a group entry in LDAP",
27
+ :default => "groupOfNames" },
28
+ :ldap_id_use_start_tls => { :description => "Connection use tls?",
29
+ :default => true },
30
+ :ldap_port => { :description => "LDAP Directory Port" },
31
+ :ldap_tls_reqcert => { :description => "The checks to perform on server certificates.",
32
+ :default => "allow" },
33
+ :ldap_user_gid_number => { :description => "LDAP attribute corresponding to the user's gid",
34
+ :default => "gidNumber" },
35
+ :ldap_user_name => { :description => "LDAP Directory User Name",
36
+ :default => "cn"},
37
+ :ldap_user_object_class => { :description => "Object class of a user entry in LDAP",
38
+ :default => "posixAccount" },
39
+ :ldap_user_uid_number => { :description => "LDAP attribute corresponding to the user's id",
40
+ :default => "uidNumber" },
41
+ :ldap_user_search_base => { :description => "The user DN search scope" },
42
+ :ldap_group_search_base => { :description => "The group DN search scope" },
43
+ :support_non_posix => { :description => "Suppoert non-posix user records",
44
+ :default => false },
45
+ )
46
+ end
47
+
48
+ def persistent_files
49
+ %w(/etc/nsswitch.conf
50
+ /etc/openldap/ldap.conf
51
+ /etc/pam.d/fingerprint-auth-ac
52
+ /etc/pam.d/httpd-auth
53
+ /etc/pam.d/password-auth-ac
54
+ /etc/pam.d/postlogin-ac
55
+ /etc/pam.d/smartcard-auth-ac
56
+ /etc/pam.d/system-auth-ac
57
+ /etc/sssd/sssd.conf
58
+ /etc/sysconfig/authconfig
59
+ /etc/sysconfig/network) + [opts[:cert_file]]
60
+ end
61
+
62
+ def configure(opts)
63
+ update_hostname(opts[:host])
64
+
65
+ init_search_base
66
+ run_auth_config
67
+ configure_pam
68
+ configure_sssd
69
+ chmod_chown_cert_file
70
+ config_map = ConfigMap.new(opts)
71
+ config_map.generate(AUTH[:type], realm, persistent_files)
72
+ config_map.save(opts[:output])
73
+ rescue => err
74
+ log_command_error(err)
75
+ raise err
76
+ end
77
+
78
+ def unconfigure
79
+ return unless configured?
80
+ raise "Unable to unconfigure authentication against LDAP"
81
+ end
82
+
83
+ def configured?
84
+ File.exist?(SSSD_CONFIG)
85
+ end
86
+
87
+ def domain
88
+ opts[:ldap_basedn].split(",").collect do |p|
89
+ p.split('dc=')[1]
90
+ end.compact.join('.')
91
+ end
92
+
93
+ private
94
+
95
+ def ldapserver_url
96
+ opts[:ldap_port] ||= opts[:ldap_mode].downcase == "ldaps" ? 636 : 389
97
+ "#{opts[:ldap_mode]}://#{opts[:ldap_host]}:#{opts[:ldap_port]}"
98
+ end
99
+
100
+ def init_search_base
101
+ opts[:ldap_user_search_base] = opts[:ldap_basedn] if opts[:ldap_user_search_base] == ""
102
+ opts[:ldap_group_search_base] = opts[:ldap_basedn] if opts[:ldap_group_search_base] == ""
103
+ end
104
+
105
+ def configure_sssd
106
+ info_msg("Configuring SSSD Service")
107
+ sssd = Sssd.new(opts)
108
+ sssd.load(SSSD_CONFIG)
109
+
110
+ sssd.configure_domain("default")
111
+ domain_section = sssd.section("domain/default")
112
+ domain_section["ldap_group_member"] = opts[:ldap_group_member]
113
+ domain_section["ldap_group_name"] = opts[:ldap_group_name]
114
+ domain_section["ldap_group_object_class"] = opts[:ldap_group_object_class]
115
+ domain_section["ldap_group_search_base"] = opts[:ldap_group_search_base]
116
+ domain_section["ldap_id_use_start_tls"] = opts[:ldap_id_use_start_tls]
117
+ domain_section["ldap_network_timeout"] = "3"
118
+ domain_section["ldap_pwd_policy"] = "none"
119
+ domain_section["ldap_tls_cacert"] = opts[:cert_file]
120
+ domain_section["ldap_tls_reqcert"] = opts[:ldap_tls_reqcert]
121
+ domain_section["ldap_user_gid_number"] = opts[:ldap_user_gid_number]
122
+ domain_section["ldap_user_name"] = opts[:ldap_user_name]
123
+ domain_section["ldap_user_object_class"] = opts[:ldap_user_object_class]
124
+ domain_section["ldap_user_search_base"] = opts[:ldap_user_search_base]
125
+ domain_section["ldap_user_uid_number"] = opts[:ldap_user_uid_number]
126
+ domain_section.delete("ldap_tls_cacertdir")
127
+
128
+ sssd_section = sssd.section("sssd")
129
+ sssd_section["config_file_version"] = "2"
130
+ sssd_section["domains"] = domain
131
+ sssd_section["default_domain_suffix"] = domain
132
+ sssd_section["sbus_timeout"] = "30"
133
+ sssd_section["services"] = "nss, pam, ifp"
134
+
135
+ sssd.add_service("pam")
136
+
137
+ sssd.configure_ifp
138
+
139
+ if opts[:support_non_posix]
140
+ sssd.section("pam")["pam_app_services"] = "httpd-auth"
141
+
142
+ debug_msg("- Setting application section to [application/#{domain}]")
143
+ domain_section.key = "application/#{domain}"
144
+
145
+ debug_msg("- Adding domain section to [domain/#{domain}]")
146
+ sssd.section("domain/#{domain}")
147
+ else
148
+ debug_msg("- Setting domain section to [domain/#{domain}]")
149
+ domain_section.key = "domain/#{domain}"
150
+ end
151
+
152
+ debug_msg("- Creating #{SSSD_CONFIG}")
153
+ sssd.save(SSSD_CONFIG)
154
+ end
155
+
156
+ def chmod_chown_cert_file
157
+ FileUtils.chown('root', 'root', opts[:cert_file])
158
+ FileUtils.chmod(0o600, opts[:cert_file])
159
+ end
160
+
161
+ def run_auth_config
162
+ params = {
163
+ :ldapserver= => ldapserver_url,
164
+ :ldapbasedn= => opts[:ldap_basedn],
165
+ :enablesssd => nil,
166
+ :enablesssdauth => nil,
167
+ :enablelocauthorize => nil,
168
+ :enableldap => nil,
169
+ :enableldapauth => nil,
170
+ :disableldaptls => nil,
171
+ :enablerfc2307bis => nil,
172
+ :enablecachecreds => nil,
173
+ :update => nil
174
+ }
175
+
176
+ command_run!(AUTHCONFIG_COMMAND, :params => params)
177
+ end
178
+
179
+ def validate_options(opts)
180
+ super(opts)
181
+ raise "ldap-mode must be one of #{LDAP_MODES.join(", ")}" unless LDAP_MODES.include?(opts[:ldap_mode].downcase)
182
+ raise "TLS certificate File #{opts[:cert_file]} not found" unless File.exist?(opts[:cert_file])
183
+ end
184
+ end
185
+ end
@@ -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
- MIQSP_METADATA_FILE = "#{SAML2_CONFIG_DIRECTORY}/miqsp-metadata.xml".freeze
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",
@@ -24,9 +24,9 @@ module HttpdConfigmapGenerator
24
24
 
25
25
  def persistent_files
26
26
  file_list = %w(
27
- /etc/httpd/saml2/miqsp-key.key
28
- /etc/httpd/saml2/miqsp-cert.cert
29
- /etc/httpd/saml2/miqsp-metadata.xml
27
+ /etc/httpd/saml2/sp-key.key
28
+ /etc/httpd/saml2/sp-cert.cert
29
+ /etc/httpd/saml2/sp-metadata.xml
30
30
  )
31
31
  file_list += [IDP_METADATA_FILE] if opts[:keycloak_add_metadata]
32
32
  file_list
@@ -53,7 +53,7 @@ module HttpdConfigmapGenerator
53
53
  end
54
54
 
55
55
  def configured?
56
- File.exist?(MIQSP_METADATA_FILE)
56
+ File.exist?(SP_METADATA_FILE)
57
57
  end
58
58
 
59
59
  def unconfigure
@@ -76,18 +76,18 @@ module HttpdConfigmapGenerator
76
76
  info_msg("Renaming mellon config files")
77
77
  Dir.chdir(SAML2_CONFIG_DIRECTORY) do
78
78
  Dir.glob("https_*.*") do |mellon_file|
79
- miq_saml2_file = nil
79
+ saml2_file = nil
80
80
  case mellon_file
81
81
  when /^https_.*\.key$/
82
- miq_saml2_file = "miqsp-key.key"
82
+ saml2_file = "sp-key.key"
83
83
  when /^https_.*\.cert$/
84
- miq_saml2_file = "miqsp-cert.cert"
84
+ saml2_file = "sp-cert.cert"
85
85
  when /^https_.*\.xml$/
86
- miq_saml2_file = "miqsp-metadata.xml"
86
+ saml2_file = "sp-metadata.xml"
87
87
  end
88
- if miq_saml2_file
89
- debug_msg("- renaming #{mellon_file} to #{miq_saml2_file}")
90
- File.rename(mellon_file, miq_saml2_file)
88
+ if saml2_file
89
+ debug_msg("- renaming #{mellon_file} to #{saml2_file}")
90
+ File.rename(mellon_file, saml2_file)
91
91
  end
92
92
  end
93
93
  end
@@ -1,3 +1,3 @@
1
1
  module HttpdConfigmapGenerator
2
- VERSION = "0.1.2".freeze
2
+ VERSION = "0.2.0".freeze
3
3
  end
@@ -0,0 +1,38 @@
1
+ allowHostDirVolumePlugin: false
2
+ allowHostIPC: false
3
+ allowHostNetwork: false
4
+ allowHostPID: false
5
+ allowHostPorts: false
6
+ allowPrivilegedContainer: false
7
+ allowedCapabilities:
8
+ apiVersion: v1
9
+ defaultAddCapabilities:
10
+ - SYS_ADMIN
11
+ fsGroup:
12
+ type: RunAsAny
13
+ groups:
14
+ - system:cluster-admins
15
+ kind: SecurityContextConstraints
16
+ metadata:
17
+ annotations:
18
+ kubernetes.io/description: httpd-scc-sysadmin provides all features of the anyuid SCC but allows users to have SYS_ADMIN capabilities. This is the required scc for Pods requiring to run with systemd and the message bus.
19
+ creationTimestamp:
20
+ name: httpd-scc-sysadmin
21
+ priority: 10
22
+ readOnlyRootFilesystem: false
23
+ requiredDropCapabilities:
24
+ - MKNOD
25
+ - SYS_CHROOT
26
+ runAsUser:
27
+ type: RunAsAny
28
+ seLinuxContext:
29
+ type: MustRunAs
30
+ supplementalGroups:
31
+ type: RunAsAny
32
+ users:
33
+ volumes:
34
+ - configMap
35
+ - downwardAPI
36
+ - emptyDir
37
+ - persistentVolumeClaim
38
+ - secret
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpd_configmap_generator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Httpd Auth Config Developers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-26 00:00:00.000000000 Z
11
+ date: 2017-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: codeclimate-test-reporter
@@ -151,6 +151,7 @@ files:
151
151
  - LICENSE
152
152
  - README-active-directory.md
153
153
  - README-ipa.md
154
+ - README-ldap.md
154
155
  - README-saml.md
155
156
  - README.md
156
157
  - Rakefile
@@ -162,9 +163,9 @@ files:
162
163
  - lib/httpd_configmap_generator/active_directory.rb
163
164
  - lib/httpd_configmap_generator/base.rb
164
165
  - lib/httpd_configmap_generator/base/command.rb
165
- - lib/httpd_configmap_generator/base/config.rb
166
+ - lib/httpd_configmap_generator/base/config_helper.rb
166
167
  - lib/httpd_configmap_generator/base/config_map.rb
167
- - lib/httpd_configmap_generator/base/file.rb
168
+ - lib/httpd_configmap_generator/base/file_helper.rb
168
169
  - lib/httpd_configmap_generator/base/kerberos.rb
169
170
  - lib/httpd_configmap_generator/base/network.rb
170
171
  - lib/httpd_configmap_generator/base/pam.rb
@@ -172,11 +173,13 @@ files:
172
173
  - lib/httpd_configmap_generator/base/sssd.rb
173
174
  - lib/httpd_configmap_generator/export.rb
174
175
  - lib/httpd_configmap_generator/ipa.rb
176
+ - lib/httpd_configmap_generator/ldap.rb
175
177
  - lib/httpd_configmap_generator/saml.rb
176
178
  - lib/httpd_configmap_generator/update.rb
177
179
  - lib/httpd_configmap_generator/version.rb
178
180
  - templates/etc/pam.d/httpd-auth
179
181
  - templates/httpd-configmap-generator-template.yaml
182
+ - templates/httpd-scc-sysadmin.yaml
180
183
  homepage: https://github.com/ManageIQ/httpd_configmap_generator
181
184
  licenses:
182
185
  - Apache-2.0
@@ -1,13 +0,0 @@
1
- require "active_support"
2
- require "active_support/core_ext" # for Time.current
3
-
4
- module HttpdConfigmapGenerator
5
- class Base
6
- def config_file_backup(path)
7
- if File.exist?(path)
8
- timestamp = Time.current.strftime(TIMESTAMP_FORMAT)
9
- FileUtils.copy(path, "#{path}.#{timestamp}")
10
- end
11
- end
12
- end
13
- end
@@ -1,65 +0,0 @@
1
- require "pathname"
2
-
3
- module HttpdConfigmapGenerator
4
- class Base
5
- def template_directory
6
- @template_directory ||=
7
- Pathname.new(Gem::Specification.find_by_name("httpd_configmap_generator").full_gem_path).join("templates")
8
- end
9
-
10
- def cp_template(file, src_dir, dest_dir = "/")
11
- src_path = path_join(src_dir, file)
12
- dest_path = path_join(dest_dir, file.gsub(".erb", ""))
13
- if src_path.to_s.include?(".erb")
14
- File.write(dest_path, ERB.new(File.read(src_path), nil, '-').result(binding))
15
- else
16
- FileUtils.cp(src_path, dest_path)
17
- end
18
- end
19
-
20
- def delete_target_file(file_path)
21
- if File.exist?(file_path)
22
- if opts[:force]
23
- info_msg("File #{file_path} exists, forcing a delete")
24
- File.delete(file_path)
25
- else
26
- raise "File #{file_path} already exist"
27
- end
28
- end
29
- end
30
-
31
- def create_target_directory(file_path)
32
- dirname = File.dirname(file_path)
33
- return if File.exist?(dirname)
34
- debug_msg("Creating directory #{dirname} ...")
35
- FileUtils.mkdir_p(dirname)
36
- end
37
-
38
- def rm_file(file, dir = "/")
39
- path = path_join(dir, file)
40
- File.delete(path) if File.exist?(path)
41
- end
42
-
43
- def path_join(*args)
44
- path = Pathname.new(args.shift)
45
- args.each { |path_seg| path = path.join("./#{path_seg}") }
46
- path
47
- end
48
-
49
- def file_binary?(file)
50
- data = File.read(file)
51
- ascii = control = binary = total = 0
52
- data[0..512].each_byte do |c|
53
- total += 1
54
- if c < 32
55
- control += 1
56
- elsif c >= 32 && c <= 128
57
- ascii += 1
58
- else
59
- binary += 1
60
- end
61
- end
62
- control.to_f / ascii > 0.1 || binary.to_f / ascii > 0.05
63
- end
64
- end
65
- end