LoginSignup
9

More than 5 years have passed since last update.

Go言語からActive Directoryにアクセスしてみる(検索編)

Last updated at Posted at 2017-06-21

はじめに

Go言語からActive Directoryを利用したいと思いましたので、まずは検索からやってみました。
尚、使用したパッケージはLDAPv3用ですので、OpenLDAP等のLDAPサーバへのアクセスでも応用できると思います。
また投稿内容は、ある程度Active Directory、LDAPの知識を有していることを前提としています。

LDAPパッケージのインストール

goコマンドでチャッチャとインストールです。

>go get -v gopkg.in/ldap.v2

サンプルコード

ldapsearch.go
package main

import (
    "gopkg.in/ldap.v2"
    "fmt"
    "log"
)

const (
    LDAPSV = "dc1.mydomain.local"
    PROTO  = "tcp"
    PORTNO = 389
    BINDDN = "cn=Administrator,cn=Users,dc=MYDOMAIN,dc=local"
    BINDPW = "P@ssw0rd"
    BASEDN = "dc=MYDOMAIN,dc=local"
    FILTER = "(&(objectCategory=computer)(operatingSystem=*Windows*))"
)

func main() {
    // LDAPサーバへ接続
    l, err := ldap.Dial(PROTO, fmt.Sprintf("%s:%d", LDAPSV, PORTNO))
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Ldap server connected.")
    defer func() {
        l.Close()
        fmt.Println("Ldap server disconnected.")
    }()

    //LDAPサーバ認証(バインド)
    err = l.Bind(BINDDN, BINDPW)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Ldap server logged in.")

    /*
    検索リクエスト作成

        コンストラクタ関数の引数
        func NewSearchRequest(
            BaseDN          string,
            Scope           int,
            DerefAliases    int,
            SizeLimit       int,
            TimeLimit       int,
            TypesOnly       bool,
            Filter          string,
            Attributes      []string,
            Controls        []Control,
        ) *SearchRequest
    */
    searchRequest := ldap.NewSearchRequest(
        BASEDN,
        ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
        FILTER,
        []string{"dn", "cn"},
        nil,
    )

    //検索リクエストを基にディレクトリ内検索
    sr, err := l.Search(searchRequest)
    if err != nil {
        log.Fatal(err)
    }

    //検索結果のリスト出力
    for _, entry := range sr.Entries {
        fmt.Printf("%s: %v\n", entry.DN, entry.GetAttributeValue("cn"))
    }
}

Go言語に慣れている方であれば、上記コードの細かい説明は要らないんじゃないかと思います。
尚、肝となる点は検索リクエスト(SearchRequest)作成の箇所となりますが、NewSearchRequestに渡すパラメータの説明は、下表のような感じです。
(Unix系OSでのldapsearchコマンドを簡易にした感じです)

NewSearchRequestパラメータ

パラメータ 説明
BaseDN 指定されたDNを起点としたツリー配下の検索を行います。
Scope ScopeBaseObject = BaseDNで指定された階層のみを検索します。
ScopeSingleLevel = BaseDNで指定された階層の1つ下の階層を検索します。
ScopeWholeSubtree = BaseDNで指定された階層以下(サブツリー)すべてを検索します。
DerefAliases エイリアスエントリの実名参照をどのように行うかを指定します。
NeverDerefAliases = 実名参照しない。
DerefInSearching = 検索の場合は実名参照する。
DerefFindingBaseObj = BaseDNツリー配下に位置した場合は実名参照する。
DerefAlways = 常に実名参照する。
SizeLimit 検索結果に返されるエントリの最大数を指定します。
0 = 無制限
TimeLimit 検索結果のタイムリミットを指定します。
0 = 無制限
TypesOnly 検索結果に属性値を含めるか指定します。
true = 属性値を含めない(属性IDだけが返される)
false = 属性値を含む
Filter 検索条件を指定します。書式についてはLDAPの仕様に準じます。
Attributes 検索結果として返される属性をリストで指定します。
Controls LDAP要求の際の、LDAPコントロールを指定します。(RFC2251 - 4.1.12. Controls)

実行してみる

実行結果は、以下のようになったと思います。
サンプルコードでは、Active DirectoryサーバからobjectCategory属性がcomputer、且つoperatingSystem属性が*Windows*のエントリを検索し、識別子(DN)とcn属性値を取得して出力しています。

>go run ldapsearch.go
Ldap server connected.
Ldap server logged in.
CN=Client1,OU=Computers,DC=MYDOMAIN,DC=local: Client1
CN=Client2,OU=Computers,DC=MYDOMAIN,DC=local: Client2
CN=Client3,OU=Computers,DC=MYDOMAIN,DC=local: Client3
...
(省略)
...
CN=Client20,OU=Computers,DC=MYDOMAIN,DC=local: Client20
Ldap server disconnected.

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9