inspec 4.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +63 -0
  3. data/inspec.gemspec +36 -0
  4. data/lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/Gemfile +11 -0
  5. data/lib/plugins/inspec-init/templates/plugins/inspec-plugin-template/inspec-plugin-template.gemspec +43 -0
  6. data/lib/plugins/inspec-init/templates/profiles/aws/README.md +192 -0
  7. data/lib/plugins/inspec-init/templates/profiles/aws/attributes.yml +2 -0
  8. data/lib/plugins/inspec-init/templates/profiles/aws/controls/example.rb +39 -0
  9. data/lib/plugins/inspec-init/templates/profiles/aws/inspec.yml +22 -0
  10. data/lib/plugins/inspec-init/templates/profiles/azure/README.md +56 -0
  11. data/lib/plugins/inspec-init/templates/profiles/azure/controls/example.rb +14 -0
  12. data/lib/plugins/inspec-init/templates/profiles/azure/inspec.yml +14 -0
  13. data/lib/plugins/inspec-init/templates/profiles/gcp/README.md +66 -0
  14. data/lib/plugins/inspec-init/templates/profiles/gcp/attributes.yml +2 -0
  15. data/lib/plugins/inspec-init/templates/profiles/gcp/controls/example.rb +27 -0
  16. data/lib/plugins/inspec-init/templates/profiles/gcp/inspec.yml +19 -0
  17. data/lib/resource_support/aws.rb +76 -0
  18. data/lib/resource_support/aws/aws_backend_base.rb +12 -0
  19. data/lib/resource_support/aws/aws_backend_factory_mixin.rb +12 -0
  20. data/lib/resource_support/aws/aws_plural_resource_mixin.rb +24 -0
  21. data/lib/resource_support/aws/aws_resource_mixin.rb +69 -0
  22. data/lib/resource_support/aws/aws_singular_resource_mixin.rb +27 -0
  23. data/lib/resources/aws/aws_billing_report.rb +107 -0
  24. data/lib/resources/aws/aws_billing_reports.rb +74 -0
  25. data/lib/resources/aws/aws_cloudtrail_trail.rb +97 -0
  26. data/lib/resources/aws/aws_cloudtrail_trails.rb +51 -0
  27. data/lib/resources/aws/aws_cloudwatch_alarm.rb +67 -0
  28. data/lib/resources/aws/aws_cloudwatch_log_metric_filter.rb +105 -0
  29. data/lib/resources/aws/aws_config_delivery_channel.rb +74 -0
  30. data/lib/resources/aws/aws_config_recorder.rb +99 -0
  31. data/lib/resources/aws/aws_ebs_volume.rb +127 -0
  32. data/lib/resources/aws/aws_ebs_volumes.rb +69 -0
  33. data/lib/resources/aws/aws_ec2_instance.rb +162 -0
  34. data/lib/resources/aws/aws_ec2_instances.rb +69 -0
  35. data/lib/resources/aws/aws_ecs_cluster.rb +88 -0
  36. data/lib/resources/aws/aws_eks_cluster.rb +105 -0
  37. data/lib/resources/aws/aws_elb.rb +85 -0
  38. data/lib/resources/aws/aws_elbs.rb +84 -0
  39. data/lib/resources/aws/aws_flow_log.rb +106 -0
  40. data/lib/resources/aws/aws_iam_access_key.rb +112 -0
  41. data/lib/resources/aws/aws_iam_access_keys.rb +153 -0
  42. data/lib/resources/aws/aws_iam_group.rb +62 -0
  43. data/lib/resources/aws/aws_iam_groups.rb +56 -0
  44. data/lib/resources/aws/aws_iam_password_policy.rb +121 -0
  45. data/lib/resources/aws/aws_iam_policies.rb +57 -0
  46. data/lib/resources/aws/aws_iam_policy.rb +311 -0
  47. data/lib/resources/aws/aws_iam_role.rb +60 -0
  48. data/lib/resources/aws/aws_iam_root_user.rb +82 -0
  49. data/lib/resources/aws/aws_iam_user.rb +145 -0
  50. data/lib/resources/aws/aws_iam_users.rb +160 -0
  51. data/lib/resources/aws/aws_kms_key.rb +100 -0
  52. data/lib/resources/aws/aws_kms_keys.rb +58 -0
  53. data/lib/resources/aws/aws_rds_instance.rb +74 -0
  54. data/lib/resources/aws/aws_route_table.rb +67 -0
  55. data/lib/resources/aws/aws_route_tables.rb +64 -0
  56. data/lib/resources/aws/aws_s3_bucket.rb +142 -0
  57. data/lib/resources/aws/aws_s3_bucket_object.rb +87 -0
  58. data/lib/resources/aws/aws_s3_buckets.rb +52 -0
  59. data/lib/resources/aws/aws_security_group.rb +314 -0
  60. data/lib/resources/aws/aws_security_groups.rb +71 -0
  61. data/lib/resources/aws/aws_sns_subscription.rb +82 -0
  62. data/lib/resources/aws/aws_sns_topic.rb +57 -0
  63. data/lib/resources/aws/aws_sns_topics.rb +60 -0
  64. data/lib/resources/aws/aws_sqs_queue.rb +66 -0
  65. data/lib/resources/aws/aws_subnet.rb +92 -0
  66. data/lib/resources/aws/aws_subnets.rb +56 -0
  67. data/lib/resources/aws/aws_vpc.rb +77 -0
  68. data/lib/resources/aws/aws_vpcs.rb +55 -0
  69. data/lib/resources/azure/azure_backend.rb +379 -0
  70. data/lib/resources/azure/azure_generic_resource.rb +55 -0
  71. data/lib/resources/azure/azure_resource_group.rb +151 -0
  72. data/lib/resources/azure/azure_virtual_machine.rb +262 -0
  73. data/lib/resources/azure/azure_virtual_machine_data_disk.rb +131 -0
  74. metadata +202 -0
@@ -0,0 +1,74 @@
1
+ require "inspec/utils/filter"
2
+ require "resource_support/aws/aws_plural_resource_mixin"
3
+ require "resource_support/aws/aws_backend_base"
4
+ require "aws-sdk-costandusagereportservice"
5
+
6
+ class AwsBillingReports < Inspec.resource(1)
7
+ name "aws_billing_reports"
8
+ supports platform: "aws"
9
+ desc "Verifies settings for AWS Cost and Billing Reports."
10
+ example <<~EXAMPLE
11
+ describe aws_billing_reports do
12
+ its('report_names') { should include 'inspec1' }
13
+ its('s3_buckets') { should include 'inspec1-s3-bucket' }
14
+ end
15
+
16
+ describe aws_billing_reports.where { report_name =~ /inspec.*/ } do
17
+ its ('report_names') { should include ['inspec1'] }
18
+ its ('time_units') { should include ['DAILY'] }
19
+ its ('s3_buckets') { should include ['inspec1-s3-bucket'] }
20
+ end
21
+ EXAMPLE
22
+
23
+ include AwsPluralResourceMixin
24
+
25
+ filtertable = FilterTable.create
26
+ filtertable.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
27
+ .register_column(:report_names, field: :report_name)
28
+ .register_column(:time_units, field: :time_unit, style: :simple)
29
+ .register_column(:formats, field: :format, style: :simple)
30
+ .register_column(:compressions, field: :compression, style: :simple)
31
+ .register_column(:s3_buckets, field: :s3_bucket, style: :simple)
32
+ .register_column(:s3_prefixes, field: :s3_prefix, style: :simple)
33
+ .register_column(:s3_regions, field: :s3_region, style: :simple)
34
+ filtertable.install_filter_methods_on_resource(self, :table)
35
+
36
+ def validate_params(resource_params)
37
+ unless resource_params.empty?
38
+ raise ArgumentError, "aws_billing_reports does not accept resource parameters."
39
+ end
40
+
41
+ resource_params
42
+ end
43
+
44
+ def to_s
45
+ "AWS Billing Reports"
46
+ end
47
+
48
+ def fetch_from_api
49
+ @table = []
50
+ pagination_opts = {}
51
+ backend = BackendFactory.create(inspec_runner)
52
+ loop do
53
+ api_result = backend.describe_report_definitions(pagination_opts)
54
+ api_result.report_definitions.each do |raw_report|
55
+ report = raw_report.to_h
56
+ %i{time_unit compression}.each { |field| report[field].downcase! }
57
+ @table << report
58
+ end
59
+ pagination_opts = { next_token: api_result.next_token }
60
+ break unless api_result.next_token
61
+ end
62
+ end
63
+
64
+ class Backend
65
+ class AwsClientApi < AwsBackendBase
66
+ AwsBillingReports::BackendFactory.set_default_backend(self)
67
+ self.aws_client_class = Aws::CostandUsageReportService::Client
68
+
69
+ def describe_report_definitions(options = {})
70
+ aws_service_client.describe_report_definitions(options)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,97 @@
1
+ require "resource_support/aws/aws_singular_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-cloudtrail"
4
+
5
+ class AwsCloudTrailTrail < Inspec.resource(1)
6
+ name "aws_cloudtrail_trail"
7
+ desc "Verifies settings for an individual AWS CloudTrail Trail"
8
+ example <<~EXAMPLE
9
+ describe aws_cloudtrail_trail('trail-name') do
10
+ it { should exist }
11
+ end
12
+ EXAMPLE
13
+
14
+ supports platform: "aws"
15
+
16
+ include AwsSingularResourceMixin
17
+ attr_reader :cloud_watch_logs_log_group_arn, :cloud_watch_logs_role_arn, :home_region,
18
+ :kms_key_id, :s3_bucket_name, :trail_arn
19
+
20
+ def to_s
21
+ "CloudTrail #{@trail_name}"
22
+ end
23
+
24
+ def multi_region_trail?
25
+ @is_multi_region_trail
26
+ end
27
+
28
+ def log_file_validation_enabled?
29
+ @log_file_validation_enabled
30
+ end
31
+
32
+ def encrypted?
33
+ !kms_key_id.nil?
34
+ end
35
+
36
+ def delivered_logs_days_ago
37
+ query = { name: @trail_name }
38
+ catch_aws_errors do
39
+ begin
40
+ resp = BackendFactory.create(inspec_runner).get_trail_status(query).to_h
41
+ ((Time.now - resp[:latest_cloud_watch_logs_delivery_time]) / (24 * 60 * 60)).to_i unless resp[:latest_cloud_watch_logs_delivery_time].nil?
42
+ rescue Aws::CloudTrail::Errors::TrailNotFoundException
43
+ nil
44
+ end
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def validate_params(raw_params)
51
+ validated_params = check_resource_param_names(
52
+ raw_params: raw_params,
53
+ allowed_params: [:trail_name],
54
+ allowed_scalar_name: :trail_name,
55
+ allowed_scalar_type: String
56
+ )
57
+
58
+ if validated_params.empty?
59
+ raise ArgumentError, "You must provide the parameter 'trail_name' to aws_cloudtrail_trail."
60
+ end
61
+
62
+ validated_params
63
+ end
64
+
65
+ def fetch_from_api
66
+ backend = BackendFactory.create(inspec_runner)
67
+
68
+ query = { trail_name_list: [@trail_name] }
69
+ resp = backend.describe_trails(query)
70
+
71
+ @trail = resp.trail_list[0].to_h
72
+ @exists = !@trail.empty?
73
+ @s3_bucket_name = @trail[:s3_bucket_name]
74
+ @is_multi_region_trail = @trail[:is_multi_region_trail]
75
+ @trail_arn = @trail[:trail_arn]
76
+ @log_file_validation_enabled = @trail[:log_file_validation_enabled]
77
+ @cloud_watch_logs_role_arn = @trail[:cloud_watch_logs_role_arn]
78
+ @cloud_watch_logs_log_group_arn = @trail[:cloud_watch_logs_log_group_arn]
79
+ @kms_key_id = @trail[:kms_key_id]
80
+ @home_region = @trail[:home_region]
81
+ end
82
+
83
+ class Backend
84
+ class AwsClientApi < AwsBackendBase
85
+ AwsCloudTrailTrail::BackendFactory.set_default_backend(self)
86
+ self.aws_client_class = Aws::CloudTrail::Client
87
+
88
+ def describe_trails(query)
89
+ aws_service_client.describe_trails(query)
90
+ end
91
+
92
+ def get_trail_status(query)
93
+ aws_service_client.get_trail_status(query)
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,51 @@
1
+ require "resource_support/aws/aws_plural_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-cloudtrail"
4
+
5
+ class AwsCloudTrailTrails < Inspec.resource(1)
6
+ name "aws_cloudtrail_trails"
7
+ desc "Verifies settings for AWS CloudTrail Trails in bulk"
8
+ example <<~EXAMPLE
9
+ describe aws_cloudtrail_trails do
10
+ it { should exist }
11
+ end
12
+ EXAMPLE
13
+ supports platform: "aws"
14
+
15
+ include AwsPluralResourceMixin
16
+
17
+ def validate_params(resource_params)
18
+ unless resource_params.empty?
19
+ raise ArgumentError, "aws_cloudtrail_trails does not accept resource parameters."
20
+ end
21
+
22
+ resource_params
23
+ end
24
+
25
+ # Underlying FilterTable implementation.
26
+ filter = FilterTable.create
27
+ filter.register_custom_matcher(:exists?) { |x| !x.entries.empty? }
28
+ filter.register_column(:trail_arns, field: :trail_arn)
29
+ filter.register_column(:names, field: :name)
30
+ filter.install_filter_methods_on_resource(self, :table)
31
+
32
+ def to_s
33
+ "CloudTrail Trails"
34
+ end
35
+
36
+ def fetch_from_api
37
+ backend = BackendFactory.create(inspec_runner)
38
+ @table = backend.describe_trails({}).to_h[:trail_list]
39
+ end
40
+
41
+ class Backend
42
+ class AwsClientApi < AwsBackendBase
43
+ AwsCloudTrailTrails::BackendFactory.set_default_backend(self)
44
+ self.aws_client_class = Aws::CloudTrail::Client
45
+
46
+ def describe_trails(query)
47
+ aws_service_client.describe_trails(query)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,67 @@
1
+ require "resource_support/aws/aws_singular_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-cloudwatch"
4
+
5
+ class AwsCloudwatchAlarm < Inspec.resource(1)
6
+ name "aws_cloudwatch_alarm"
7
+ desc <<~EXAMPLE
8
+ # Look for a specific alarm
9
+ aws_cloudwatch_alarm(
10
+ metric_name: 'my-metric-name',
11
+ metric_namespace: 'my-metric-namespace',
12
+ ) do
13
+ it { should exist }
14
+ end
15
+ EXAMPLE
16
+ supports platform: "aws"
17
+
18
+ include AwsSingularResourceMixin
19
+ attr_reader :alarm_actions, :alarm_name, :metric_name, :metric_namespace
20
+
21
+ private
22
+
23
+ def validate_params(raw_params)
24
+ recognized_params = check_resource_param_names(
25
+ raw_params: raw_params,
26
+ allowed_params: %i{metric_name metric_namespace}
27
+ )
28
+ validated_params = {}
29
+ # Currently you must specify exactly metric_name and metric_namespace
30
+ %i{metric_name metric_namespace}.each do |param|
31
+ raise ArgumentError, "Missing resource param #{param}" unless recognized_params.key?(param)
32
+
33
+ validated_params[param] = recognized_params.delete(param)
34
+ end
35
+
36
+ validated_params
37
+ end
38
+
39
+ def fetch_from_api
40
+ aws_alarms = BackendFactory.create(inspec_runner).describe_alarms_for_metric(
41
+ metric_name: @metric_name,
42
+ namespace: @metric_namespace
43
+ )
44
+ if aws_alarms.metric_alarms.empty?
45
+ @exists = false
46
+ elsif aws_alarms.metric_alarms.count > 1
47
+ alarms = aws_alarms.metric_alarms.map(&:alarm_name)
48
+ raise "More than one Cloudwatch Alarm was matched. Try using " \
49
+ "more specific resource parameters. Alarms matched: #{alarms.join(", ")}"
50
+ else
51
+ @alarm_actions = aws_alarms.metric_alarms.first.alarm_actions
52
+ @alarm_name = aws_alarms.metric_alarms.first.alarm_name
53
+ @exists = true
54
+ end
55
+ end
56
+
57
+ class Backend
58
+ class AwsClientApi < AwsBackendBase
59
+ AwsCloudwatchAlarm::BackendFactory.set_default_backend(self)
60
+ self.aws_client_class = Aws::CloudWatch::Client
61
+
62
+ def describe_alarms_for_metric(query)
63
+ aws_service_client.describe_alarms_for_metric(query)
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,105 @@
1
+ require "resource_support/aws/aws_singular_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-cloudwatchlogs"
4
+
5
+ class AwsCloudwatchLogMetricFilter < Inspec.resource(1)
6
+ name "aws_cloudwatch_log_metric_filter"
7
+ desc "Verifies individual Cloudwatch Log Metric Filters"
8
+ example <<~EXAMPLE
9
+ # Look for a LMF by its filter name and log group name. This combination
10
+ # will always either find at most one LMF - no duplicates.
11
+ describe aws_cloudwatch_log_metric_filter(
12
+ filter_name: 'my-filter',
13
+ log_group_name: 'my-log-group'
14
+ ) do
15
+ it { should exist }
16
+ end
17
+
18
+ # Search for an LMF by pattern and log group.
19
+ # This could result in an error if the results are not unique.
20
+ describe aws_cloudwatch_log_metric_filter(
21
+ log_group_name: 'my-log-group',
22
+ pattern: 'my-filter'
23
+ ) do
24
+ it { should exist }
25
+ end
26
+ EXAMPLE
27
+ supports platform: "aws"
28
+ include AwsSingularResourceMixin
29
+ attr_reader :filter_name, :log_group_name, :metric_name, :metric_namespace, :pattern
30
+
31
+ private
32
+
33
+ def validate_params(raw_params)
34
+ validated_params = check_resource_param_names(
35
+ raw_params: raw_params,
36
+ allowed_params: %i{filter_name log_group_name pattern}
37
+ )
38
+ if validated_params.empty?
39
+ raise ArgumentError, "You must provide either filter_name, log_group, or pattern to aws_cloudwatch_log_metric_filter."
40
+ end
41
+
42
+ validated_params
43
+ end
44
+
45
+ def fetch_from_api
46
+ # get a backend
47
+ backend = BackendFactory.create(inspec_runner)
48
+
49
+ # Perform query with remote filtering
50
+ aws_search_criteria = {}
51
+ aws_search_criteria[:filter_name] = filter_name if filter_name
52
+ aws_search_criteria[:log_group_name] = log_group_name if log_group_name
53
+ begin
54
+ aws_results = backend.describe_metric_filters(aws_search_criteria)
55
+ rescue Aws::CloudWatchLogs::Errors::ResourceNotFoundException
56
+ @exists = false
57
+ return
58
+ end
59
+
60
+ # Then perform local filtering
61
+ if pattern
62
+ aws_results.select! { |lmf| lmf.filter_pattern == pattern }
63
+ end
64
+
65
+ # Check result count. We're a singular resource and can tolerate
66
+ # 0 or 1 results, not multiple.
67
+ if aws_results.count > 1
68
+ raise "More than one result was returned, but aws_cloudwatch_log_metric_filter "\
69
+ "can only handle a single AWS resource. Consider passing more resource "\
70
+ "parameters to narrow down the search."
71
+ elsif aws_results.empty?
72
+ @exists = false
73
+ else
74
+ @exists = true
75
+ # Unpack the funny-shaped object we got back from AWS into our instance vars
76
+ lmf = aws_results.first
77
+ @filter_name = lmf.filter_name
78
+ @log_group_name = lmf.log_group_name
79
+ @pattern = lmf.filter_pattern # Note inconsistent name
80
+ # AWS SDK returns an array of metric transformations
81
+ # but only allows one (mandatory) entry, let's flatten that
82
+ @metric_name = lmf.metric_transformations.first.metric_name
83
+ @metric_namespace = lmf.metric_transformations.first.metric_namespace
84
+ end
85
+ end
86
+
87
+ class Backend
88
+ # Uses the cloudwatch API to really talk to AWS
89
+ class AwsClientApi < AwsBackendBase
90
+ BackendFactory.set_default_backend(self)
91
+ self.aws_client_class = Aws::CloudWatchLogs::Client
92
+
93
+ def describe_metric_filters(criteria)
94
+ query = {}
95
+ query[:filter_name_prefix] = criteria[:filter_name] if criteria[:filter_name]
96
+ query[:log_group_name] = criteria[:log_group_name] if criteria[:log_group_name]
97
+ # 'pattern' is not available as a remote filter,
98
+ # we filter it after the fact locally
99
+ # TODO: handle pagination? Max 50/page. Maybe you want a plural resource?
100
+ aws_response = aws_service_client.describe_metric_filters(query)
101
+ aws_response.metric_filters
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,74 @@
1
+ require "resource_support/aws/aws_singular_resource_mixin"
2
+ require "resource_support/aws/aws_backend_base"
3
+ require "aws-sdk-configservice"
4
+
5
+ class AwsConfigDeliveryChannel < Inspec.resource(1)
6
+ name "aws_config_delivery_channel"
7
+ desc "Verifies settings for AWS Config Delivery Channel"
8
+ example <<~EXAMPLE
9
+ describe aws_config_delivery_channel do
10
+ it { should exist }
11
+ its('s3_bucket_name') { should eq 'my_bucket' }
12
+ its('sns_topic_arn') { should eq arn:aws:sns:us-east-1:721741954427:sns_topic' }
13
+ end
14
+ EXAMPLE
15
+ supports platform: "aws"
16
+
17
+ include AwsSingularResourceMixin
18
+ attr_reader :channel_name, :s3_bucket_name, :s3_key_prefix, :sns_topic_arn,
19
+ :delivery_frequency_in_hours
20
+
21
+ def to_s
22
+ "Config_Delivery_Channel: #{@channel_name}"
23
+ end
24
+
25
+ private
26
+
27
+ def validate_params(raw_params)
28
+ validated_params = check_resource_param_names(
29
+ raw_params: raw_params,
30
+ allowed_params: [:channel_name],
31
+ allowed_scalar_name: :channel_name,
32
+ allowed_scalar_type: String
33
+ )
34
+
35
+ validated_params
36
+ end
37
+
38
+ def fetch_from_api
39
+ backend = BackendFactory.create(inspec_runner)
40
+ query = @channel_name ? { delivery_channel_names: [@channel_name] } : {}
41
+ response = backend.describe_delivery_channels(query)
42
+
43
+ @exists = !response.delivery_channels.empty?
44
+ return unless exists?
45
+
46
+ channel = response.delivery_channels.first.to_h
47
+ @channel_name = channel[:name]
48
+ @s3_bucket_name = channel[:s3_bucket_name]
49
+ @s3_key_prefix = channel[:s3_key_prefix]
50
+ @sns_topic_arn = channel[:sns_topic_arn]
51
+ @delivery_frequency_in_hours = channel.dig(:config_snapshot_delivery_properties, :delivery_frequency)
52
+ frequencies = {
53
+ "One_Hour" => 1,
54
+ "TwentyFour_Hours" => 24,
55
+ "Three_Hours" => 3,
56
+ "Six_Hours" => 6,
57
+ "Twelve_Hours" => 12,
58
+ }
59
+ @delivery_frequency_in_hours = frequencies[@delivery_frequency_in_hours]
60
+ rescue Aws::ConfigService::Errors::NoSuchDeliveryChannelException
61
+ @exists = false
62
+ end
63
+
64
+ class Backend
65
+ class AwsClientApi < AwsBackendBase
66
+ BackendFactory.set_default_backend(self)
67
+ self.aws_client_class = Aws::ConfigService::Client
68
+
69
+ def describe_delivery_channels(query = {})
70
+ aws_service_client.describe_delivery_channels(query)
71
+ end
72
+ end
73
+ end
74
+ end