#!/usr/bin/perl # # create_grants_from_template # - Simple script to generate a series of grants given some # configuration variables. # # Usage: create_grants_from_template < template_grants_file # # Variables are configured in the form of values defined on a single line: # # -- VARIABLE: %WEB_USER% = 'web'@'10.0.1.%' # -- VARIABLE: %WEB_USER% = 'web'@'10.0.2.%' # # or together on the same line separated by commas. # # -- VARIABLE: %WEB_USER% = 'web'@'10.0.1.%','web'@'10.0.2.%' # # A combination of both styles can be used. # # This script will recognise usage of these variables by repeating the # input lines containing these variables multiple times. # # If the following is used as input: # --------- input ------ #-- VARIABLE: %WEB_USER% = 'web'@'10.0.1.%' #-- VARIABLE: %WEB_USER% = 'web'@'10.0.2.%' # #-- Grants for the web user #GRANT USAGE ON *.* TO %WEB_USER% IDENTIFIED BY 'some_secret' WITH MAX_USER_CONNECTIONS 400; #GRANT SELECT ON some_db.* TO %WEB_USER%; # --------- input ------ # # the following output will be generated: # # --------- output ------ #-- VARIABLE: %WEB_USER% = 'web'@'10.0.1.%' #-- VARIABLE: %WEB_USER% = 'web'@'10.0.2.%' # #-- Grants for the web user #GRANT USAGE ON *.* TO 'web'@'10.0.1.%' IDENTIFIED BY 'some_secret' WITH MAX_USER_CONNECTIONS 400; #GRANT SELECT ON some_db.* TO 'web'@'10.0.1.%'; #-- Grants for the web user #GRANT USAGE ON *.* TO 'web'@'10.0.2.%' IDENTIFIED BY 'some_secret' WITH MAX_USER_CONNECTIONS 400; #GRANT SELECT ON some_db.* TO 'web'@'10.0.2.%'; # --------- output ------ # # License: # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You may have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, # USA. # # An on-line copy of the GNU General Public License can be found # http://www.fsf.org/copyleft/gpl.html. use strict; use warnings; my $variables = {}; my $line; my $pattern = '-- VARIABLE:\s+(\S+)\s*=\s*(.*)$'; sub msg_debug { print join( ' ', @_ ) . "\n" if $ENV{DEBUG}; } sub process_definition { my ( $line , $name, $values ) = @_; msg_debug( "process_definition('...', '$name', '...'" ); # add first empty value if the variable is not known # this allows us to do the following if needed: # -- VARIABLE: %VALUE% = one # -- VARIABLE: %VALUE% = two if ( not exists $variables->{$name} ) { msg_debug( "new variable $name" ); @{$variables->{$name}} = (); } my @individual_values = split( /,/, $values ); foreach my $value ( @individual_values ) { $value =~ s/^\s+//; # trim leading whitespace $value =~ s/\s+$//; # trim trailing whitespace next if $value eq ''; # skip empty variable settings push @{$variables->{$name}}, $value; } print $line . "\n"; } # Process a multiline block substituting values as needed print the # resultant string. # Note: if we have a variable with multiple values an extra block is # created for each additional value. sub process_block { my $block = shift; my $lines = scalar @{ $block }; if ( $lines == 0 ) { msg_debug( "process_block: nothing to process: lines = $lines" ); # return if nothing to process. return; } else { msg_debug( "process_block: something to process: lines = $lines" ); } # create the input string which are the concatanated lines my $input = join( "\n", @$block ); # this stores each output block (starting with 1, the input) my @output = ( $input ); # Iterate over variables substituting if found in the input. foreach my $name ( keys %$variables ) { msg_debug( "Found variable $name in block" ); if ( $input =~ /$name/ ) { my @new_output = (); foreach my $line ( @output ) { # if the variable has one value we just substitute it, but as it may have # more we need to create extra ouptut strings with the individual substitution values. foreach my $variable_value ( @{$variables->{$name}} ) { my $new_entry = $line; $new_entry =~ s/$name/$variable_value/g; push @new_output, $new_entry; } } @output = @new_output; } } # join the results together and print the output. $input = join( "\n", @output ) if @output; print $input . "\n"; } my $block = []; while ( <> ) { $line = $_; chomp $line; msg_debug( "processing: $line" ); # Parse the setting of variables by storing the name and values into a pointer to a hash if ( $line =~ /-- VARIABLE:\s+(\S+)\s*=\s*(.*)$/ ) { my ( $variable, $value ) = ( $1, $2 ); process_block( $block ); $block = []; process_definition ( $line, $variable, $value ); } elsif ( $line =~ /^\s*$/ ) { push @$block, $line; msg_debug( "found empty line in block, new total = " . scalar @{$block} ); process_block( $block ); $block = []; } else { push @$block, $line; msg_debug( "adding line to block, new total = " . scalar @{$block} ); } } # Process the final line(s) process_block( $block );