-
Notifications
You must be signed in to change notification settings - Fork 18
/
controller.rb
188 lines (166 loc) · 6.85 KB
/
controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# frozen_string_literal: true
module Entitlements
class Backend
class LDAP
class Controller < Entitlements::Backend::BaseController
register
include ::Contracts::Core
C = ::Contracts
# Constructor. Generic constructor that takes a hash of configuration options.
#
# group_name - Name of the corresponding group in the entitlements configuration file.
# config - Optionally, a Hash of configuration information (configuration is referenced if empty).
Contract String, C::Maybe[C::HashOf[String => C::Any]] => C::Any
def initialize(group_name, config = nil)
super
@ldap = Entitlements::Service::LDAP.new_with_cache(
addr: @config.fetch("ldap_uri"),
binddn: @config.fetch("ldap_binddn"),
bindpw: @config.fetch("ldap_bindpw"),
ca_file: @config.fetch("ldap_ca_file", ENV["LDAP_CACERT"]),
disable_ssl_verification: @config.fetch("ldap_disable_ssl_verification", false),
person_dn_format: @config.fetch("person_dn_format")
)
@provider = Entitlements::Backend::LDAP::Provider.new(ldap: @ldap)
end
# Pre-fetch the existing group membership in each OU.
#
# Takes no arguments.
#
# Returns nothing. (Populates cache.)
Contract C::None => C::Any
def prefetch
logger.debug "Pre-fetching group membership in #{group_name} (#{config['base']}) from LDAP"
provider.read_all(config["base"])
end
# Validation routines.
#
# Takes no arguments.
#
# Returns nothing.
Contract C::None => C::Any
def validate
return unless config["mirror"]
Entitlements::Util::Mirror.validate_mirror!(group_name)
end
# Get count of changes.
#
# Takes no arguments.
#
# Returns an Integer.
Contract C::None => Integer
def change_count
actions.size + (ou_needs_to_be_created? ? 1 : 0)
end
# Calculation routines.
#
# Takes no arguments.
#
# Returns nothing (populates @actions).
Contract C::None => C::Any
def calculate
if ou_needs_to_be_created?
logger.info "ADD #{config['base']}"
end
existing = provider.read_all(config["base"])
proposed = Entitlements::Data::Groups::Calculated.read_all(group_name, config)
# Calculate differences.
added = (proposed - existing)
.map { |i| Entitlements::Models::Action.new(i, nil, Entitlements::Data::Groups::Calculated.read(i), group_name) }
removed = (existing - proposed)
.map { |i| Entitlements::Models::Action.new(i, provider.read(i), nil, group_name) }
changed = (existing & proposed)
.reject { |i| provider.read(i).equals?(Entitlements::Data::Groups::Calculated.read(i)) }
.map { |i| Entitlements::Models::Action.new(i, provider.read(i), Entitlements::Data::Groups::Calculated.read(i), group_name) }
# Print the differences.
print_differences(key: group_name, added: added, removed: removed, changed: changed)
# Populate the actions
@actions = [added, removed, changed].flatten.compact
end
# Pre-apply routines. For the LDAP provider this creates the OU if it does not exist,
# and if "create_if_missing" has been set to true.
#
# Takes no arguments.
#
# Returns nothing.
Contract C::None => C::Any
def preapply
return unless ou_needs_to_be_created?
if ldap.upsert(dn: config["base"], attributes: {"objectClass" => "organizationalUnit"})
logger.debug "APPLY: Creating #{config['base']}"
else
logger.warn "DID NOT APPLY: Changes not needed to #{config['base']}"
end
end
# Apply changes.
#
# action - Action array.
#
# Returns nothing.
Contract Entitlements::Models::Action => C::Any
def apply(action)
if action.updated.nil?
logger.debug "APPLY: Deleting #{action.dn}"
ldap.delete(action.dn)
else
override = Entitlements::Util::Override.override_hash_from_plugin(action.config["plugin"], action.updated, ldap) || {}
if provider.upsert(action.updated, override)
logger.debug "APPLY: Upserting #{action.dn}"
else
logger.warn "DID NOT APPLY: Changes not needed to #{action.dn}"
logger.debug "Old: #{action.existing.inspect}"
logger.debug "New: #{action.updated.inspect}"
end
end
end
# Validate configuration options.
#
# key - String with the name of the group.
# data - Hash with the configuration data.
#
# Returns nothing.
Contract String, C::HashOf[String => C::Any] => nil
def validate_config!(key, data)
spec = COMMON_GROUP_CONFIG.merge({
"base" => { required: true, type: String },
"create_if_missing" => { required: false, type: [FalseClass, TrueClass]},
"ldap_binddn" => { required: true, type: String },
"ldap_bindpw" => { required: true, type: String },
"ldap_ca_file" => { required: false, type: String },
"disable_ssl_verification" => { required: false, type: [FalseClass, TrueClass] },
"ldap_uri" => { required: true, type: String },
"plugin" => { required: false, type: Hash },
"mirror" => { required: false, type: String },
"person_dn_format" => { required: true, type: String }
})
text = "Group #{key.inspect}"
Entitlements::Util::Util.validate_attr!(spec, data, text)
end
# ***********************************************************
# Private methods for this backend go below.
# ***********************************************************
# Determine if the OU needs to be created.
#
# Takes no arguments.
#
# Returns an Array of Strings (DNs).
Contract C::None => C::Bool
def ou_needs_to_be_created?
return false unless config["create_if_missing"]
@ou_needs_to_be_created ||= begin
if ldap.exists?(config["base"])
logger.debug "OU create_if_missing: #{config['base']} already exists"
:false
else
logger.debug "OU create_if_missing: #{config['base']} needs to be created"
:true
end
end
@ou_needs_to_be_created == :true
end
private
attr_reader :ldap, :provider
end
end
end
end