Miam is a tool to manage IAM. It defines the state of IAM using DSL, and updates IAM according to DSL.
Ruby

README.md

Miam

Miam is a tool to manage IAM.

It defines the state of IAM using DSL, and updates IAM according to DSL.

Gem Version Build Status Coverage Status

Notice

  • >= 0.2.0
  • >= 0.2.1
    • Support Managed Policy attach/detach
    • Support JSON format
  • >= 0.2.2
    • Improve update (show diff)
    • Support Template
    • Add --ignore-login-profile option
    • Sort policy array
  • >= 0.2.3
    • Support Custom Managed Policy
  • >= 0.2.4
    • Fix for Password Policy (RP#22)
    • Fix --target option for Policies (RP#21)
    • Fix for Rate exceeded (PR#23)
    • Fix for non-User credentials (PR#17)
    • Add --exclude option

Installation

Add this line to your application's Gemfile:

gem 'miam'

And then execute:

$ bundle

Or install it yourself as:

$ gem install miam

Usage

export AWS_ACCESS_KEY_ID='...'
export AWS_SECRET_ACCESS_KEY='...'
export AWS_REGION='us-east-1'
miam -e -o IAMfile  # export IAM
vi IAMfile
miam -a --dry-run
miam -a             # apply `IAMfile`

Help

Usage: miam [options]
    -p, --profile PROFILE_NAME
        --credentials-path PATH
    -k, --access-key ACCESS_KEY
    -s, --secret-key SECRET_KEY
    -r, --region REGION
    -a, --apply
    -f, --file FILE
        --dry-run
        --account-output FILE
    -e, --export
    -o, --output FILE
        --split
        --split-more
        --format=FORMAT
        --export-concurrency N
        --target REGEXP
        --exclude REGEXP
        --ignore-login-profile
        --no-color
        --no-progress
        --debug

IAMfile example

require 'other/iamfile'

user "bob", :path => "/developer/" do
  login_profile :password_reset_required=>true

  groups(
    "Admin"
  )

  policy "bob-policy" do
    {"Version"=>"2012-10-17",
     "Statement"=>
      [{"Action"=>
         ["s3:Get*",
          "s3:List*"],
        "Effect"=>"Allow",
        "Resource"=>"*"}]}
  end

  attached_managed_policies(
    # attached_managed_policy
  )
end

user "mary", :path => "/staff/" do
  # login_profile :password_reset_required=>true

  groups(
    # no group
  )

  policy "s3-readonly" do
    {"Version"=>"2012-10-17",
     "Statement"=>
      [{"Action"=>
         ["s3:Get*",
          "s3:List*"],
        "Effect"=>"Allow",
        "Resource"=>"*"}]}
  end

  policy "route53-readonly" do
    {"Version"=>"2012-10-17",
     "Statement"=>
      [{"Action"=>
         ["route53:Get*",
          "route53:List*"],
        "Effect"=>"Allow",
        "Resource"=>"*"}]}
  end

  attached_managed_policies(
    "arn:aws:iam::aws:policy/AdministratorAccess",
    "arn:aws:iam::123456789012:policy/my_policy"
  )
end

group "Admin", :path => "/admin/" do
  policy "Admin" do
    {"Statement"=>[{"Effect"=>"Allow", "Action"=>"*", "Resource"=>"*"}]}
  end
end

role "S3", :path => "/" do
  instance_profiles(
    "S3"
  )

  assume_role_policy_document do
    {"Version"=>"2012-10-17",
     "Statement"=>
      [{"Sid"=>"",
        "Effect"=>"Allow",
        "Principal"=>{"Service"=>"ec2.amazonaws.com"},
        "Action"=>"sts:AssumeRole"}]}
  end

  policy "S3-role-policy" do
    {"Version"=>"2012-10-17",
     "Statement"=>[{"Effect"=>"Allow", "Action"=>"*", "Resource"=>"*"}]}
  end
end

instance_profile "S3", :path => "/"

Rename

require 'other/iamfile'

user "bob2", :path => "/developer/", :renamed_from => "bob" do
  # ...
end

group "Admin2", :path => "/admin/". :renamed_from => "Admin" do
  # ...
end

Managed Policy attach/detach

user "bob", :path => "/developer/" do
  login_profile :password_reset_required=>true

  groups(
    "Admin"
  )

  policy "bob-policy" do
    # ...
  end

  attached_managed_policies(
    "arn:aws:iam::aws:policy/AmazonElastiCacheReadOnlyAccess"
  )
end

Custom Managed Policy

managed_policy "my-policy", :path=>"/" do
  {"Version"=>"2012-10-17",
   "Statement"=>
    [{"Effect"=>"Allow", "Action"=>"directconnect:Describe*", "Resource"=>"*"}]}
end

user "bob", :path => "/developer/" do
  login_profile :password_reset_required=>true

  groups(
    "Admin"
  )

  policy "bob-policy" do
    # ...
  end

  attached_managed_policies(
    "arn:aws:iam::123456789012:policy/my-policy"
  )
end

Use JSON

$ miam -e -o iam.json
   ᗧ 100%
Export IAM to `iam.json`

$ cat iam.json
{
  "users": {
    "bob": {
      "path": "/",
      "groups": [
        "Admin"
      ],
      "policies": {
      ...

$ miam -a -f iam.json --dry-run
Apply `iam.json` to IAM (dry-run)
   ᗧ 100%
No change

Use Template

template "common-policy" do
  policy "my-policy" do
    {"Version"=>context.version,
     "Statement"=>
      [{"Action"=>
         ["s3:Get*",
          "s3:List*"],
        "Effect"=>"Allow",
        "Resource"=>"*"}]}
  end
end

template "common-role-attrs" do
  assume_role_policy_document do
    {"Version"=>context.version,
     "Statement"=>
      [{"Sid"=>"",
        "Effect"=>"Allow",
        "Principal"=>{"Service"=>"ec2.amazonaws.com"},
        "Action"=>"sts:AssumeRole"}]}
  end
end

user "bob", :path => "/developer/" do
  login_profile :password_reset_required=>true

  groups(
    "Admin"
  )

  include_template "common-policy", version: "2012-10-17"
end

user "mary", :path => "/staff/" do
  # login_profile :password_reset_required=>true

  groups(
    # no group
  )

  context.version = "2012-10-17"
  include_template "common-policy"

  attached_managed_policies(
    "arn:aws:iam::aws:policy/AdministratorAccess",
    "arn:aws:iam::123456789012:policy/my_policy"
  )
end

role "S3", :path => "/" do
  instance_profiles(
    "S3"
  )

  include_template "common-role-attrs"

  policy "S3-role-policy" do
    {"Version"=>"2012-10-17",
     "Statement"=>[{"Effect"=>"Allow", "Action"=>"*", "Resource"=>"*"}]}
  end
end

Similar tools