httpd_configmap_generator 0.1.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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/.travis.yml +14 -0
- data/Dockerfile +16 -0
- data/Gemfile +4 -0
- data/LICENSE +201 -0
- data/README-active-directory.md +38 -0
- data/README-ipa.md +41 -0
- data/README-saml.md +70 -0
- data/README.md +386 -0
- data/Rakefile +8 -0
- data/bin/httpd_configmap_generator +101 -0
- data/httpd_configmap_generator.gemspec +34 -0
- data/lib/httpd_configmap_generator.rb +29 -0
- data/lib/httpd_configmap_generator/active_directory.rb +114 -0
- data/lib/httpd_configmap_generator/base.rb +83 -0
- data/lib/httpd_configmap_generator/base/command.rb +29 -0
- data/lib/httpd_configmap_generator/base/config.rb +13 -0
- data/lib/httpd_configmap_generator/base/config_map.rb +183 -0
- data/lib/httpd_configmap_generator/base/file.rb +66 -0
- data/lib/httpd_configmap_generator/base/kerberos.rb +13 -0
- data/lib/httpd_configmap_generator/base/network.rb +37 -0
- data/lib/httpd_configmap_generator/base/pam.rb +9 -0
- data/lib/httpd_configmap_generator/base/principal.rb +33 -0
- data/lib/httpd_configmap_generator/base/sssd.rb +51 -0
- data/lib/httpd_configmap_generator/export.rb +31 -0
- data/lib/httpd_configmap_generator/ipa.rb +122 -0
- data/lib/httpd_configmap_generator/options.rb +13 -0
- data/lib/httpd_configmap_generator/saml.rb +104 -0
- data/lib/httpd_configmap_generator/update.rb +39 -0
- data/lib/httpd_configmap_generator/version.rb +3 -0
- data/templates/etc/pam.d/httpd-auth +2 -0
- data/templates/httpd-configmap-generator-template.yaml +113 -0
- metadata +203 -0
data/Rakefile
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Script for configuring container with external authentication
|
4
|
+
#
|
5
|
+
# Stdout: standard processing messages ...
|
6
|
+
# Stderr: any errors during configuration ...
|
7
|
+
# -o filename: for the generated auth-config map.
|
8
|
+
#
|
9
|
+
|
10
|
+
require "bundler/setup"
|
11
|
+
require "trollop"
|
12
|
+
require "httpd_configmap_generator"
|
13
|
+
|
14
|
+
CMD = File.basename($PROGRAM_NAME)
|
15
|
+
|
16
|
+
def error_msg(msg)
|
17
|
+
$stderr.puts msg
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
|
21
|
+
module HttpdConfigmapGenerator
|
22
|
+
class Cli
|
23
|
+
def parse_arguments(auth_config)
|
24
|
+
opts = Trollop.options do
|
25
|
+
version("#{CMD} #{HttpdConfigmapGenerator::VERSION} - External Authentication Configuration script")
|
26
|
+
banner <<-EOS
|
27
|
+
#{version}
|
28
|
+
|
29
|
+
Usage: #{CMD} auth_type | update | export [--help | options]
|
30
|
+
|
31
|
+
#{CMD} options are:
|
32
|
+
EOS
|
33
|
+
opt :version, "Version of the #{CMD} command",
|
34
|
+
:default => false, :short => "-V"
|
35
|
+
auth_config.required_options.each do |key, key_options|
|
36
|
+
opt key, key_options[:description], HttpdConfigmapGenerator::Cli.options_for(key_options, true)
|
37
|
+
end
|
38
|
+
auth_config.optional_options.each do |key, key_options|
|
39
|
+
opt key, key_options[:description], HttpdConfigmapGenerator::Cli.options_for(key_options)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
opts
|
43
|
+
end
|
44
|
+
|
45
|
+
def run_configure(auth_type)
|
46
|
+
begin
|
47
|
+
auth_config = HttpdConfigmapGenerator.new_config(auth_type)
|
48
|
+
rescue => err
|
49
|
+
error_msg(err.to_s)
|
50
|
+
end
|
51
|
+
|
52
|
+
auth_config.run_configure(parse_arguments(auth_config))
|
53
|
+
end
|
54
|
+
|
55
|
+
def run_update
|
56
|
+
begin
|
57
|
+
auth_config = HttpdConfigmapGenerator::Update.new
|
58
|
+
rescue => err
|
59
|
+
error_msg(err.to_s)
|
60
|
+
end
|
61
|
+
|
62
|
+
auth_config.update(parse_arguments(auth_config))
|
63
|
+
end
|
64
|
+
|
65
|
+
def run_export
|
66
|
+
begin
|
67
|
+
auth_config = HttpdConfigmapGenerator::Export.new
|
68
|
+
rescue => err
|
69
|
+
error_msg(err.to_s)
|
70
|
+
end
|
71
|
+
|
72
|
+
auth_config.export(parse_arguments(auth_config))
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.options_for(key_options, required = false)
|
76
|
+
options = {}
|
77
|
+
options[:default] = key_options.key?(:default) ? key_options[:default] : ""
|
78
|
+
options[:required] = true if required
|
79
|
+
options[:short] = key_options[:short] if key_options[:short]
|
80
|
+
options[:multi] = key_options[:multi] if key_options[:multi]
|
81
|
+
options
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
if ARGV.empty?
|
87
|
+
error_msg("
|
88
|
+
Usage: #{CMD} auth_type | update | export [--help | options]
|
89
|
+
Supported auth_type: #{HttpdConfigmapGenerator.supported_auth_types.join(', ')}
|
90
|
+
")
|
91
|
+
else
|
92
|
+
auth_type = ARGV.shift
|
93
|
+
case auth_type
|
94
|
+
when "update"
|
95
|
+
HttpdConfigmapGenerator::Cli.new.run_update
|
96
|
+
when "export"
|
97
|
+
HttpdConfigmapGenerator::Cli.new.run_export
|
98
|
+
else
|
99
|
+
HttpdConfigmapGenerator::Cli.new.run_configure(auth_type)
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
# Declare Gem's Version
|
5
|
+
require "httpd_configmap_generator/version"
|
6
|
+
|
7
|
+
# Declare Dependencies
|
8
|
+
Gem::Specification.new do |s|
|
9
|
+
s.name = "httpd_configmap_generator"
|
10
|
+
s.version = HttpdConfigmapGenerator::VERSION
|
11
|
+
s.authors = ["Httpd Auth Config Developers"]
|
12
|
+
s.homepage = "https://github.com/ManageIQ/httpd_configmap_generator"
|
13
|
+
s.summary = "The Httpd Configmap Generator"
|
14
|
+
s.description = "The Httpd Configmap Generator"
|
15
|
+
s.licenses = ["Apache-2.0"]
|
16
|
+
|
17
|
+
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
s.bindir = "bin"
|
21
|
+
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
|
+
s.require_paths = ["lib"]
|
23
|
+
|
24
|
+
s.add_development_dependency "codeclimate-test-reporter", "~> 1.0.0"
|
25
|
+
s.add_development_dependency "rspec", "~> 3.0"
|
26
|
+
s.add_development_dependency "rake"
|
27
|
+
s.add_development_dependency "simplecov"
|
28
|
+
|
29
|
+
s.add_dependency "activesupport", ">=5.0"
|
30
|
+
s.add_dependency "awesome_spawn", "~> 1.4"
|
31
|
+
s.add_dependency "iniparse", "~> 1.4"
|
32
|
+
s.add_dependency "more_core_extensions", "~> 3.4"
|
33
|
+
s.add_dependency "trollop", "~> 2.1"
|
34
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "httpd_configmap_generator/version"
|
2
|
+
require "httpd_configmap_generator/base"
|
3
|
+
require "httpd_configmap_generator/active_directory"
|
4
|
+
require "httpd_configmap_generator/ipa"
|
5
|
+
require "httpd_configmap_generator/saml"
|
6
|
+
require "httpd_configmap_generator/update"
|
7
|
+
require "httpd_configmap_generator/export"
|
8
|
+
require "more_core_extensions/core_ext/hash"
|
9
|
+
|
10
|
+
module HttpdConfigmapGenerator
|
11
|
+
def self.new_config(auth_type)
|
12
|
+
auth_class(auth_type).new
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.supported_auth_types
|
16
|
+
constants.collect do |c|
|
17
|
+
k = const_get(c)
|
18
|
+
k::AUTH[:subtype] if k.kind_of?(Class) && k.constants.include?(:AUTH)
|
19
|
+
end.compact
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.auth_class(auth_type)
|
23
|
+
require "active_support/core_ext/string" # for camelize
|
24
|
+
|
25
|
+
auth_type = auth_type.tr('-', '_').camelize
|
26
|
+
raise "Invalid Authentication Type #{auth_type} specified" unless const_defined?(auth_type, false)
|
27
|
+
const_get(auth_type, false)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module HttpdConfigmapGenerator
|
2
|
+
class ActiveDirectory < Base
|
3
|
+
REALM_COMMAND = "/usr/sbin/realm".freeze
|
4
|
+
KERBEROS_KEYTAB_FILE = "/etc/krb5.keytab".freeze
|
5
|
+
AUTH = {
|
6
|
+
:type => "active-directory",
|
7
|
+
:subtype => "active-directory"
|
8
|
+
}.freeze
|
9
|
+
|
10
|
+
def required_options
|
11
|
+
super.merge(
|
12
|
+
:ad_domain => { :description => "Active Directory Domain" },
|
13
|
+
:ad_user => { :description => "Active Directory User" },
|
14
|
+
:ad_password => { :description => "Active Directory Password" }
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def optional_options
|
19
|
+
super.merge(
|
20
|
+
:ad_realm => { :description => "Active Directory Realm" },
|
21
|
+
:ad_server => { :description => "Active Directory Server" }
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def persistent_files
|
26
|
+
%w(
|
27
|
+
/etc/krb5.keytab
|
28
|
+
/etc/krb5.conf
|
29
|
+
/etc/nsswitch.conf
|
30
|
+
/etc/openldap/ldap.conf
|
31
|
+
/etc/pam.d/fingerprint-auth-ac
|
32
|
+
/etc/pam.d/httpd-auth
|
33
|
+
/etc/pam.d/password-auth-ac
|
34
|
+
/etc/pam.d/postlogin-ac
|
35
|
+
/etc/pam.d/smartcard-auth-ac
|
36
|
+
/etc/pam.d/system-auth-ac
|
37
|
+
/etc/resolv.conf
|
38
|
+
/etc/sssd/sssd.conf
|
39
|
+
/etc/sysconfig/authconfig
|
40
|
+
/etc/sysconfig/network
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
def configure(opts)
|
45
|
+
update_hostname(opts[:host])
|
46
|
+
join_ad_realm
|
47
|
+
realm_permit_all
|
48
|
+
configure_pam
|
49
|
+
configure_sssd
|
50
|
+
update_kerberos_keytab_permissions
|
51
|
+
enable_kerberos_dns_lookups
|
52
|
+
config_map = ConfigMap.new(opts)
|
53
|
+
config_map.generate(AUTH[:type], realm, persistent_files)
|
54
|
+
config_map.save(opts[:output])
|
55
|
+
rescue => err
|
56
|
+
log_command_error(err)
|
57
|
+
raise err
|
58
|
+
end
|
59
|
+
|
60
|
+
def configured?
|
61
|
+
File.exist?(SSSD_CONFIG)
|
62
|
+
end
|
63
|
+
|
64
|
+
def unconfigure
|
65
|
+
return unless configured?
|
66
|
+
end
|
67
|
+
|
68
|
+
def realm
|
69
|
+
@realm ||= opts[:ad_realm] if opts[:ad_realm].present?
|
70
|
+
@realm ||= domain
|
71
|
+
@realm ||= super
|
72
|
+
@realm = @realm.upcase
|
73
|
+
end
|
74
|
+
|
75
|
+
def domain
|
76
|
+
@domain ||= opts[:ad_domain] if opts[:ad_domain].present?
|
77
|
+
@domain ||= super
|
78
|
+
@domain
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def configure_sssd
|
84
|
+
info_msg("Configuring SSSD Service")
|
85
|
+
sssd = Sssd.new(opts)
|
86
|
+
sssd.load(SSSD_CONFIG)
|
87
|
+
sssd.configure_domain(domain)
|
88
|
+
sssd.section("domain/#{domain}")["ad_server"] = opts[:ad_server] if opts[:ad_server].present?
|
89
|
+
sssd.section("sssd")["domains"] = domain
|
90
|
+
sssd.section("sssd")["default_domain_suffix"] = domain
|
91
|
+
sssd.add_service("pam")
|
92
|
+
sssd.configure_ifp
|
93
|
+
debug_msg("- Creating #{SSSD_CONFIG}")
|
94
|
+
sssd.save(SSSD_CONFIG)
|
95
|
+
end
|
96
|
+
|
97
|
+
def join_ad_realm
|
98
|
+
info_msg("Joining the AD Realm ...")
|
99
|
+
debug_msg(" - realm join #{realm} ...")
|
100
|
+
command_run!(REALM_COMMAND, :params => ["join", domain, "-U", opts[:ad_user]], :stdin_data => opts[:ad_password])
|
101
|
+
end
|
102
|
+
|
103
|
+
def realm_permit_all
|
104
|
+
info_msg("Allowing AD Users to Login ...")
|
105
|
+
command_run!(REALM_COMMAND, :params => ["permit", "--all"])
|
106
|
+
end
|
107
|
+
|
108
|
+
def update_kerberos_keytab_permissions
|
109
|
+
info_msg("Updating Kerberos keytab permissions ...")
|
110
|
+
FileUtils.chown("apache", "root", KERBEROS_KEYTAB_FILE)
|
111
|
+
FileUtils.chmod(0o640, KERBEROS_KEYTAB_FILE)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require "pathname"
|
2
|
+
require "httpd_configmap_generator/base/command"
|
3
|
+
require "httpd_configmap_generator/base/config"
|
4
|
+
require "httpd_configmap_generator/base/config_map"
|
5
|
+
require "httpd_configmap_generator/base/file"
|
6
|
+
require "httpd_configmap_generator/base/kerberos"
|
7
|
+
require "httpd_configmap_generator/base/network"
|
8
|
+
require "httpd_configmap_generator/base/pam"
|
9
|
+
require "httpd_configmap_generator/base/principal"
|
10
|
+
require "httpd_configmap_generator/base/sssd"
|
11
|
+
|
12
|
+
module HttpdConfigmapGenerator
|
13
|
+
class Base
|
14
|
+
APACHE_USER = "apache".freeze
|
15
|
+
HTTP_KEYTAB = "/etc/http.keytab".freeze
|
16
|
+
IPA_COMMAND = "/usr/bin/ipa".freeze
|
17
|
+
KERBEROS_CONFIG_FILE = "/etc/krb5.conf".freeze
|
18
|
+
LDAP_ATTRS = {
|
19
|
+
"mail" => "REMOTE_USER_EMAIL",
|
20
|
+
"givenname" => "REMOTE_USER_FIRSTNAME",
|
21
|
+
"sn" => "REMOTE_USER_LASTNAME",
|
22
|
+
"displayname" => "REMOTE_USER_FULLNAME",
|
23
|
+
"domainname" => "REMOTE_USER_DOMAIN"
|
24
|
+
}.freeze
|
25
|
+
PAM_CONFIG = "/etc/pam.d/httpd-auth".freeze
|
26
|
+
SSSD_CONFIG = "/etc/sssd/sssd.conf".freeze
|
27
|
+
TIMESTAMP_FORMAT = "%Y%m%d_%H%M%S".freeze
|
28
|
+
|
29
|
+
attr_accessor :opts
|
30
|
+
|
31
|
+
def initialize(opts = {})
|
32
|
+
@opts = opts
|
33
|
+
@realm = @domain = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def err_msg(msg)
|
37
|
+
STDERR.puts(msg)
|
38
|
+
end
|
39
|
+
|
40
|
+
def info_msg(msg)
|
41
|
+
STDOUT.puts(msg)
|
42
|
+
end
|
43
|
+
|
44
|
+
def debug_msg(msg)
|
45
|
+
STDOUT.puts(msg) if opts[:debug]
|
46
|
+
end
|
47
|
+
|
48
|
+
def required_options
|
49
|
+
{
|
50
|
+
:host => { :description => "Application Domain",
|
51
|
+
:short => "-h" },
|
52
|
+
:output => { :description => "Configuration map file to create",
|
53
|
+
:short => "-o" }
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def optional_options
|
58
|
+
{
|
59
|
+
:force => { :description => "Force configuration if configured already",
|
60
|
+
:short => "-f",
|
61
|
+
:default => false },
|
62
|
+
:debug => { :description => "Enable debugging",
|
63
|
+
:short => "-d",
|
64
|
+
:default => false }
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
def run_configure(opts)
|
69
|
+
validate_options(opts)
|
70
|
+
@opts = opts
|
71
|
+
unconfigure if configured? && opts[:force]
|
72
|
+
raise "#{self.class.name} Already Configured" if configured?
|
73
|
+
unless ENV["HTTPD_AUTH_TYPE"]
|
74
|
+
raise "Not running in httpd_configmap_generator container - Skipping #{self.class.name} configuration"
|
75
|
+
end
|
76
|
+
configure(opts)
|
77
|
+
end
|
78
|
+
|
79
|
+
def validate_options(_options)
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "awesome_spawn"
|
2
|
+
|
3
|
+
module HttpdConfigmapGenerator
|
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)}")
|
8
|
+
end
|
9
|
+
AwesomeSpawn.run(executable, options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def command_run!(executable, options = {})
|
13
|
+
if opts && opts[:debug]
|
14
|
+
debug_msg("Running Command: #{AwesomeSpawn.build_command_line(executable, options)}")
|
15
|
+
end
|
16
|
+
AwesomeSpawn.run!(executable, options)
|
17
|
+
end
|
18
|
+
|
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)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,13 @@
|
|
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
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require "base64"
|
2
|
+
require "yaml"
|
3
|
+
require "uri"
|
4
|
+
require "etc"
|
5
|
+
|
6
|
+
module HttpdConfigmapGenerator
|
7
|
+
class ConfigMap < Base
|
8
|
+
DATA_SECTION = "data".freeze
|
9
|
+
AUTH_CONFIGURATION = "auth-configuration.conf".freeze
|
10
|
+
|
11
|
+
attr_accessor :config_map
|
12
|
+
attr_accessor :opts
|
13
|
+
|
14
|
+
def initialize(opts = {})
|
15
|
+
@opts = opts
|
16
|
+
@config_map = template
|
17
|
+
end
|
18
|
+
|
19
|
+
def generate(auth_type, realm, file_list)
|
20
|
+
info_msg("Generating Auth Config-Map for #{auth_type}")
|
21
|
+
@config_map = template(auth_type, realm)
|
22
|
+
file_specs = gen_filespecs(file_list)
|
23
|
+
define_configuration(file_specs)
|
24
|
+
include_files(file_specs)
|
25
|
+
end
|
26
|
+
|
27
|
+
def load(file_path)
|
28
|
+
@config_map = File.exist?(file_path) ? YAML.load_file(file_path) : {}
|
29
|
+
end
|
30
|
+
|
31
|
+
def save(file_path)
|
32
|
+
delete_target_file(file_path)
|
33
|
+
info_msg("Saving Auth Config-Map to #{file_path}")
|
34
|
+
File.open(file_path, "w") { |f| f.write(config_map.to_yaml) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_files(file_list)
|
38
|
+
return unless file_list
|
39
|
+
file_specs = gen_filespecs_for_files_to_add(file_list)
|
40
|
+
update_configuration(file_specs)
|
41
|
+
include_files(file_specs)
|
42
|
+
end
|
43
|
+
|
44
|
+
def export_file(file_entry, output_file)
|
45
|
+
basename, _target_file, _mode = search_file_entry(file_entry)
|
46
|
+
raise "File #{file_entry} does not exist in the configuration map" unless basename
|
47
|
+
delete_target_file(output_file)
|
48
|
+
create_target_directory(output_file)
|
49
|
+
debug_msg("Exporting #{file_entry} to #{output_file} ...")
|
50
|
+
content = config_map.fetch_path(DATA_SECTION, basename)
|
51
|
+
content = Base64.decode64(content) if basename =~ /^.*\.base64$/
|
52
|
+
File.write(output_file, content)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def template(auth_type = "internal", kerberos_realms = "undefined")
|
58
|
+
{
|
59
|
+
DATA_SECTION => {
|
60
|
+
"auth-type" => auth_type,
|
61
|
+
"auth-kerberos-realms" => kerberos_realms
|
62
|
+
},
|
63
|
+
"kind" => "ConfigMap",
|
64
|
+
"metadata" => {
|
65
|
+
"name" => "httpd-auth-configs"
|
66
|
+
}
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
def gen_filespecs(file_list)
|
71
|
+
file_specs = []
|
72
|
+
file_list.each do |file|
|
73
|
+
file_specs << file_entry_spec(file.strip)
|
74
|
+
end
|
75
|
+
file_specs.sort_by { |file_spec| file_spec[:basename] }
|
76
|
+
end
|
77
|
+
|
78
|
+
# Supporting the following signatures:
|
79
|
+
# /path/of/real/file
|
80
|
+
# /path/of/source/file,/path/of/real/file
|
81
|
+
# /path/of/source/file,/path/of/real/file,mode
|
82
|
+
# http://url_source,/path/of/real/file,mode
|
83
|
+
def gen_filespecs_for_files_to_add(file_list)
|
84
|
+
file_specs = []
|
85
|
+
file_list.each do |file_to_add|
|
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)
|
100
|
+
else
|
101
|
+
file_entry = file_entry_spec(source_file, target_file, mode)
|
102
|
+
end
|
103
|
+
else
|
104
|
+
raise "Invalid file specification #{file_to_add}"
|
105
|
+
end
|
106
|
+
file_specs << file_entry
|
107
|
+
end
|
108
|
+
file_specs.sort_by { |file_spec| file_spec[:basename] }
|
109
|
+
end
|
110
|
+
|
111
|
+
def file_entry_spec(source_file, target_file = nil, mode = nil)
|
112
|
+
target_file = source_file.dup unless target_file
|
113
|
+
unless mode
|
114
|
+
stat = File.stat(source_file)
|
115
|
+
file_owner = Etc.getpwuid(stat.uid).name
|
116
|
+
file_group = Etc.getgrgid(stat.gid).name
|
117
|
+
end
|
118
|
+
{
|
119
|
+
:basename => File.basename(target_file).dup,
|
120
|
+
:binary => file_binary?(source_file),
|
121
|
+
:target => target_file,
|
122
|
+
:mode => mode ? mode : "%4o:%s:%s" % [stat.mode & 0o7777, file_owner, file_group]
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
126
|
+
def update_configuration(file_specs)
|
127
|
+
auth_configuration = fetch_auth_configuration
|
128
|
+
return define_configuration(file_specs) unless auth_configuration
|
129
|
+
# first, remove any file_specs references in the file list, we don't want duplication here.
|
130
|
+
auth_configuration = auth_configuration.split("\n")
|
131
|
+
file_specs.each do |file_spec|
|
132
|
+
entry = auth_configuration.select { |line| line =~ file_entry_regex(file_spec[:target]) }
|
133
|
+
auth_configuration -= entry if entry
|
134
|
+
end
|
135
|
+
auth_configuration = auth_configuration.join("\n") + "\n"
|
136
|
+
# now, append any of the new file_specs at the end of the list.
|
137
|
+
append_configuration(auth_configuration, file_specs)
|
138
|
+
end
|
139
|
+
|
140
|
+
def search_file_entry(target_file)
|
141
|
+
auth_configuration = fetch_auth_configuration
|
142
|
+
return nil unless auth_configuration
|
143
|
+
auth_configuration = auth_configuration.split("\n")
|
144
|
+
entry = auth_configuration.select { |line| line =~ file_entry_regex(target_file) }
|
145
|
+
entry ? entry.first.split('=')[1].strip.split(' ') : nil
|
146
|
+
end
|
147
|
+
|
148
|
+
def define_configuration(file_specs)
|
149
|
+
auth_configuration = "# External Authentication Configuration File\n#\n"
|
150
|
+
append_configuration(auth_configuration, file_specs)
|
151
|
+
end
|
152
|
+
|
153
|
+
def include_files(file_specs)
|
154
|
+
file_specs.each do |file_spec|
|
155
|
+
content = File.read(file_spec[:target])
|
156
|
+
content = Base64.encode64(content) if file_spec[:binary]
|
157
|
+
# encode(:universal_newline => true) will convert \r\n to \n, necessary for to_yaml to render properly.
|
158
|
+
config_map[DATA_SECTION].merge!(file_basename(file_spec) => content.encode(:universal_newline => true))
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def file_basename(file_spec)
|
163
|
+
file_spec[:binary] ? "#{file_spec[:basename]}.base64" : file_spec[:basename]
|
164
|
+
end
|
165
|
+
|
166
|
+
def append_configuration(auth_configuration, file_specs)
|
167
|
+
file_specs.each do |file_spec|
|
168
|
+
debug_msg("Adding file #{file_spec[:target]} ...")
|
169
|
+
auth_configuration += "file = #{file_basename(file_spec)} #{file_spec[:target]} #{file_spec[:mode]}\n"
|
170
|
+
end
|
171
|
+
config_map[DATA_SECTION] ||= {}
|
172
|
+
config_map[DATA_SECTION].merge!(AUTH_CONFIGURATION => auth_configuration)
|
173
|
+
end
|
174
|
+
|
175
|
+
def fetch_auth_configuration
|
176
|
+
config_map.fetch_path(DATA_SECTION, AUTH_CONFIGURATION)
|
177
|
+
end
|
178
|
+
|
179
|
+
def file_entry_regex(target_file)
|
180
|
+
/^file = .* #{target_file} .*$/
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|