Sovite.LDAP (sovite v0.2.0)

Copy Markdown View Source

A small layer over OTP's :eldap: connecting with StartTLS or LDAPS, binding, searching, and running all of it in a process of its own.

Sovite.LDAP.isolated(fn ->
  with {:ok, handle} <- Sovite.LDAP.connect(servers: ["ldap.example.com"]) do
    try do
      Sovite.LDAP.search(handle, "dc=example,dc=com", filter, ["mail"])
    after
      Sovite.LDAP.close(handle)
    end
  end
end, 10_000)

Connection options

  • :servers - host names, tried in order. Required.
  • :port - defaults to 389, or 636 with security: :ldaps.
  • :security - :starttls (default), :ldaps, or :none.
  • :tls_options - :ssl client options. Default: verify the server against the system CAs and its name.
  • :timeout - milliseconds per request. Defaults to 10 seconds.

Summary

Types

A search result: the DN and the attributes asked for.

An open connection.

Functions

Binds as dn with password. A bind with an empty password is refused here: LDAP would treat it as anonymous (RFC 4513 §5.1.2).

Closes a connection.

Opens a connection, see the options above.

Fills the placeholders of a DN template, escaping the values (RFC 4514 §2.4), and returns the DN as :eldap wants it.

Runs fun in a process of its own and returns its result, or {:error, :timeout} / {:error, {:exit, reason}}.

Searches the subtree under base with a filter from Sovite.LDAP.Filter.build/2 and returns at most size_limit entries with attributes. Use ["1.1"] for no attributes.

The placeholder values for a user name, for filters and DN templates: u the whole name, n the part before the last @, d the part after it (empty if none).

Types

entry()

@type entry() :: {dn :: charlist(), %{required(String.t()) => [binary()]}}

A search result: the DN and the attributes asked for.

handle()

@type handle() :: pid()

An open connection.

Functions

bind(handle, dn, password)

@spec bind(handle(), String.t() | charlist(), binary()) :: :ok | {:error, term()}

Binds as dn with password. A bind with an empty password is refused here: LDAP would treat it as anonymous (RFC 4513 §5.1.2).

close(handle)

@spec close(handle()) :: :ok

Closes a connection.

connect(opts)

@spec connect(keyword()) :: {:ok, handle()} | {:error, term()}

Opens a connection, see the options above.

dn(template, values)

@spec dn(String.t(), %{required(String.t()) => String.t()}) :: charlist()

Fills the placeholders of a DN template, escaping the values (RFC 4514 §2.4), and returns the DN as :eldap wants it.

isolated(fun, timeout)

@spec isolated((-> result), timeout()) ::
  result | {:error, :timeout | {:exit, term()}}
when result: term()

Runs fun in a process of its own and returns its result, or {:error, :timeout} / {:error, {:exit, reason}}.

:eldap links its connection process to the caller, so a dropped connection would otherwise take the caller down with it.

search(handle, base, filter, attributes, size_limit \\ 100)

@spec search(handle(), String.t(), term(), [String.t()], pos_integer()) ::
  {:ok, [entry()]} | {:error, term()}

Searches the subtree under base with a filter from Sovite.LDAP.Filter.build/2 and returns at most size_limit entries with attributes. Use ["1.1"] for no attributes.

user_values(username)

@spec user_values(String.t()) :: %{required(String.t()) => String.t()}

The placeholder values for a user name, for filters and DN templates: u the whole name, n the part before the last @, d the part after it (empty if none).