#はじめに
Go言語からActive Directoryを利用したいと思いましたので、まずは検索からやってみました。
尚、使用したパッケージはLDAPv3用ですので、OpenLDAP等のLDAPサーバへのアクセスでも応用できると思います。
また投稿内容は、ある程度Active Directory、LDAPの知識を有していることを前提としています。
#LDAPパッケージのインストール
goコマンドでチャッチャとインストールです。
>go get -v gopkg.in/ldap.v2
#サンプルコード
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.