cloudformation + lambda

Сегодня речь пойдет о массовом добавлении IP адресов в WAF-сервис, который помогает ограничить доступ к Вашим ресурсам, например к AWS CloudFront CDN.
- А в чем собственно проблема?… Открыл AWS консоль, создал условие и добавил IP адреса…
- Ок, а что если их 50, 100 или более?

Проблема

Проблема в том, что казалось бы в AWS, столь продвинутом сервисе, не получится добавить десятки IP-адресов, скажем, разделенных запятой или пробелом. Форма просто не позволяет это сделать.

Решение

Есть несколько вариантов решения этой проблемы:

  • AWS API
  • AWS SDK
  • AWS CLI

В данной статье мы будем рассматривать вариант решения AWS SDK, а именно Ruby aws-sdk.

Помочь нам в этом нелегком деле может вот такой скрипт:

#!/usr/bin/env ruby

require 'aws-sdk'
require 'pp'

region = 'eu-central-1'
credentials = Aws::Credentials.new(
  ENV['AWS_ACCESS_KEY_ID'],
  ENV['AWS_SECRET_ACCESS_KEY']
)
waf_ip_set_name = ARGV[0]

puts "Region: #{region}"
puts "WAF IP Set Name: #{waf_ip_set_name}"

WAF = Aws::WAF::Client.new(
  region: region,
  credentials: credentials
)
change_token = lambda { WAF.get_change_token({})[:change_token] }

resp = WAF.create_ip_set({
  change_token: change_token.call,
  name: waf_ip_set_name,
})

ip_set_id = resp[:ip_set][:ip_set_id]
puts "IP Set id: #{ip_set_id}"

#
# Notes about CIDR format
# (http://docs.aws.amazon.com/waf/latest/developerguide/web-acl-ip-conditions.html)
# AWS WAF supports /8, /16, /24, and /32 IPv4 address ranges
# and /16, /24, /32, /56, /64, and /128 IPv6 address ranges.
#

resp = WAF.update_ip_set({
  change_token: change_token.call,
  ip_set_id: ip_set_id,
  updates: [
    {
      action: "INSERT",
      ip_set_descriptor: {
        type: "IPV4",
        value: "192.0.2.44/32"
      }
    },
    {
      action: "INSERT",
      ip_set_descriptor: {
        type: "IPV6",
        value: "2620:0:2d0:200::/64"
      }
    }
  ]
})

puts "Response:"
p resp

exit 0

Маленькое предостережение, иногда встречаются маски, которые не поддерживаются, в этом случае нужно разбить эти сети на более мелкие и добавить их “руками” в скрипт, а скрипт их добавит в AWS WAF.