From 463288219ab4e49a80ef7898a53cd5b2c10db6d0 Mon Sep 17 00:00:00 2001 From: alpineriveredge Date: Sat, 25 Jan 2025 16:12:37 +0900 Subject: [PATCH] Add wafv2_ip_set resource --- .rubocop.yml | 1 + doc/_resource_types/wafv2_ip_set.md | 17 +++++++++ doc/resource_types.md | 25 +++++++++++++ lib/awspec/command/generate.rb | 12 +++++++ lib/awspec/generator.rb | 1 + lib/awspec/generator/doc/type/wafv2_ip_set.rb | 19 ++++++++++ lib/awspec/generator/spec/wafv2_ip_set.rb | 35 +++++++++++++++++++ lib/awspec/helper/finder.rb | 5 ++- lib/awspec/helper/finder/wafv2.rb | 27 ++++++++++++++ lib/awspec/helper/type.rb | 2 +- lib/awspec/shared_context.rb | 6 ++++ lib/awspec/stub/wafv2_ip_set.rb | 32 +++++++++++++++++ lib/awspec/type/wafv2_ip_set.rb | 23 ++++++++++++ spec/generator/spec/wafv2_ip_set_spec.rb | 25 +++++++++++++ spec/type/wafv2_ip_set_spec.rb | 18 ++++++++++ 15 files changed, 246 insertions(+), 2 deletions(-) create mode 100644 doc/_resource_types/wafv2_ip_set.md create mode 100644 lib/awspec/generator/doc/type/wafv2_ip_set.rb create mode 100644 lib/awspec/generator/spec/wafv2_ip_set.rb create mode 100644 lib/awspec/helper/finder/wafv2.rb create mode 100644 lib/awspec/stub/wafv2_ip_set.rb create mode 100644 lib/awspec/type/wafv2_ip_set.rb create mode 100644 spec/generator/spec/wafv2_ip_set_spec.rb create mode 100644 spec/type/wafv2_ip_set_spec.rb diff --git a/.rubocop.yml b/.rubocop.yml index e45dabca..fc4e1f1d 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -20,6 +20,7 @@ Lint/DuplicateMethods: - 'lib/awspec/type/ecs_service.rb' - 'lib/awspec/type/eks_nodegroup.rb' - 'lib/awspec/type/resource_base.rb' + - 'lib/awspec/type/wafv2_ip_set.rb' Lint/ErbNewArguments: Enabled: false diff --git a/doc/_resource_types/wafv2_ip_set.md b/doc/_resource_types/wafv2_ip_set.md new file mode 100644 index 00000000..734936df --- /dev/null +++ b/doc/_resource_types/wafv2_ip_set.md @@ -0,0 +1,17 @@ +### exist + +You can set `scope` to CLOUDFRONT or REGIONAL ( default: `REGIONAL` ). + +```ruby +describe wafv2_ip_set('my-ip-set'), scope: 'REGIONAL' do + it { should exist } +end +``` + +### have_ip_address + +```ruby +describe wafv2_ip_set('my-ip-set'), scope: 'REGIONAL' do + it { should have_ip_address('10.0.0.0/32') } +end +``` diff --git a/doc/resource_types.md b/doc/resource_types.md index 10a744d6..403c8dcd 100644 --- a/doc/resource_types.md +++ b/doc/resource_types.md @@ -89,6 +89,7 @@ | [vpn_gateway](#vpn_gateway) | [waf_web_acl](#waf_web_acl) | [wafregional_web_acl](#wafregional_web_acl) +| [wafv2_ip_set](#wafv2_ip_set) | [account](#account) ## acm @@ -4300,6 +4301,30 @@ end ### its(:default_action), its(:web_acl_id), its(:name), its(:metric_name), its(:web_acl_arn) +## wafv2_ip_set + +Wafv2IpSet resource type. + +### exist + +You can set `scope` to CLOUDFRONT or REGIONAL ( default: `REGIONAL` ). + +```ruby +describe wafv2_ip_set('my-ip-set'), scope: 'REGIONAL' do + it { should exist } +end +``` + + +### have_ip_address + +```ruby +describe wafv2_ip_set('my-ip-set'), scope: 'REGIONAL' do + it { should have_ip_address('10.0.0.0/32') } +end +``` + +### its(:name), its(:id), its(:arn), its(:description), its(:ip_address_version), its(:addresses) # Account and Attributes ## account diff --git a/lib/awspec/command/generate.rb b/lib/awspec/command/generate.rb index 94228d7b..96f1057e 100644 --- a/lib/awspec/command/generate.rb +++ b/lib/awspec/command/generate.rb @@ -62,6 +62,18 @@ def s3_bucket(bucket_name = nil) end end + types = %w[ + wafv2_ip_set + ] + + types.each do |type| + desc "#{type} [scope]", "Generate #{type} spec from scope: (CLOUDFRONT or REGIONAL)." + define_method type do |_scope| + Awsecrets.load(profile: options[:profile], region: options[:region], secrets_path: options[:secrets_path]) + eval "puts Awspec::Generator::Spec::#{type.camelize}.new.generate_by_scope(_scope)" + end + end + types_for_generate_all = %w[ cloudwatch_alarm cloudwatch_event directconnect ebs efs elasticsearch iam_group iam_policy iam_role iam_user kms lambda diff --git a/lib/awspec/generator.rb b/lib/awspec/generator.rb index b8e0327e..c8e81961 100644 --- a/lib/awspec/generator.rb +++ b/lib/awspec/generator.rb @@ -45,6 +45,7 @@ require 'awspec/generator/spec/rds_global_cluster' require 'awspec/generator/spec/managed_prefix_list' require 'awspec/generator/spec/codepipeline' +require 'awspec/generator/spec/wafv2_ip_set' # Doc require 'awspec/generator/doc/type' diff --git a/lib/awspec/generator/doc/type/wafv2_ip_set.rb b/lib/awspec/generator/doc/type/wafv2_ip_set.rb new file mode 100644 index 00000000..15059c9d --- /dev/null +++ b/lib/awspec/generator/doc/type/wafv2_ip_set.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Awspec::Generator + module Doc + module Type + class Wafv2IpSet < Base + def initialize + super + @type_name = 'Wafv2IpSet' + @type = Awspec::Type::Wafv2IpSet.new('my-ip-set') + @ret = @type.resource_via_client + @matchers = [] + @ignore_matchers = [] + @describes = [] + end + end + end + end +end diff --git a/lib/awspec/generator/spec/wafv2_ip_set.rb b/lib/awspec/generator/spec/wafv2_ip_set.rb new file mode 100644 index 00000000..09a5ae0e --- /dev/null +++ b/lib/awspec/generator/spec/wafv2_ip_set.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Awspec::Generator + module Spec + class Wafv2IpSet + include Awspec::Helper::Finder + def generate_by_scope(scope) + ip_sets = select_all_ip_sets(scope) + raise 'Not Found WAFV2 IP sets' if ip_sets.empty? + + specs = ip_sets.map do |i| + ip_set = get_ip_set(scope, i.name, i.id) + ERB.new(wafv2_ip_set_spec_template, nil, '-').result(binding).gsub(/^\n/, '') + end + specs.join("\n") + end + + def wafv2_ip_set_spec_template + <<-'EOF' +describe wafv2_ip_set('<%= ip_set.name %>'), scope: '<%= scope %>' do + it { should exist } + its(:name) { should eq '<%= ip_set.name %>' } + its(:id) { should eq '<%= ip_set.id %>' } + its(:arn) { should eq '<%= ip_set.arn %>' } + its(:description) { should eq '<%= ip_set.description %>' } + its(:ip_address_version) { should eq '<%= ip_set.ip_address_version %>' } +<% ip_set.addresses.each do |address| %> + it { should have_ip_address('<%= address %>') } +<% end %> +end +EOF + end + end + end +end diff --git a/lib/awspec/helper/finder.rb b/lib/awspec/helper/finder.rb index 84300555..9437c663 100644 --- a/lib/awspec/helper/finder.rb +++ b/lib/awspec/helper/finder.rb @@ -56,6 +56,7 @@ require 'awspec/helper/finder/cognito_identity_pool' require 'awspec/helper/finder/transfer' require 'awspec/helper/finder/codepipeline' +require 'awspec/helper/finder/wafv2' require 'awspec/helper/finder/account_attributes' @@ -119,6 +120,7 @@ module Finder include Awspec::Helper::Finder::CognitoIdentityPool include Awspec::Helper::Finder::Transfer include Awspec::Helper::Finder::Codepipeline + include Awspec::Helper::Finder::Wafv2 CLIENTS = { ec2_client: Aws::EC2::Client, @@ -168,7 +170,8 @@ module Finder cognito_identity_client: Aws::CognitoIdentity::Client, cognito_identity_provider_client: Aws::CognitoIdentityProvider::Client, transfer_client: Aws::Transfer::Client, - codepipeline_client: Aws::CodePipeline::Client + codepipeline_client: Aws::CodePipeline::Client, + wafv2_client: Aws::WAFV2::Client } CLIENT_OPTIONS = { diff --git a/lib/awspec/helper/finder/wafv2.rb b/lib/awspec/helper/finder/wafv2.rb new file mode 100644 index 00000000..a526f4a4 --- /dev/null +++ b/lib/awspec/helper/finder/wafv2.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Awspec::Helper + module Finder + module Wafv2 + def find_ip_set(scope, name) + ip_sets = select_all_ip_sets(scope) + ip_set = ip_sets.find do |i| + i.name == name + end + return false unless ip_set + + get_ip_set(scope, name, ip_set.id) + end + + def select_all_ip_sets(scope) + res = wafv2_client.list_ip_sets({ scope: scope }) + res.ip_sets + end + + def get_ip_set(scope, name, id) + res = wafv2_client.get_ip_set({ name: name, scope: scope, id: id }) + res.ip_set + end + end + end +end diff --git a/lib/awspec/helper/type.rb b/lib/awspec/helper/type.rb index 30dc9de0..dfc2ab69 100644 --- a/lib/awspec/helper/type.rb +++ b/lib/awspec/helper/type.rb @@ -24,7 +24,7 @@ module Type internet_gateway acm cloudwatch_logs dynamodb_table eip sqs ssm_parameter cloudformation_stack codebuild sns_topic redshift redshift_cluster_parameter_group codedeploy codedeploy_deployment_group secretsmanager msk transit_gateway cognito_identity_pool cognito_user_pool vpc_endpoints - transfer_server managed_prefix_list codepipeline + transfer_server managed_prefix_list codepipeline wafv2_ip_set ] ACCOUNT_ATTRIBUTES = %w[ diff --git a/lib/awspec/shared_context.rb b/lib/awspec/shared_context.rb index 55cf049d..7131f04e 100644 --- a/lib/awspec/shared_context.rb +++ b/lib/awspec/shared_context.rb @@ -38,3 +38,9 @@ example.metadata[:described_class].application_name = example.metadata[:application_name] end end + +shared_context 'scope', :scope do + before do |example| + example.metadata[:described_class].scope = example.metadata[:scope] + end +end diff --git a/lib/awspec/stub/wafv2_ip_set.rb b/lib/awspec/stub/wafv2_ip_set.rb new file mode 100644 index 00000000..9bb4a169 --- /dev/null +++ b/lib/awspec/stub/wafv2_ip_set.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +Aws.config[:wafv2] = { + stub_responses: { + get_ip_set: { + ip_set: { + name: 'my-ip-set', + id: '01234567-89ab-cdef-0123-456789abcdef', + arn: 'arn:aws:wafv2:ap-northeast-1:123456789012:regional/ipset/my-ip-set/01234567-89ab-cdef-0123-456789abcdef', + description: 'dev ips', + ip_address_version: 'IPV4', + addresses: [ + '10.0.0.0/32', + '10.0.0.1/32' + ] + }, + lock_token: '01234567-89ab-cdef-0123456789abcdef0' + }, + list_ip_sets: { + next_marker: 'my-ip-set', + ip_sets: [ + { + name: 'my-ip-set', + id: '01234567-89ab-cdef-0123-456789abcdef', + description: 'dev ips', + lock_token: '01234567-89ab-cdef-0123456789abcdef0', + arn: 'arn:aws:wafv2:ap-northeast-1:123456789012:regional/ipset/my-ip-set/01234567-89ab-cdef-0123-456789abcdef' + } + ] + } + } +} diff --git a/lib/awspec/type/wafv2_ip_set.rb b/lib/awspec/type/wafv2_ip_set.rb new file mode 100644 index 00000000..cdfc6b45 --- /dev/null +++ b/lib/awspec/type/wafv2_ip_set.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module Awspec::Type + class Wafv2IpSet < ResourceBase + attr_accessor :scope + + def resource_via_client + @resource_via_client ||= find_ip_set(scope, @display_name) + end + + def id + @id ||= resource_via_client.id if resource_via_client + end + + def scope + @scope || 'REGIONAL' + end + + def has_ip_address?(ip_address) + resource_via_client.addresses.include?(ip_address) + end + end +end diff --git a/spec/generator/spec/wafv2_ip_set_spec.rb b/spec/generator/spec/wafv2_ip_set_spec.rb new file mode 100644 index 00000000..6a1563c0 --- /dev/null +++ b/spec/generator/spec/wafv2_ip_set_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe 'Awspec::Generator::Spec::Wafv2IpSet' do + before do + Awspec::Stub.load 'wafv2_ip_set' + end + let(:wafv2_ip_set) { Awspec::Generator::Spec::Wafv2IpSet.new } + it 'generate_by_scope generate spec' do + spec = <<-'EOF' +describe wafv2_ip_set('my-ip-set'), scope: 'REGIONAL' do + it { should exist } + its(:name) { should eq 'my-ip-set' } + its(:id) { should eq '01234567-89ab-cdef-0123-456789abcdef' } + its(:arn) { should eq 'arn:aws:wafv2:ap-northeast-1:123456789012:regional/ipset/my-ip-set/01234567-89ab-cdef-0123-456789abcdef' } + its(:description) { should eq 'dev ips' } + its(:ip_address_version) { should eq 'IPV4' } + it { should have_ip_address('10.0.0.0/32') } + it { should have_ip_address('10.0.0.1/32') } +end +EOF + expect(wafv2_ip_set.generate_by_scope('REGIONAL').to_s.gsub(/\n/, "\n")).to eq spec + end +end diff --git a/spec/type/wafv2_ip_set_spec.rb b/spec/type/wafv2_ip_set_spec.rb new file mode 100644 index 00000000..e5eff435 --- /dev/null +++ b/spec/type/wafv2_ip_set_spec.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'spec_helper' +Awspec::Stub.load 'wafv2_ip_set' + +describe wafv2_ip_set('my-ip-set'), scope: 'REGIONAL' do + it { should exist } + its(:name) { should eq 'my-ip-set' } + its(:id) { should eq '01234567-89ab-cdef-0123-456789abcdef' } + its(:arn) do + should eq 'arn:aws:wafv2:ap-northeast-1:123456789012:regional/ipset/'\ + 'my-ip-set/01234567-89ab-cdef-0123-456789abcdef' + end + its(:description) { should eq 'dev ips' } + its(:ip_address_version) { should eq 'IPV4' } + it { should have_ip_address('10.0.0.0/32') } + it { should have_ip_address('10.0.0.1/32') } +end