2014-04-01 14 views
5

Voglio fare una query su una directory LDAP di come i dipendenti sono distribuiti in dipartimenti e gruppi ...Come si esegue una query ldap utilizzando R?

Qualcosa come: "Dammi il nome del reparto di tutti i membri di un gruppo" e poi utilizzate R per fare un'analisi della frequenza, ma non riesco a trovare nessuna esempi su come collegare ed eseguire una query LDAP utilizzando R.

RCurl sembra avere un qualche tipo di supporto (http://cran.r-project.org/web/packages/RCurl/index.html):

Inoltre, l'implementazione sottostante è robusta ed estesa, di supporto/FTPS/TFTP (upload e download) FTP, SSL/HTTPS, Telnet, dict, LDAP, e supporta anche biscotti, redirect, autenticazione, ecc

Ma non sono un esperto in R e non sono stati in grado di trovare un solo esempio utilizzando RCurl (o qualsiasi altra libreria R) per fare questo ..

In questo momento sto usando CURL come questo per ottenere i membri di un gruppo:

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

Chiunque qui sa come fare lo stesso in R con RCurl?

+2

avremmo bisogno di conoscere un po 'di più sulla configurazione del server LDAP. Un esempio di query LDAP tramite 'curl -u USERNAME 'ldap: //192.168.0.66/CN=Users,DC=training,DC=local \? SAMAccountName? Sub? (ObjectClass = *)'' (proveniente da un esempio IBM) . Non funzionerà per te dal momento che devi conoscere i parametri di ricerca corretti. È piuttosto semplice eseguirlo tramite 'RCurl' e quindi elaborare i risultati, ma se si deve ottenere la query dal comando' curl' sulla riga di comando prima. – hrbrmstr

+1

In questo momento sto recuperando la lista dei membri di un gruppo come questo: 'ldapsearch -t -h ldap.replaceme.com -x -b" o = replaceme.com "" (cn = nome-gruppo) "memberuid' – Luxspes

+0

@hrbrmstr se puoi tradurre il mio 'ldapsearch' in' curl' e poi in 'R' con' RCurl', questa sarebbe la risposta esatta che sto cercando ... – Luxspes

risposta

5

trovato la risposta me stesso:

Prima esecuzione questi comandi per assicurarsi che RCurl sia installato (come descritto in http://www.programmingr.com/content/webscraping-using-readlines-and-rcurl/):

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

E poi getURL utente con un URL LDAP (come descritto nella http://www.ietf.org/rfc/rfc2255.txt anche se non riuscivo a capire fino a quando ho letto e ho visto http://docs.oracle.com/cd/E19396-01/817-7616/ldurl.htmlldap[s]://hostname:port/base_dn?attributes?scope?filter):

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

Su una nota correlata questa è un'ottima guida sull'uso di RCurl http://www.omegahat.org/RCurl/RCurlJSS. PDF – Luxspes

5

Ho scritto una funzione qui per analizzare l'output di ldap in un dataframe, e ho usato gli esempi forniti come riferimento per far funzionare tutto.

Spero che aiuti qualcuno!

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

ho seguito questa strategia:

  1. run uno script Perl con una query LDAP, scrivere i dati sul disco come JSON.
  2. leggere nella struttura JSON con R, creare un dataframe.

Per il passaggio (1), ho usato questo script:

#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; 

Potrebbe essere necessario controllare il limite di dimensione un massimo di voci restituite dal server LDAP. Vedere https://serverfault.com/questions/328671/paging-using-ldapsearch

Per il passaggio (2), ho usato questo codice R:

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) 
Problemi correlati