LoginSignup
0
0

More than 5 years have passed since last update.

ほのぼの Rake タスクで S3 のバケットポリシーをちょっと管理する(表示と export と diff と update するだけ)

Last updated at Posted at 2016-11-23

こちらからの転載です。

最近

ギョームで S3 バケットを更新する作業があったので、ほのぼの Rake タスクで汎用的に管理出来る感じにしてみました。

タスク

Rakefile

require 'aws-sdk'
require 'diffy'
require 'json'

POLICY_DIR='policies/'

def s3
  Aws.config[:credentials] = Aws::SharedCredentials.new(profile_name: 'あなたのプロファイル')
  Aws::S3::Client.new(region: 'ap-northeast-1')
end

def get_bucket_policy(bucket)
  begin
    resp = s3.get_bucket_policy({
      bucket: bucket
    })
    JSON.parse(resp.policy.read)
  rescue JSON::ParserError => e
    puts e
  end
end

def open_policy_document(path)
  begin
    File.open(POLICY_DIR + path) do |file|
      JSON.load(file)
    end
  rescue JSON::ParserError => e
    puts e
  end
end

def valid_json?(json)
  begin
    JSON.parse(json)
    return true
  rescue JSON::ParserError => e
    return false
  end
end

namespace :s3 do

  namespace :policy do

    desc "S3 バケット policy を取得する"
    task :export, :bucket do |task, args|
      puts "#{args[:bucket]} の policy を取得します..."
      hash = get_bucket_policy(args[:bucket])
      puts JSON.pretty_generate(hash)
      File.open(POLICY_DIR + args[:bucket], "w") do |f| 
        f.puts(JSON.pretty_generate(hash))
      end
    end

    desc "S3 バケット policy を表示する"
    task :view, :bucket do |task, args|
      puts "#{args[:bucket]} の policy を表示します..."
      hash = get_bucket_policy(args[:bucket])
      puts JSON.pretty_generate(hash)
    end

    targets = []
    Dir.glob(POLICY_DIR + '*').each do |file|
      target = File.basename(file)
      target = "_#{target}" if target == "default"
      targets << target
    end

    targets.each do |target|
      namespace target.to_sym do
        desc "S3 バケット #{target} の policy を変更する"
        task :update do
          resp = s3.put_bucket_policy({
            bucket: "#{target}",
            policy: open_policy_document(target).to_json
          })
          puts resp
        end

        desc "S3 バケット #{target} に適用する policy と既存のポリシーを比較する"
        task :diff do
          hash = get_bucket_policy(target)
          old = JSON.pretty_generate(hash)
          new = JSON.pretty_generate(open_policy_document(target))
          puts Diffy::Diff.new(old, new).to_s(:color)
        end

      end
    end
  end
end

使い方

  • 初期状態の tasks
$ bundle exec rake -T
rake s3:policy:export[bucket]          # S3 バケット policy を取得する
rake s3:policy:view[bucket]            # S3 バケット policy を表示する
  • バケットポリシーを export しましょう
$ mkdir policies
$ bundle exec rake "s3:policy:export[hage.inokara.com]"

以下のように出力されます。

hage.inokara.com の policy を取得します...
{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "AllowPublicRead",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::hage.inokara.com/*"
    }
  ]
}

デフォルトではカレントディレクトリの policies というディレクトリ以下にバケット名と同じ名前のポリシーファイルが作成されています。

bash-3.2$ ls -l policies/
total 8
-rw-r--r--  1 syorou  staff  253 Nov 23 11:58 hage.inokara.com

tasks も確認しましょう。

bash-3.2$ bundle exec rake -T
rake s3:policy:hage.inokara.com:diff    # S3 バケット hage.inokara.com に適用する policy と既存のポリシーを比較する
rake s3:policy:hage.inokara.com:update  # S3 バケット hage.inokara.com の policy を変更する
rake s3:policy:export[bucket]          # S3 バケット policy を取得する
rake s3:policy:view[bucket]            # S3 バケット policy を表示する
  • バケットポリシーを修正しましょう
bash-3.2$ vim policies/hage.inokara.com

ドキュメントを参考に IP アドレス制限をかけてみました。

{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "AllowPublicRead",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::hage.inokara.com/*",
      "Condition": {
         "IpAddress": {"aws:SourceIp": "54.240.143.0/24"},
         "NotIpAddress": {"aws:SourceIp": "54.240.143.188/32"}
      }
    }
  ]
}
  • 差分を確認しましょう
bash-3.2$ bundle exec rake s3:policy:hage.inokara.com:diff
 {
   "Version": "2008-10-17",
   "Statement": [
     {
       "Sid": "AllowPublicRead",
       "Effect": "Allow",
       "Principal": {
         "AWS": "*"
       },
       "Action": "s3:GetObject",
-      "Resource": "arn:aws:s3:::hage.inokara.com/*"
+      "Resource": "arn:aws:s3:::hage.inokara.com/*",
+      "Condition": {
+        "IpAddress": {
+          "aws:SourceIp": "54.240.143.0/24"
+        },
+        "NotIpAddress": {
+          "aws:SourceIp": "54.240.143.188/32"
+        }
+      }
     }
   ]
 }
\ No newline at end of file

ちゃんと既存の設定との差分を表示してくれます。ありがたい。

  • バケットポリシーをツッコミましょう
bash-3.2$ bundle exec rake s3:policy:hage.inokara.com:update
#<struct Aws::S3::Types::EmptyStructure>
  • 適用したポリシーを見てみましょう
bash-3.2$ bundle exec rake s3:policy:view[hage.inokara.com]
hage.inokara.com の policy を表示します...
{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "AllowPublicRead",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::hage.inokara.com/*",
      "Condition": {
        "NotIpAddress": {
          "aws:SourceIp": "54.240.143.188/32"
        },
        "IpAddress": {
          "aws:SourceIp": "54.240.143.0/24"
        }
      }
    }
  ]
}

最後に

バケラッタ

この Rake タスクを書き終わった後に気づきましたが、既に Codenize.tools の Bukelatta というツールがありますので、今後はバケラッタを使っていきたいと思います。

[https://github.com/winebarrel/bukelatta:embed:cite]

Rake って

楽しいですね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0