class DN
rubocop:disable ClassLength Accepts various DN
strings and returns a DN
object
Attributes
Public Class Methods
Initialize the instance
@param opts [Hash] Options hash for new DN
instance attribute values @param opts [String] The DN
string you want to parse into a DN
@param opts User provided logger vs Rails / Logging default logger NOTE: opts defaults to “upcase”; use “to_s” for no change. @param opts [String] String
method for changing DN
. @param opts [String] Specify a custom delimiter for dn_string
NOTE: opts is a last resort config, defaults to RFC4514 spec. @param opts [Array] Specify the order of RDNs for .to_s @return [DN]
# File lib/dnc/dn.rb, line 27 def initialize(opts = {}) @dn_string = opts[:dn_string] raise 'dnc: dn_string parameter is **required**' if dn_string.nil? @original_dn = dn_string @logger = opts[:logger] || logger @transformation = opts[:transformation] || 'upcase' @string_order = opts[:string_order] || %w(cn l st o ou c street dc uid) @delimiter = opts[:delimiter] || identify_delimiter format_dn end
Public Instance Methods
logger method to return Rails logger if defined, else logging logger
# File lib/dnc/dn.rb, line 39 def logger unless defined? @logger logger = Logging.logger[self] @logger = Kernel.const_defined?('Rails') ? Rails.logger : logger end @logger end
Split passed DN
by identified delimiter
# File lib/dnc/dn.rb, line 61 def split_by_delimiter dn_string.split(delimiter).reject(&:empty?) end
Convert DN
object into a string (order follows RFC4514 LDAP specifications)
# File lib/dnc/dn.rb, line 48 def to_s return_string = '' @string_order.each do |string_name| unless send(string_name.to_sym).blank? return_string += ',' unless return_string.empty? return_string += send("#{string_name}_string".to_sym) end end return_string end
Private Instance Methods
# File lib/dnc/dn.rb, line 115 def assign_rdn_as_array(method_name, value) send("#{method_name}=", Array.wrap(send(method_name))) send(method_name).push(value) end
# File lib/dnc/dn.rb, line 111 def assign_rdn_as_string(method_name, value) send("#{method_name}=", value) end
Regex to match the DN
delimiter by getting the 2nd key non-word predecessor
# File lib/dnc/dn.rb, line 136 def delimiter_regexp /\A.*=.*((([^\w\s\+\)\(])|([_]))\s?)\w+=.*\z/ end
Dynamically define a method to return DN
array values as string format
# File lib/dnc/dn.rb, line 171 def dn_array_to_string(getter_method) tmp_str = '' value = send(getter_method.to_sym) value.each do |el| tmp_str += ',' unless tmp_str.empty? tmp_str += "#{getter_method.to_s.upcase}=#{el}" end tmp_str end
Verify DN
starts with 'CN='
# File lib/dnc/dn.rb, line 131 def dn_begins_properly?(dn_str) dn_str.nil? ? false : /^#{Regexp.escape(delimiter)}?CN/i.match(dn_str) end
Dynamically define a method to return DN
hash values as string format
# File lib/dnc/dn.rb, line 183 def dn_hash_to_string(getter_method) return_string = '' value = send(getter_method.to_sym) value.each do |key, string| return_string += '+' unless return_string.empty? return_string += "#{key.upcase}=#{string}" end return_string end
Dynamically define a method to return DN
string values as string format
# File lib/dnc/dn.rb, line 195 def dn_string_to_string(getter_method) "#{getter_method.to_s.upcase}=#{send(getter_method.to_sym)}" end
Dynamically format the “#{attr}_string” method by value's class type
# File lib/dnc/dn.rb, line 162 def dynamic_strings(getter_method, value_class) send("dn_#{value_class.to_s.downcase}_to_string".to_sym, getter_method) end
Orchestrates reformatting DN
to expected element order for LDAP auth.
# File lib/dnc/dn.rb, line 68 def format_dn # Transform dn_string for consistency / uniqueness @dn_string = dn_string.send(transformation.to_sym) format_dn_element_order unless dn_begins_properly?(dn_string) parse_rdns_to_attrs self end
Ensure order of DN
elements is proper for CAS server
# File lib/dnc/dn.rb, line 121 def format_dn_element_order formatted_dn = split_by_delimiter.reverse.join(delimiter) if dn_begins_properly?(formatted_dn) @dn_string = formatted_dn else raise "DN invalid format for LDAP authentication, DN:\r\n#{original_dn}" end end
Identify and set the DN
delimiter
# File lib/dnc/dn.rb, line 141 def identify_delimiter logger.debug("DN.identify_delimeter: #{dn_string}") delimiter_regexp.match(dn_string)[1] rescue raise DnDelimiterUnparsableError, "DN delimiter could not be identified \r\nPlease ensure your string complies with RFC1779 formatting." end
# File lib/dnc/dn.rb, line 149 def method_missing(method_name) # Catch methods that end with _string method_match = method_name.to_s.match(/(.+)_string\z/) unless method_match.blank? method = method_match[1] method_class = send(method.to_sym).class return send(:dynamic_strings, method.to_s, method_class) end super end
# File lib/dnc/dn.rb, line 100 def parse_nested_rdn(rdn) rdn_keypairs = {} rdn_array = rdn.split('+') rdn_array.each do |string| keypair = string.split('=') rdn_keypairs[keypair[0].to_sym] = keypair[1] end send("#{rdn_keypairs.keys.first.downcase}=", rdn_keypairs) end
Parse @dn_string RDNs and assign them to DN
attributes
# File lib/dnc/dn.rb, line 77 def parse_rdns_to_attrs split_by_delimiter.each do |rdn| if rdn.include?('+') parse_nested_rdn(rdn) else parse_top_level_rdn(rdn) end end self end
# File lib/dnc/dn.rb, line 89 def parse_top_level_rdn(rdn) rdn_array = rdn.split('=') method = rdn_array[0].downcase.to_sym value = rdn_array[1] if send(method).blank? assign_rdn_as_string(method, value) else assign_rdn_as_array(method, value) end end