#!/usr/bin/env ruby $: << File.expand_path("#{File.dirname __FILE__}/../lib") require 'rubygems' require 'miam' require 'fileutils' require 'optparse' Version = Miam::VERSION DEFAULT_FILENAME = 'IAMfile' mode = nil file = DEFAULT_FILENAME output_file = '-' account_output = 'account.csv' split = false MAGIC_COMMENT = <<-EOS # -*- mode: ruby -*- # vi: set ft=ruby : EOS options = { :dry_run => false, :format => :ruby, :color => true, :debug => false, } options[:password_manager] = Miam::PasswordManager.new(account_output, options) ARGV.options do |opt| begin access_key = nil secret_key = nil region = nil profile_name = nil credentials_path = nil format_passed = false opt.on('-p', '--profile PROFILE_NAME') {|v| profile_name = v } opt.on('' , '--credentials-path PATH') {|v| credentials_path = v } opt.on('-k', '--access-key ACCESS_KEY') {|v| access_key = v } opt.on('-s', '--secret-key SECRET_KEY') {|v| secret_key = v } opt.on('-r', '--region REGION') {|v| region = v } opt.on('-a', '--apply') { mode = :apply } opt.on('-f', '--file FILE') {|v| file = v } opt.on('' , '--dry-run') { options[:dry_run] = true } opt.on('' , '--account-output FILE') {|v| options[:password_manager] = Miam::PasswordManager.new(v, options) } opt.on('-e', '--export') { mode = :export } opt.on('-o', '--output FILE') {|v| output_file = v } opt.on('' , '--split') { split = true } opt.on('' , '--split-more') { split = :more } opt.on('', '--format=FORMAT', [:ruby, :json]) {|v| format_passed = true; options[:format] = v } opt.on('' , '--export-concurrency N', Integer) {|v| options[:export_concurrency] = v } opt.on('' , '--target REGEXP') {|v| options[:target] = Regexp.new(v) } opt.on('' , '--no-color') { options[:color] = false } opt.on('' , '--no-progress') { options[:no_progress] = true } opt.on('' , '--debug') { options[:debug] = true } opt.parse! aws_opts = {} if access_key and secret_key aws_opts.update( :access_key_id => access_key, :secret_access_key => secret_key ) elsif profile_name or credentials_path credentials_opts = {} credentials_opts[:profile_name] = profile_name if profile_name credentials_opts[:path] = credentials_path if credentials_path credentials = Aws::SharedCredentials.new(credentials_opts) aws_opts[:credentials] = credentials elsif (access_key and !secret_key) or (!access_key and secret_key) or mode.nil? puts opt.help exit 1 end aws_opts[:region] = region if region Aws.config.update(aws_opts) if not format_passed and [file, output_file].any? {|i| i =~ /\.json\z/ } options[:format] = :json end rescue => e $stderr.puts("[ERROR] #{e.message}") exit 1 end end String.colorize = options[:color] if options[:debug] Aws.config.update( :http_wire_trace => true, :logger => Miam::Logger.instance ) end begin logger = Miam::Logger.instance logger.set_debug(options[:debug]) client = Miam::Client.new(options) case mode when :export if split logger.info('Export IAM') output_file = DEFAULT_FILENAME if output_file == '-' requires = [] client.export(:split_more => (split == :more), :convert => (options[:format] == :ruby)) do |args| type, dsl = args.values_at(:type, :dsl) next if dsl.empty? type = type.to_s dir = File.dirname(output_file) if split == :more name = args[:name] dir = File.join(dir, type) FileUtils.mkdir_p(dir) iam_filename = "#{name}.iam" iam_file = File.join(dir, iam_filename) requires << File.join(type, iam_filename) else iam_filename = "#{type}.iam" iam_file = File.join(dir, iam_filename) requires << iam_filename end if options[:format] == :json iam_file << '.json' end logger.info(" write `#{iam_file}`") open(iam_file, 'wb') do |f| f.puts MAGIC_COMMENT if options[:format] == :ruby f.puts dsl end end if options[:format] == :ruby logger.info(" write `#{output_file}`") open(output_file, 'wb') do |f| f.puts MAGIC_COMMENT requires.each do |iam_file| f.puts "require '#{iam_file}'" end end end else exported = client.export(:convert => (options[:format] == :ruby)) if output_file == '-' logger.info('# Export IAM') puts exported else logger.info("Export IAM to `#{output_file}`") open(output_file, 'wb') do |f| f.puts MAGIC_COMMENT if options[:format] == :ruby f.puts exported end end end when :apply unless File.exist?(file) raise "No IAMfile found (looking for: #{file})" end msg = "Apply `#{file}` to IAM" msg << ' (dry-run)' if options[:dry_run] logger.info(msg) updated = client.apply(file) logger.info('No change'.intense_blue) unless updated end rescue => e if options[:debug] raise e else $stderr.puts("[ERROR] #{e.message}".red) exit 1 end end