| #!/usr/bin/perl -w |
| |
| # $0 -b "ou=People,dc=borgia,dc=com" -Q /dev/with/quota=0:0:0:0 -F '(attr=value)' |
| |
| # Synopsis |
| # setSystemQuotas.pl is a script solely for modifying the quota attribute in |
| # LDAP. It expects that the users you intend to have quotas already have the |
| # systemQuotas objectClass set. |
| # This tool is capable of applying standard LDAP filters to the user-supplied |
| # base DN for modifying multiple users' quotas at once. |
| |
| # Examples: |
| # Set quota on /dev/sda7 and /dev/sda8 for user stefan |
| # ./setSystemQuotas.pl -b "uid=stefan,ou=People,dc=borgia,dc=com" -Q /dev/sda7=4000000:4400000:10000:11000 -Q /dev/sda8=4000000:4400000:10000:11000 |
| # |
| # Set quota on /dev/sda8 for user all People with description of Student |
| # ./setSystemQuotas.pl -b "ou=People,dc=borgia,dc=com" -Q /dev/sda8=40000:44000:1000:1100 -F "(description=Student)" |
| # |
| # Delete quotas for user stefan |
| # ./setSystemQuotas.pl -b "uid=stefan,ou=People,dc=borgia,dc=com" |
| |
| use strict; |
| use Net::LDAP; |
| use Getopt::Long; |
| |
| chomp(my $Password = `cat /etc/ldap.secret`); |
| my $Host = 'localhost'; |
| my $Port = '389'; |
| my $BindDN = 'cn=Manager,dc=borgia,dc=com'; |
| my $SSL = 0; |
| |
| my $b = ''; |
| my %Q = (); |
| my $F = ''; |
| GetOptions( |
| 'b=s' => \$b, |
| 'Q=s' => \%Q, |
| 'F=s' => \$F, |
| ); |
| die "Usage: $0 -b userdn [-F '(extrafilter)'] [-Q /fs=sb:hb:sf:hf ...]\n" unless $b; |
| foreach ( keys %Q ) { |
| local @_ = split /:/, $Q{$_}; |
| unless ( $#_ == 3 ) { |
| print "Ignoring $_: invalid format\n"; |
| delete $Q{$_}; |
| } |
| } |
| |
| my $ldap = connectLDAP(); |
| |
| my $quota = {}; |
| my $search; |
| $search = $ldap->search( |
| base => $b, |
| filter => "(&(objectClass=systemQuotas)$F)", |
| attrs => ['*', 'quota'], |
| ); |
| $search->code && die $search->error; |
| my $i = 0; |
| my $max = $search->count; |
| for ( $i=0; $i<$max; $i++ ) { |
| my $entry = $search->entry($i); |
| my $dn = $entry->dn; |
| if ( keys %Q ) { |
| $quota->{$dn} = 1; |
| foreach ( $entry->get_value('quota') ) { |
| my @quota = split /:/; |
| my $fs = shift @quota; |
| delete $quota->{$dn} if $quota->{$dn} == 1; |
| $quota->{$dn}->{$fs} = join ':', @quota; |
| } |
| } else { |
| $quota->{$dn} = 0; |
| delete $quota->{$dn} unless $entry->get_value('quota'); |
| } |
| } |
| |
| foreach my $dn ( keys %{$quota} ) { |
| if ( ref $quota->{$dn} eq 'HASH' ) { |
| print STDERR "Modify $dn:\n"; |
| foreach ( keys %Q ) { |
| print STDERR "\t$_:$Q{$_}\n"; |
| $quota->{$dn}->{$_} = $Q{$_}; |
| } |
| my @quota = map { "$_:$quota->{$dn}->{$_}" } keys %{$quota->{$dn}}; |
| my $modify = $ldap->modify( |
| $dn, |
| replace => { |
| quota => [@quota], |
| }, |
| ); |
| $modify->code && warn "Failed to modify quota: ", $modify->error, "\n"; |
| } else { |
| if ( $quota->{$dn} == 1 ) { |
| delete $quota->{$dn}; |
| print STDERR "Add $dn:\n"; |
| foreach ( keys %Q ) { |
| print STDERR "\t$_:$Q{$_}\n"; |
| $quota->{$dn}->{$_} = $Q{$_} |
| } |
| my @quota = map { "$_:$quota->{$dn}->{$_}" } keys %{$quota->{$dn}}; |
| my $modify = $ldap->modify( |
| $dn, |
| add => { |
| quota => [@quota], |
| }, |
| ); |
| $modify->code && warn "Failed to modify quota: ", $modify->error, "\n"; |
| } elsif ( $quota->{$dn} == 0 ) { |
| print STDERR "Delete $dn:\n"; |
| my $modify = $ldap->modify( |
| $dn, |
| delete => ['quota'], |
| ); |
| $modify->code && warn "Failed to modify quota: ", $modify->error, "\n"; |
| } |
| } |
| } |
| $ldap->unbind; |
| |
| sub connectLDAP { |
| # bind to a directory with dn and password |
| my $ldap = Net::LDAP->new( |
| $Host, |
| port => $Port, |
| version => 3, |
| # debug => 0xffff, |
| ) or die "Can't contact LDAP server ($@)\n"; |
| if ( $SSL ) { |
| $ldap->start_tls( |
| # verify => 'require', |
| # clientcert => 'mycert.pem', |
| # clientkey => 'mykey.pem', |
| # decryptkey => sub { 'secret'; }, |
| # capath => '/usr/local/cacerts/' |
| ); |
| } |
| $ldap->bind($BindDN, password=>$Password); |
| return $ldap; |
| } |