setSystemQuotas.pl 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #!/usr/bin/perl -w
  2. # $0 -b "ou=People,dc=borgia,dc=com" -Q /dev/with/quota=0:0:0:0 -F '(attr=value)'
  3. # Synopsis
  4. # setSystemQuotas.pl is a script solely for modifying the quota attribute in
  5. # LDAP. It expects that the users you intend to have quotas already have the
  6. # systemQuotas objectClass set.
  7. # This tool is capable of applying standard LDAP filters to the user-supplied
  8. # base DN for modifying multiple users' quotas at once.
  9. # Examples:
  10. # Set quota on /dev/sda7 and /dev/sda8 for user stefan
  11. # ./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
  12. #
  13. # Set quota on /dev/sda8 for user all People with description of Student
  14. # ./setSystemQuotas.pl -b "ou=People,dc=borgia,dc=com" -Q /dev/sda8=40000:44000:1000:1100 -F "(description=Student)"
  15. #
  16. # Delete quotas for user stefan
  17. # ./setSystemQuotas.pl -b "uid=stefan,ou=People,dc=borgia,dc=com"
  18. use strict;
  19. use Net::LDAP;
  20. use Getopt::Long;
  21. chomp(my $Password = `cat /etc/ldap.secret`);
  22. my $Host = 'localhost';
  23. my $Port = '389';
  24. my $BindDN = 'cn=Manager,dc=borgia,dc=com';
  25. my $SSL = 0;
  26. my $b = '';
  27. my %Q = ();
  28. my $F = '';
  29. GetOptions(
  30. 'b=s' => \$b,
  31. 'Q=s' => \%Q,
  32. 'F=s' => \$F,
  33. );
  34. die "Usage: $0 -b userdn [-F '(extrafilter)'] [-Q /fs=sb:hb:sf:hf ...]\n" unless $b;
  35. foreach ( keys %Q ) {
  36. local @_ = split /:/, $Q{$_};
  37. unless ( $#_ == 3 ) {
  38. print "Ignoring $_: invalid format\n";
  39. delete $Q{$_};
  40. }
  41. }
  42. my $ldap = connectLDAP();
  43. my $quota = {};
  44. my $search;
  45. $search = $ldap->search(
  46. base => $b,
  47. filter => "(&(objectClass=systemQuotas)$F)",
  48. attrs => ['*', 'quota'],
  49. );
  50. $search->code && die $search->error;
  51. my $i = 0;
  52. my $max = $search->count;
  53. for ( $i=0; $i<$max; $i++ ) {
  54. my $entry = $search->entry($i);
  55. my $dn = $entry->dn;
  56. if ( keys %Q ) {
  57. $quota->{$dn} = 1;
  58. foreach ( $entry->get_value('quota') ) {
  59. my @quota = split /:/;
  60. my $fs = shift @quota;
  61. delete $quota->{$dn} if $quota->{$dn} == 1;
  62. $quota->{$dn}->{$fs} = join ':', @quota;
  63. }
  64. } else {
  65. $quota->{$dn} = 0;
  66. delete $quota->{$dn} unless $entry->get_value('quota');
  67. }
  68. }
  69. foreach my $dn ( keys %{$quota} ) {
  70. if ( ref $quota->{$dn} eq 'HASH' ) {
  71. print STDERR "Modify $dn:\n";
  72. foreach ( keys %Q ) {
  73. print STDERR "\t$_:$Q{$_}\n";
  74. $quota->{$dn}->{$_} = $Q{$_};
  75. }
  76. my @quota = map { "$_:$quota->{$dn}->{$_}" } keys %{$quota->{$dn}};
  77. my $modify = $ldap->modify(
  78. $dn,
  79. replace => {
  80. quota => [@quota],
  81. },
  82. );
  83. $modify->code && warn "Failed to modify quota: ", $modify->error, "\n";
  84. } else {
  85. if ( $quota->{$dn} == 1 ) {
  86. delete $quota->{$dn};
  87. print STDERR "Add $dn:\n";
  88. foreach ( keys %Q ) {
  89. print STDERR "\t$_:$Q{$_}\n";
  90. $quota->{$dn}->{$_} = $Q{$_}
  91. }
  92. my @quota = map { "$_:$quota->{$dn}->{$_}" } keys %{$quota->{$dn}};
  93. my $modify = $ldap->modify(
  94. $dn,
  95. add => {
  96. quota => [@quota],
  97. },
  98. );
  99. $modify->code && warn "Failed to modify quota: ", $modify->error, "\n";
  100. } elsif ( $quota->{$dn} == 0 ) {
  101. print STDERR "Delete $dn:\n";
  102. my $modify = $ldap->modify(
  103. $dn,
  104. delete => ['quota'],
  105. );
  106. $modify->code && warn "Failed to modify quota: ", $modify->error, "\n";
  107. }
  108. }
  109. }
  110. $ldap->unbind;
  111. sub connectLDAP {
  112. # bind to a directory with dn and password
  113. my $ldap = Net::LDAP->new(
  114. $Host,
  115. port => $Port,
  116. version => 3,
  117. # debug => 0xffff,
  118. ) or die "Can't contact LDAP server ($@)\n";
  119. if ( $SSL ) {
  120. $ldap->start_tls(
  121. # verify => 'require',
  122. # clientcert => 'mycert.pem',
  123. # clientkey => 'mykey.pem',
  124. # decryptkey => sub { 'secret'; },
  125. # capath => '/usr/local/cacerts/'
  126. );
  127. }
  128. $ldap->bind($BindDN, password=>$Password);
  129. return $ldap;
  130. }