2014-04-01 24 views
5

Tôi muốn thực hiện một truy vấn đối với một thư mục LDAP như thế nào nhân viên được phân phối tại các phòng ban và các nhóm ...Làm cách nào để chạy truy vấn ldap bằng R?

Cái gì như: "Hãy cho tôi tên bộ phận của tất cả các thành viên của một nhóm" và sau đó sử dụng R để thực hiện một phân tích tần số, nhưng tôi không thể tìm thấy bất kỳ ví dụ về cách để kết nối và chạy một truy vấn LDAP sử dụng R.

RCurl dường như có một số loại hỗ trợ (http://cran.r-project.org/web/packages/RCurl/index.html):

Bên cạnh đó, việc triển khai cơ bản là mạnh mẽ và rộng rãi, hỗ trợ FTP/FTPS/TFTP (tải lên và tải), SSL/HTTPS, telnet, dict, ldap, và cũng hỗ trợ các tập tin cookie, chuyển hướng, xác thực, vv

Nhưng tôi không có chuyên môn trong R và đã không thể tìm thấy một ví dụ đơn sử dụng RCurl (hoặc bất kỳ thư viện R khác) để làm điều này ..

Ngay bây giờ tôi đang sử dụng CURL như thế này để có được những thành viên của một nhóm:

curl "ldap://ldap.replaceme.com/o=replaceme.com?memberuid?sub?(cn=group-name)" 

Bất cứ ai ở đây đều biết cách làm tương tự trong R với RCurl?

+2

Chúng tôi cần phải biết thêm một chút thông tin về cấu hình máy chủ LDAP. Một ví dụ truy vấn LDAP thông qua 'curl -u USERNAME 'ldap: //192.168.0.66/CN=Users, DC=training ,DC=local \? SAMAccountName? Sub? (ObjectClass = *)'' (đó là từ một ví dụ của IBM) . Nó sẽ không làm việc cho bạn vì bạn cần phải biết các thông số tìm kiếm thích hợp. Nó khá đơn giản để chạy nó thông qua 'RCurl' và sau đó xử lý các kết quả, nhưng nếu bạn sẽ nhận được truy vấn làm việc từ' curl' trên dòng lệnh đầu tiên. – hrbrmstr

+1

Ngay bây giờ tôi đang lấy danh sách các thành viên của một nhóm như thế này: 'ldapsearch -t -h ldap.replaceme.com -x -b" o = replaceme.com "" (cn = group-name) "memberuid' – Luxspes

+0

@hrbrmstr nếu bạn có thể dịch 'ldapsearch' tôi cho 'curl' và sau đó cho' r' với 'RCurl', đó sẽ là câu trả lời chính xác tôi đang tìm kiếm ... – Luxspes

Trả lời

5

Tìm thấy câu trả lời bản thân mình:

chạy đầu tiên lệnh này để đảm bảo RCurl được cài đặt (như mô tả trong http://www.programmingr.com/content/webscraping-using-readlines-and-rcurl/):

install.packages("RCurl", dependencies = TRUE) 
library("RCurl") 

Và sau đó getURL người dùng với một URL ldap (như mô tả trong http://www.ietf.org/rfc/rfc2255.txt mặc dù tôi không thể hiểu được nó cho đến khi tôi đọc http://docs.oracle.com/cd/E19396-01/817-7616/ldurl.html và thấy ldap[s]://hostname:port/base_dn?attributes?scope?filter):

getURL("ldap://ldap.replaceme.com/o=replaceme.com?memberuid?sub?(cn=group-name)") 
+0

Trên một lưu ý liên quan này là một hướng dẫn tuyệt vời về việc sử dụng RCurl http://www.omegahat.org/RCurl/RCurlJSS. pdf – Luxspes

5

Tôi đã viết một hàm ở đây để phân tích đầu ra ldap thành một khung dữ liệu, và tôi đã sử dụng các ví dụ được cung cấp làm tham chiếu để nhận mọi thứ.

Tôi hy vọng nó sẽ giúp ai đó!

library(RCurl) 
library(gtools) 

parseldap<-function(url, userpwd=NULL) 
{ 
    ldapraw<-getURL(url, userpwd=userpwd) 
    # seperate by two new lines 
    ldapraw<-gsub("(DN: .*?)\n", "\\1\n\n", ldapraw) 
    ldapsplit<-strsplit(ldapraw, "\n\n") 
    ldapsplit<-unlist(ldapsplit) 
    # init list and count 
    mylist<-list() 
    count<-0 
    for (ldapline in ldapsplit) { 
    # if this is the beginning of the entry 
    if(grepl("^DN:", ldapline)) { 
     count<-count+1 
     # after the first 
     if(count == 2) { 
     df<-data.frame(mylist) 
     mylist<-list() 
     } 
     if(count > 2) { 
     df<-smartbind(df, mylist) 
     mylist<-list() 
     } 
     mylist["DN"] <-gsub("^DN: ", "", ldapline) 
    } else { 
     linesplit<-unlist(strsplit(ldapline, "\n")) 
     if(length(linesplit) > 1) { 
     for(line in linesplit) { 
      linesplit2<-unlist(strsplit(line, "\t")) 
      linesplit2<-unlist(strsplit(linesplit2[2], ": ")) 
      if(!is.null(unlist(mylist[linesplit2[1]]))) { 
      x<-strsplit(unlist(mylist[linesplit2[1]]), "|", fixed=TRUE) 

      x<-append(unlist(x), linesplit2[2]) 
      x<-paste(x, sep="", collapse="|") 
      mylist[linesplit2[1]] <- x 
      } else { 
      mylist[linesplit2[1]] <- linesplit2[2] 
      } 
     } 
     } else { 
     ldaplinesplit<-unlist(strsplit(ldapline, "\t")) 
     ldaplinesplit<-unlist(strsplit(ldaplinesplit[2], ": ")) 
     mylist[ldaplinesplit[1]] <- ldaplinesplit[2] 
     } 

    } 

    } 
    if(count == 1) { 
    df<-data.frame(mylist) 
    } else { 
    df<-smartbind(df, mylist) 
    } 
    return(df) 
} 
0

Tôi đi theo chiến lược này:

  1. chạy một kịch bản Perl với một truy vấn LDAP, ghi dữ liệu vào đĩa như JSON.
  2. đọc trong cấu trúc json với R, tạo một khung dữ liệu.

Đối với bước (1), tôi đã sử dụng kịch bản này:

#use Modern::Perl; 
use strict; 
use warnings; 
use feature 'say'; 
use Net::LDAP; 
use JSON; 
chdir("~/git/_my/R_one-offs/R_grabbag"); 
my $ldap = Net::LDAP->new('ldap.mydomain.de') or die "[email protected]"; 
my $outfile = "ldapentries_mydomain_ldap.json"; 
my $mesg = $ldap->bind ; # an anonymous bind 
# get all cn's (= all names) 
$mesg = $ldap->search(
       base => " ou=People,dc=mydomain,dc=de", 
       filter => "(cn=*)" 
      ); 

my $json_text = ""; 
my @entries; 

foreach my $entry ($mesg->entries){ 
my %entry; 
foreach my $attr ($entry->attributes) { 
    foreach my $value ($entry->get_value($attr)) { 
     $entry{$attr} = $value; 
    } 
    } 
    push @entries, \%entry; 
} 

$json_text = to_json(\@entries); 
say "Length json_text: " . length($json_text); 


open(my $FH, ">", $outfile); 
print $FH $json_text; 
close($FH); 
$mesg = $ldap->unbind; 

Bạn có thể cần kiểm tra giới hạn kích thước tối đa là mục trả về bởi máy chủ ldap. Xem https://serverfault.com/questions/328671/paging-using-ldapsearch

Đối với bước (2), tôi đã sử dụng mã R này:

setwd("~/git/_my/R_one-offs/R_grabbag") 
library(rjson) 
# read into R list, from file, created from perl script 
json <- rjson::fromJSON(file="ldapentries_mydomain_ldap.json",method = "C") 
head(json) 

# create a data frame from list 
library(reshape2) 
library(dplyr) 
library(tidyr) 

# not really efficient, maybe thre's a better way to do it 
df.ldap <- json %>% melt %>% spread(L2,value) 

# optional: 
# turn factors into characters 
i <- sapply(df.ldap, is.factor) 
df.ldap[i] <- lapply(df.ldap[i], as.character) 
Các vấn đề liên quan