Guest User

Untitled

a guest
Jul 18th, 2018
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.62 KB | None | 0 0
  1. #!/usr/local/bin/perl
  2. #
  3. # We use /usr/local/bin/perl because cygwin installs in /usr/bin/perl and we want to
  4. # use ActiveState Perl on Windows. As a result, we have to symlink all others
  5. # links:
  6. # !compiled_on_cygwin::
  7. # /usr/local/bin/perl -> /usr/bin/perl type=symbolic
  8. #
  9. use strict;
  10. # This is the LDAP module that makes all the dynamic stuff in cfengine work
  11. # determine this host's fqdn
  12. # determine this host's domain name
  13. # do a srv record lookup for ldap tcp 636 on this domain name
  14. #
  15. # if this host's fqdn is one of the returned records:
  16. # try to connect to self's fqdn for LDAP,
  17. # then try to connect to other records until one connects
  18. # if one is reached:
  19. # look up cn=hostname, ou=Hosts, dc=domain, dc=domain, dc=domain
  20. # and activate all classes in record and exit.
  21. # if record is not found, back-off and retry on next pass.
  22. # if none of the ldap servers can be reached, including oneself then assume localhost
  23. # is the first of it's kind and:
  24. # activate core_server, which will:
  25. # activate cfengine_server
  26. # (if debian) update /etc/apt/sources.list to use backports
  27. # (if debian) create /etc/apt/preferences to mask backports for !git
  28. # install git
  29. # install git2masterfiles
  30. # activate certificate_authority
  31. # using "secret" create caroot tree
  32. # using "secret" create gpg identity
  33. # activate ldap_server, which will:
  34. # add slapd.conf for self's domain name (determined earlier) if not exists
  35. # start slapd,
  36. # create self's host record if it doesn't exist,
  37. # define classes for self
  38. # setup and run all core services
  39. #
  40. # if no ldap servers are reachable and the fqdn is not in the _ldap._tcp srv list,
  41. # then take no action; Assume the host is disconnected from the core completely.
  42. #
  43.  
  44. package Superstring;
  45. use Data::Dumper;
  46.  
  47. sub new{
  48. use Sys::Hostname;
  49. use Sys::Hostname::Long;
  50. use FileHandle;
  51. my $class = shift;
  52. my $construct = shift if @_;
  53. my $self = { };
  54. bless ($self, $class);
  55. $self->{'cfg'}->{'fqdn'} = hostname_long();
  56. $self->{'cfg'}->{'hostname'} = hostname();
  57. $self->{'cfg'}->{'hostname'}=~s/\..*//g;
  58. $self->{'cfg'}->{'domain'} = $self->{'cfg'}->{'fqdn'};
  59. $self->{'cfg'}->{'domain'} =~ s/^$self->{'cfg'}->{'hostname'}\.//;
  60. $self->{'cfg'}->{'base_dn'} = $self->{'cfg'}->{'domain'};
  61. $self->{'cfg'}->{'base_dn'} =~ s/^/dc=/;
  62. $self->{'cfg'}->{'base_dn'} =~ s/\./,dc=/;
  63. if(-f "/usr/local/sbin/secret"){
  64. my $sech = new FileHandle;
  65. if($sech->open("/usr/local/sbin/secret|")){
  66. $self->{'cfg'}->{'secret'}=<$sech>;
  67. $sech->close;
  68. }
  69. }
  70. if($self->{'cfg'}->{'domain'} ne ""){
  71. return $self;
  72. }
  73. return undef;
  74. }
  75. ###################################################
  76. # Get all the DNS records that could determine
  77. # what this host is supposed to be
  78. ###################################################
  79. sub get_dns_records(){
  80. use Net::DNS;
  81. my $self = shift;
  82. my $res = Net::DNS::Resolver->new;
  83. my $query = $res->query("_ldap._tcp.".$self->{'cfg'}->{'domain'}, "SRV");
  84. if ($query){
  85. foreach my $rr (grep { $_->type eq 'SRV' } $query->answer) {
  86. push(@{ $self->{'cfg'}->{'ldap_servers'} },$rr->target);
  87. if($rr->target eq $self->{'cfg'}->{'fqdn'}){
  88. push(@{ $self->{'cfclasses'} },"ldap_server");
  89. }
  90. }
  91. }else{
  92. push(@{ $self->{'cfclasses'} },'dns_errors');
  93. warn "query failed: ", $res->errorstring, "\n";
  94. }
  95. my $query = $res->query($self->{'cfg'}->{'domain'}, "NS");
  96. if ($query){
  97. foreach my $rr (grep { $_->type eq 'NS' } $query->answer) {
  98. my $nameserver=$rr->nsdname;
  99. my $res2 = Net::DNS::Resolver->new;
  100. my $subquery = $res2->query($nameserver, "A");
  101. if ($subquery){
  102. foreach my $rra (grep { $_->type eq 'A' } $subquery->answer) {
  103. push(@{ $self->{'cfg'}->{'dns'}->{'a'}->{$nameserver} },$rra->address);
  104. my $res3 = Net::DNS::Resolver->new;
  105. my $ptrquery = $res2->query($rra->address, "PTR");
  106. if ($ptrquery){
  107. foreach my $rrp (grep { $_->type eq 'PTR' } $ptrquery->answer) {
  108. push(@{ $self->{'cfg'}->{'dns'}->{'ptr'}->{$rra->address} },$rrp->ptrdname);
  109. if($rrp->ptrdname eq $self->{'cfg'}->{'fqdn'}){
  110. push(@{ $self->{'cfclasses'} },"bind9_server");
  111. }
  112. }
  113. }else{
  114. push(@{ $self->{'cfclasses'} },'dns_errors');
  115. warn "query failed: ", $res3->errorstring, "\n";
  116. }
  117. }
  118. }else{
  119. push(@{ $self->{'cfclasses'} },'dns_errors');
  120. warn "query failed: ", $res2->errorstring, "\n";
  121. }
  122. push(@{ $self->{'cfg'}->{'dns'}->{'ns'} },$rr->nsdname);
  123. if($rr->nsdname eq $self->{'cfg'}->{'fqdn'}){
  124. push(@{ $self->{'cfclasses'} },"bind9_server");
  125. }
  126. }
  127. }else{
  128. warn "query failed: ", $res->errorstring, "\n";
  129. }
  130. return $self;
  131. }
  132.  
  133. sub add_classes(){
  134. my $self=shift;
  135. foreach my $c (@_){
  136. push(@{ $self->{'cfclasses'} }, $c);
  137. }
  138. return $self;
  139. }
  140.  
  141. sub dumpclasses(){
  142. my $self=shift;
  143. foreach my $c (@{ $self->{'cfclasses'} }){
  144. print "+",$c,"\n";
  145. }
  146. return $self;
  147. }
  148.  
  149. sub dumpvariables(){
  150. my $self=shift;
  151. foreach my $k (keys(%{ $self->{'variables'} })){
  152. print "=",$k,"=",$self->{'variables'}->{$k},"\n";
  153. }
  154. return $self;
  155. }
  156.  
  157. sub ldap_servers{
  158. my $self=shift;
  159. return $self->{'cfg'}->{'ldap_servers'} if defined $self->{'cfg'}->{'ldap_servers'};
  160. return undef;
  161. }
  162.  
  163. sub domain{
  164. my $self=shift;
  165. return $self->{'cfg'}->{'domain'} if defined $self->{'cfg'}->{'domain'};
  166. return undef;
  167. }
  168.  
  169. sub base_hostname{
  170. my $self=shift;
  171. return $self->{'cfg'}->{'hostname'} if defined $self->{'cfg'}->{'hostname'};
  172. return undef;
  173. }
  174.  
  175. sub fqdomain{
  176. my $self=shift;
  177. return $self->{'cfg'}->{'fqdn'} if defined $self->{'cfg'}->{'fqdn'};
  178. return undef;
  179. }
  180.  
  181. ###################################################
  182. # Attempt to contact all the LDAP Servers
  183. # and get this hosts LDAP record
  184. ###################################################
  185. sub ldapsearch{
  186. use Net::LDAP;
  187. my $self=shift;
  188. my $setup=shift;
  189. my $returnlist;
  190. my $ldap = Net::LDAP->new( $setup->{'host'}, timeout => 10) or warn "$@";
  191. my $mesg;
  192. if($ldap){
  193. if(defined($self->{'cfg'}->{'secret'})){
  194. $mesg = $ldap->bind(
  195. "cn=$self->{'cfg'}->{'hostname'},ou=Hosts,$self->{'cfg'}->{'base_dn'}",
  196. password=> $self->{'cfg'}->{'secret'}
  197. );
  198. }else{
  199. $mesg = $ldap->bind; # an anonymous bind
  200. }
  201. $mesg = $ldap->search( base => $setup->{'basedn'},scope=>'base',filter => "($setup->{'search'})");
  202. $mesg->code && warn $mesg->error;
  203. foreach my $entry ($mesg->entries) { push(@{$returnlist},$entry); }
  204. $mesg = $ldap->unbind; # take down session
  205. }
  206. return $returnlist;
  207. }
  208.  
  209. sub host_ldap_record(){
  210. my $self=shift;
  211. my $host=shift;
  212. my $basedn="cn=".$self->base_hostname().",ou=Hosts,dc=".join(",dc=",split(/\./,$self->domain()));
  213. my $searchdn="cn=".$self->base_hostname();
  214. # loop through ldap_records and see if we are one of them...
  215. my $iamone=0;
  216. foreach my $ldap_server (@{$self->ldap_servers}){
  217. if($self->{'cfg'}->{'fqdn'} eq $ldap_server){ $iamone=1; }
  218. }
  219. # first try to fetch the record from oneself
  220. if($iamone){
  221. # get host record from our self
  222. print STDERR "Searching for $searchdn via ldap://".$self->fqdomain().":636\n";
  223. $self->{'cfg'}->{'ldap'}->{'hostrecord'}=$self->ldapsearch({'host'=>$self->fqdomain(),'basedn'=>$basedn,'search'=>$searchdn});
  224. }
  225. if(!defined( $self->{'cfg'}->{'ldap'}->{'hostrecord'} )){
  226. foreach my $ldap_server (@{$self->ldap_servers}){
  227. # We already tried self...
  228. next if(($self->{'cfg'}->{'fqdn'} eq $ldap_server)||(defined($self->{'cfg'}->{'ldap'}->{'hostrecord'})));
  229. print STDERR "Searching for $searchdn via ldap://".$ldap_server.":636\n";
  230. $self->{'cfg'}->{'ldap'}->{'hostrecord'}=$self->ldapsearch({'host'=>$ldap_server,'basedn'=>$basedn,'search'=>$searchdn});
  231. if(defined($self->{'cfg'}->{'ldap'}->{'hostrecord'})){ print STDERR "$searchdn found.\n"; }
  232. }
  233. }
  234. if(($iamone eq 1)&&(!defined( $self->{'cfg'}->{'ldap'}->{'hostrecord'} ))){
  235. $self->add_classes("core_server");
  236. }
  237. return $self;
  238. }
  239.  
  240. 1;
  241.  
  242. my $ss = Superstring->new();
  243. if($ss){
  244. $ss->get_dns_records();
  245. if(defined($ss->ldap_servers())){
  246. $ss->host_ldap_record($ss->fqdomain());
  247. foreach my $entry ( @{ $ss->{'cfg'}->{'ldap'}->{'hostrecord'} }){
  248. foreach my $attr ( $entry->attributes ){
  249. if($attr =~ /^configSet$/i){
  250. $ss->add_classes($entry->get_value( $attr ));
  251. }
  252. if($attr =~ /^configBase$/i){
  253. $ss->add_classes($entry->get_value( $attr ));
  254. }
  255. }
  256. }
  257. }else{
  258. print "No ldap server SRV records found in DNS\n";
  259. }
  260. binmode STDOUT;
  261. $ss->dumpclasses();
  262. $ss->dumpvariables();
  263. }
  264. #print Data::Dumper->Dump([$ss]);
Add Comment
Please, Sign In to add comment