瀏覽代碼

modularized ldap and fixed up get_group_memberships

Daniel Moore 11 年之前
父節點
當前提交
9b8dc2f631
共有 3 個文件被更改,包括 108 次插入63 次删除
  1. 25 0
      src/config.erl
  2. 77 0
      src/ldap_integration.erl
  3. 6 63
      src/main.erl

+ 25 - 0
src/config.erl

@@ -0,0 +1,25 @@
+%%%-------------------------------------------------------------------
+%%% @author dmoore
+%%% @copyright (C) 2013, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 08. Oct 2013 10:25 PM
+%%%-------------------------------------------------------------------
+-module(config).
+-author("dmoore").
+
+%% API
+-export([get_config/1]).
+
+get_config([]) -> [];
+get_config([Key|Rem]) ->
+  [case Key of
+    "UseSsl" -> false;
+    "LdapServer" -> "atlas.northhorizon.local";
+     "BaseDN" -> "DC=northhorizon,DC=local";
+     "SearchUserDN" -> "CN=ldapsearch,CN=Users,DC=northhorizon,DC=local";
+     "SearchUserPassword" -> "Welcome1";
+     "UserDNMapAttr" -> "userPrincipalName";
+     "GroupDNMapAttr" -> "name"
+  end | get_config(Rem)].

+ 77 - 0
src/ldap_integration.erl

@@ -0,0 +1,77 @@
+%%%-------------------------------------------------------------------
+%%% @author dmoore
+%%% @copyright (C) 2013, <COMPANY>
+%%% @doc
+%%%
+%%% @end
+%%% Created : 08. Oct 2013 10:21 PM
+%%%-------------------------------------------------------------------
+-module(ldap_integration).
+-author("dmoore").
+
+-include_lib("eldap/include/eldap.hrl").
+
+%% API
+-export([connect/0, authenticate/3, get_group_memberships/2]).
+
+-import(config, [get_config/1]).
+
+authenticate(LdapConnection, User, Password) ->
+  [UserDNMapAttr] = get_config(["UserDNMapAttr"]),
+
+  case query(LdapConnection, "person", eldap:equalityMatch(UserDNMapAttr, User)) of
+    [] -> throw({ invalid_credentials });
+    [#eldap_entry{ object_name = UserDN } | _] ->
+      % attempt to connect as UserDN and if it doesn't throw, immediately disconnect.
+      eldap:close(connect(UserDN, Password)),
+
+      UserDN
+  end.
+
+connect() ->
+  [SearchUserDN, SearchUserPassword] = get_config(["SearchUserDN", "SearchUserPassword"]),
+  io:format("Connecting with ~s / ~s\n", [SearchUserDN, SearchUserPassword]),
+  connect(SearchUserDN, SearchUserPassword).
+
+connect(DN, Password) ->
+  [LdapServer, UseSsl] = get_config(["LdapServer", "UseSsl"]),
+  case eldap:open([LdapServer], [{ssl, UseSsl}]) of
+    {error, Reason} -> throw({ ldap_connection_error, Reason });
+    {ok, LdapConnection} ->
+      case eldap:simple_bind(LdapConnection, DN, Password) of
+        {error, _} ->
+          eldap:close(LdapConnection),
+          throw({ invalid_credentials });
+        ok -> LdapConnection
+      end
+  end.
+
+query(LdapConnection, Type, Filter) ->
+  [BaseDN] = get_config(["BaseDN"]),
+  TypedFilter = eldap:'and'([eldap:equalityMatch("objectClass", Type), Filter]),
+  case eldap:search(LdapConnection, [{ base, BaseDN }, { filter, TypedFilter }]) of
+    {error, Reason} -> throw({search, Reason});
+    {ok, #eldap_search_result{ entries = Result }} -> Result
+  end.
+
+get_group_memberships(LdapConnection, UserDN) ->
+  Memberships = get_group_memberships(LdapConnection, sets:new(), UserDN),
+  [ element(2, T) || T <- sets:to_list(Memberships) ].
+
+get_group_memberships(LdapConnection, Memberships, DN) ->
+  [GroupDNMapAttr] = get_config(["GroupDNMapAttr"]),
+  case query(LdapConnection, "group", eldap:equalityMatch("member", DN)) of
+    [] -> Memberships;
+    Entries ->
+      ParentGroupDNs = [
+        case element(2, lists:keyfind(GroupDNMapAttr, 1, X#eldap_entry.attributes)) of
+          [Value|_] -> {X#eldap_entry.object_name, Value};
+          _ -> throw({no_value})
+        end || X <- Entries
+      ],
+      S = sets:subtract(sets:from_list(ParentGroupDNs), Memberships),
+      case sets:size(S) of
+        0 -> Memberships;
+        _ -> sets:fold(fun ({N, _}, P) -> get_group_memberships(LdapConnection, P, N) end, sets:union(Memberships, S), S)
+      end
+  end.

+ 6 - 63
src/main.erl

@@ -10,14 +10,6 @@
 
 
 -export([start/0]).
 -export([start/0]).
 
 
--define(USE_SSL, false).
--define(LDAP_SERVER, "atlas.northhorizon.local").
--define(BASE_DN, "DC=northhorizon,DC=local").
--define(SEARCH_USER_DN, "CN=ldapsearch,CN=Users,DC=northhorizon,DC=local").
--define(SEARCH_USER_PASSWORD, "Welcome1").
--define(USER_DN_MAP_ATTR, "userPrincipalName").
--define(GROUP_DN_MAP_ATTR, "name").
-
 -define(TEST_USER, "test@northhorizon.local").
 -define(TEST_USER, "test@northhorizon.local").
 -define(TEST_USER_PASSWORD, "Welcome1").
 -define(TEST_USER_PASSWORD, "Welcome1").
 
 
@@ -30,65 +22,16 @@
 
 
 -include_lib("eldap/include/eldap.hrl").
 -include_lib("eldap/include/eldap.hrl").
 
 
+-import(ldap_integration, [connect/0, authenticate/3, get_group_memberships/2]).
+
 start() ->
 start() ->
 %%   User = string:strip(io:get_line("User: "), right, $\n),
 %%   User = string:strip(io:get_line("User: "), right, $\n),
 %%   Password = string:strip(io:get_line("Password: "), right, $\n),
 %%   Password = string:strip(io:get_line("Password: "), right, $\n),
 %%
 %%
 %%   authenticate(User, Password).
 %%   authenticate(User, Password).
-  authenticate(?TEST_USER, ?TEST_USER_PASSWORD).
-
-
-authenticate(User, Password) ->
-  LdapConnection = connect(?SEARCH_USER_DN, ?SEARCH_USER_PASSWORD),
-  case query(LdapConnection, "person", eldap:equalityMatch(?USER_DN_MAP_ATTR, User)) of
-    [] -> throw({ invalid_credentials });
-    [#eldap_entry{ object_name = UserDN } | _] ->
-      % attempt to connect as UserDN and if it doesn't throw, immediately disconnect.
-      eldap:close(connect(UserDN, Password)),
-
-      % If we're here, auth succeeded.
-
-      io:format("user: ~p\n", [UserDN]),
-      Groups = get_group_memberships(LdapConnection, UserDN),
-      io:format("groups: ~p", [Groups])
-  end,
-  eldap:close(LdapConnection).
-
-connect(DN, Password) ->
-  case eldap:open([?LDAP_SERVER], [{ssl, ?USE_SSL}]) of
-    {error, Reason} -> throw({ ldap_connection_error, Reason });
-    {ok, LdapConnection} ->
-      case eldap:simple_bind(LdapConnection, DN, Password) of
-        {error, _} ->
-          eldap:close(LdapConnection),
-          throw({ invalid_credentials });
-        ok -> LdapConnection
-      end
-  end.
-
-query(LdapConnection, Type, Filter) ->
-  TypedFilter = eldap:'and'([eldap:equalityMatch("objectClass", Type), Filter]),
-  case eldap:search(LdapConnection, [{ base, ?BASE_DN }, { filter, TypedFilter }]) of
-    {error, Reason} -> throw({search, Reason});
-    {ok, #eldap_search_result{ entries = Result }} -> io:format("found ~p\n", [Result]), Result
-  end.
-
-get_group_memberships(LdapConnection, UserDN) ->
-  Memberships = get_group_memberships(LdapConnection, sets:new(), UserDN),
-  sets:to_list(Memberships).
+  LdapConnection = connect(),
+  UserDN = authenticate(LdapConnection, ?TEST_USER, ?TEST_USER_PASSWORD),
+  Groups = get_group_memberships(LdapConnection, UserDN),
 
 
-get_group_memberships(LdapConnection, Memberships, DN) ->
-  case query(LdapConnection, "group", eldap:equalityMatch("member", DN)) of
-    [] -> Memberships;
-    Entries ->
-      ParentGroupDNs = [ {X#eldap_entry.object_name, get_record_value(X, ?GROUP_DN_MAP_ATTR)} || X <- Entries ],
-      S = sets:subtract(sets:from_list(ParentGroupDNs), Memberships),
-      case sets:size(S) of
-        0 -> Memberships;
-        _ -> sets:fold(fun (N, P) -> get_group_memberships(LdapConnection, P, N) end, sets:union(Memberships, S), S)
-      end
-  end.
+  io:format("user: ~p\ngroups: ~p\n", [UserDN, Groups]).
 
 
-get_record_value(Record, Field) ->
-  FieldAtom = string_to_atom(Field)
-  lists:filter(fun ({FieldAtom})