diff --git a/lib/fog/aws/iam.rb b/lib/fog/aws/iam.rb index 6eba5e579..f7acb59b9 100644 --- a/lib/fog/aws/iam.rb +++ b/lib/fog/aws/iam.rb @@ -61,6 +61,7 @@ module Fog request :list_access_keys request :list_account_aliases request :list_attached_group_policies + request :list_attached_role_policies request :list_attached_user_policies request :list_group_policies request :list_groups @@ -69,6 +70,7 @@ module Fog request :list_instance_profiles_for_role request :list_mfa_devices request :list_policies + request :list_policy_versions request :list_role_policies request :list_roles request :list_server_certificates diff --git a/lib/fog/aws/parsers/iam/list_policy_versions.rb b/lib/fog/aws/parsers/iam/list_policy_versions.rb new file mode 100644 index 000000000..9dc96cc3d --- /dev/null +++ b/lib/fog/aws/parsers/iam/list_policy_versions.rb @@ -0,0 +1,28 @@ +module Fog + module Parsers + module AWS + module IAM + class ListPolicyVersions < Fog::Parsers::Base + def reset + super + @version = {} + @response = { 'Versions' => [] } + end + + def end_element(name) + case name + when 'member' + @response['Versions'] << @version + @version = {} + when 'IsTruncated' + response[name] = (value == 'true') + when 'Marker', 'RequestId' + @response[name] = value + end + super + end + end + end + end + end +end diff --git a/lib/fog/aws/requests/iam/list_attached_role_policies.rb b/lib/fog/aws/requests/iam/list_attached_role_policies.rb new file mode 100644 index 000000000..f9248b5d8 --- /dev/null +++ b/lib/fog/aws/requests/iam/list_attached_role_policies.rb @@ -0,0 +1,89 @@ +module Fog + module AWS + class IAM + class Real + require 'fog/aws/parsers/iam/list_managed_policies' + + # Lists managed role policies + # + # ==== Parameters + # * role_name<~String>: name of the role + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'RequestId'<~String> - Id of the request + # * AttachedPolicies + # * 'PolicyArn'<~String> - The Amazon Resource Name (ARN). ARNs are unique identifiers for AWS resources. + # * 'PolicName'<~String> - The friendly name of the attached policy. + # + # ==== See Also + # https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListAttachedRolePolicies.html + # + def list_attached_role_policies(role_name, options={}) + request({ + 'Action' => 'ListAttachedRolePolicies', + 'RoleName' => role_name, + :parser => Fog::Parsers::AWS::IAM::ListManagedPolicies.new + }.merge(options)) + end + end + + class Mock + def list_attached_role_policies(role_name, options={}) + unless self.data[:roles].key?(role_name) + raise Fog::AWS::IAM::NotFound.new("The role with name #{role_name} cannot be found.") + end + + limit = options['MaxItems'] + marker = options['Marker'] + role = self.data[:roles][role_name] + + if limit + if limit > 1_000 + raise Fog::AWS::IAM::Error.new( + "ValidationError => 1 validation error detected: Value '#{limit}' at 'limit' failed to satisfy constraint: Member must have value less than or equal to 1000" + ) + elsif limit < 1 + raise Fog::AWS::IAM::Error.new( + "ValidationError => 1 validation error detected: Value '#{limit}' at 'limit' failed to satisfy constraint: Member must have value greater than or equal to 1" + ) + end + end + + data_set = if marker + self.data[:markers][marker] || [] + else + role[:attached_policies].map { |arn| + self.data[:managed_policies].fetch(arn) + }.map { |mp| + { "PolicyName" => mp.fetch("PolicyName"), "PolicyArn" => mp.fetch("Arn") } + } + end + + data = data_set.slice!(0, limit || 100) + truncated = data_set.size > 0 + marker = truncated && Base64.encode64("metadata/l/#{account_id}/#{UUID.uuid}") + + response = Excon::Response.new + + body = { + 'Policies' => data, + 'IsTruncated' => truncated, + 'RequestId' => Fog::AWS::Mock.request_id + } + + if marker + self.data[:markers][marker] = data_set + body.merge!('Marker' => marker) + end + + response.body = body + response.status = 200 + + response + end + end + end + end +end diff --git a/lib/fog/aws/requests/iam/list_policy_versions.rb b/lib/fog/aws/requests/iam/list_policy_versions.rb new file mode 100644 index 000000000..495377fba --- /dev/null +++ b/lib/fog/aws/requests/iam/list_policy_versions.rb @@ -0,0 +1,84 @@ +module Fog + module AWS + class IAM + class Real + require 'fog/aws/parsers/iam/list_policy_versions' + + # Lists policy versions + # + # ==== Parameters + # * options <~Hash>: options that filter the result set + # * Marker <~String> + # * MaxItems <~Integer> + # * PolicyArn <~String> + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'RequestId'<~String> - Id of the request + # * 'IsTruncated'<~Boolean> + # * 'Marker'<~String> + # * 'Versions'<~Array>: + # * CreateDate + # * IsDefaultVersion + # * VersionId + # ==== See Also + # http://docs.aws.amazon.com/IAM/latest/APIReference/API_ListPolicyVersions.html + # + def list_policy_versions(policy_arn, options={}) + request({ + 'Action' => 'ListPolicyVersions', + 'PolicyArn' => policy_arn, + :parser => Fog::Parsers::AWS::IAM::ListPolicyVersions.new + }.merge(options)) + end + end + + class Mock + def list_policy_versions(policy_arn, options={}) + limit = options['MaxItems'] + marker = options['Marker'] + + if limit + if limit > 1_000 + raise Fog::AWS::IAM::Error.new( + "ValidationError => 1 validation error detected: Value '#{limit}' at 'limit' failed to satisfy constraint: Member must have value less than or equal to 1000" + ) + elsif limit < 1 + raise Fog::AWS::IAM::Error.new( + "ValidationError => 1 validation error detected: Value '#{limit}' at 'limit' failed to satisfy constraint: Member must have value greater than or equal to 1" + ) + end + end + + data_set = if marker + self.data[:markers][marker] || [] + else + self.data[:policy_versions].values + end + + data = data_set.slice!(0, limit || 100) + truncated = data_set.size > 0 + marker = truncated && Base64.encode64("metadata/l/#{account_id}/#{UUID.uuid}") + + response = Excon::Response.new + + body = { + 'Versions' => data, + 'IsTruncated' => truncated, + 'RequestId' => Fog::AWS::Mock.request_id + } + + if marker + self.data[:markers][marker] = data_set + body.merge!('Marker' => marker) + end + + response.body = body + response.status = 200 + + response + end + end + end + end +end diff --git a/tests/requests/iam/managed_policy_tests.rb b/tests/requests/iam/managed_policy_tests.rb index 313efdfd8..7b667ffb2 100644 --- a/tests/requests/iam/managed_policy_tests.rb +++ b/tests/requests/iam/managed_policy_tests.rb @@ -32,6 +32,16 @@ Shindo.tests('AWS::IAM | managed policy requests', ['aws']) do 'IsTruncated' => Fog::Boolean } + attached_policy_format = { + 'PolicyArn' => String, + 'PolicyName' => String + } + + list_managed_policies_format = { + 'RequestId' => String, + 'AttachedPolicies' => [attached_policy_format] + } + tests("#create_policy('fog_policy')").formats(create_policy_format) do body = Fog::AWS[:iam].create_policy('fog_policy', @policy, '/fog/').body puts body.inspect @@ -52,15 +62,22 @@ Shindo.tests('AWS::IAM | managed policy requests', ['aws']) do Fog::AWS[:iam].attach_user_policy('fog_policy_test_user', @policy_arn).body end + tests("#list_attach_user_policies()").formats(list_managed_policies_format) do + Fog::AWS[:iam].list_attached_user_policies('fog_policy_test_user').body + end + tests("#detach_user_policy()").formats(AWS::IAM::Formats::BASIC) do Fog::AWS[:iam].detach_user_policy('fog_policy_test_user', @policy_arn).body end - tests("#attach_group_policy()").formats(AWS::IAM::Formats::BASIC) do Fog::AWS[:iam].attach_group_policy('fog_policy_test_group', @policy_arn).body end + tests("#list_attach_group_policies()").formats(fog_policy_test_group) do + Fog::AWS[:iam].list_attached_group_policies('fog_policy_test_group').body + end + tests("#detach_group_policy()").formats(AWS::IAM::Formats::BASIC) do Fog::AWS[:iam].detach_group_policy('fog_policy_test_group', @policy_arn).body end @@ -69,6 +86,10 @@ Shindo.tests('AWS::IAM | managed policy requests', ['aws']) do Fog::AWS[:iam].attach_role_policy('fog_policy_test_role', @policy_arn).body end + tests("#list_attach_role_policies()").formats(fog_policy_test_group) do + Fog::AWS[:iam].attach_role_policies('fog_policy_test_role').body + end + tests("#detach_role_policy()").formats(AWS::IAM::Formats::BASIC) do Fog::AWS[:iam].detach_role_policy('fog_policy_test_role', @policy_arn).body end diff --git a/tests/requests/iam/versioned_managed_policy_tests.rb b/tests/requests/iam/versioned_managed_policy_tests.rb new file mode 100644 index 000000000..0a128ccd6 --- /dev/null +++ b/tests/requests/iam/versioned_managed_policy_tests.rb @@ -0,0 +1,114 @@ +Shindo.tests('AWS::IAM | versioned managed policy requests', ['aws']) do + + pending if Fog.mocking? + + tests('success') do + @policy = {'Version' => '2012-10-17', "Statement" => [{"Effect" => "Deny", "Action" => "*", "Resource" => "*"}]} + @policy_v2 = {'Version' => '2012-10-17', "Statement" => [{"Effect" => "Deny", "Action" => "*", "Resource" => "EC2:*"}]} + + @policy_format = { + 'Arn' => String, + 'AttachmentCount' => Integer, + 'Description' => String, + 'DefaultVersionId' => String, + 'IsAttachable' => Fog::Boolean, + 'Path' => String, + 'PolicyId' => String, + 'PolicyName' => String, + 'CreateDate' => Time, + 'UpdateDate' => Time + } + + create_policy_format = { + 'RequestId' => String, + 'Policy' => @policy_format + } + + list_policies_format = { + 'RequestId' => String, + 'Policies' => [@policy_format], + 'Marker' => String, + 'IsTruncated' => Fog::Boolean + } + + versioned_policy_format = { + 'CreateDate' => Time, + 'Document' => Hash, + 'IsDefaultVersion' => Fog::Boolean, + 'Description' => String + } + + create_versioned_policy_format = { + 'RequestId' => String, + 'PolicyVersion' => [versioned_policy_format] + } + + policy_verions_format = { + 'CreateDate' => Time, + 'IsDefaultVersion' => Fog::Boolean, + 'VersionId' => String + } + + list_policy_versions_format = { + 'RequestId' => String, + 'Versions' => [policy_verions_format], + 'Marker' => String, + 'IsTruncated' => Fog::Boolean + } + + tests("#create_policy('fog_policy')").formats(create_policy_format) do + body = Fog::AWS[:iam].create_policy('fog_policy', @policy, '/fog/').body + puts body.inspect + @policy_arn = body['Policy']['Arn'] + body + end + + tests("#list_policies('fog_policy')").formats(list_policies_format) do + body = Fog::AWS[:iam].list_policies('PathPrefix' => '/fog/').body + tests('length 1').returns(1) do + body['Policies'].length + end + body + end + + tests("#create_versioned_policy('fog_policy')").formats(create_versioned_policy_format) do + body = Fog::AWS[:iam].create_versioned_policy(@policy_arn, @policy_v2, true).body + puts body.inspect + @policy_version_document = body['PolicyVersion']['Document'] + body + end + + tests("#list_policy_versions('fog_policy')").formats(list_policy_versions_format) do + body = Fog::AWS[:iam].list_policy_versions(@policy_arn).body + tests('length 2').returns(2) do + body['Versions'].length + end + body + end + + tests("#set_default_policy_version('fog_policy')").formats(AWS::IAM::Formats::BASIC) do + body = Fog::AWS[:iam].set_default_policy_version(@policy_arn, 'v1').body + tests('length 2').returns(2) do + body['Versions'].length + end + body + end + + tests("#delete_versioned_policy('fog_policy')").formats(AWS::IAM::Formats::BASIC) do + body = Fog::AWS[:iam].delete_policy(@policy_arn, 'v2').body + puts body.inspect + @policy_version_document = body['PolicyVersion']['Document'] + body + end + + tests("#delete_policy('fog_policy')").formats(AWS::IAM::Formats::BASIC) do + Fog::AWS[:iam].delete_policy(@policy_arn).body + end + + end + + tests('failure') do + test('failing conditions') + end + +end