httpd_configmap_generator 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|