diff --git a/README.md b/README.md index e58d028..3cf0fda 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,8 @@ Parsers are currently implemented for the following actions: * GetUser * ListAccessKeys * ListGroup + * ListRoles + * ListRoleTags * ListUsers * UpdateAccessKey * UpdateGroup diff --git a/lib/ex_aws/iam.ex b/lib/ex_aws/iam.ex index b683d4a..a159eab 100644 --- a/lib/ex_aws/iam.ex +++ b/lib/ex_aws/iam.ex @@ -47,6 +47,8 @@ defmodule ExAws.Iam do * GetUser * ListAccessKeys * ListGroup + * ListRoles + * ListRoleTags * ListUsers * UpdateAccessKey * UpdateGroup @@ -76,8 +78,9 @@ defmodule ExAws.Iam do @shared_opts [version: "2010-05-08"] @doc """ - Generates an ExAws operation for the given IAM API action. See the AWS IAM - API Reference for a list of available actions and their parameters. + Generates an ExAws operation for the given IAM API action. + + See the AWS IAM API Reference for a list of available actions. * https://docs.aws.amazon.com/IAM/latest/APIReference @@ -85,10 +88,12 @@ defmodule ExAws.Iam do * `action` - The name of the action you want to call. Should be a _CamelCase_ string. - * `params` - A keyword list of any params the action accepts. + * `params` - A keyword list of any params the action takes. ## Options + Any options that the given action + * `parser` - A function to parse the request result. Defaults to `Parser.parser/2`. @@ -405,6 +410,48 @@ defmodule ExAws.Iam do operation(:delete_group, [group_name: name] ++ opts) end + @doc """ + Creates an ExAws operation for a `ListRoles` IAM request. + + ## Options + + * `:marker` - Use this parameter only when paginating results. + + * `:max_items` - Use this only when paginating results to indicate + the maximum number of items you want in the response. + + * `:path_prefix` - The path prefix for filtering the results. + + See shared options in moduledoc. + + """ + def list_roles(opts \\ []) do + operation(:list_roles, opts) + end + + @doc """ + Creates an ExAws operation for a `ListRoleTags` IAM request. + + ## Parameters + + * `role_name` - The name of the role to return for which you want to get the list of tags. + + ## Options + + * `:marker` - Use this parameter only when paginating results. + + * `:max_items` - Use this only when paginating results to indicate + the maximum number of items you want in the response. + + * `:path_prefix` - The path prefix for filtering the results. + + See shared options in moduledoc. + + """ + def list_role_tags(role_name, opts \\ []) do + operation(:list_role_tags, [role_name: role_name] ++ opts) + end + defp to_operation(params, opts) do %ExAws.Operation.Query{ action: params["Action"], diff --git a/lib/ex_aws/iam/parser.ex b/lib/ex_aws/iam/parser.ex index 17c1a9d..2e7ef1b 100644 --- a/lib/ex_aws/iam/parser.ex +++ b/lib/ex_aws/iam/parser.ex @@ -14,6 +14,7 @@ defmodule ExAws.Iam.Parser do AccessKey, Group, Metadata, + Role, User } @@ -58,6 +59,15 @@ defmodule ExAws.Iam.Parser do Group.parse(xml, action) end + @role_actions ~w[ + ListRoles + ListRoleTags + ] + + defp dispatch(xml, action) when action in @role_actions do + Role.parse(xml, action) + end + @metadata_only_actions ~w[ UpdateAccessKey UpdateGroup diff --git a/lib/ex_aws/iam/parsers/role.ex b/lib/ex_aws/iam/parsers/role.ex new file mode 100644 index 0000000..671e62c --- /dev/null +++ b/lib/ex_aws/iam/parsers/role.ex @@ -0,0 +1,55 @@ +defmodule ExAws.Iam.Parsers.Role do + @moduledoc """ + Defines parsers for handling AWS IAM `Role` query reponses. + + """ + + import SweetXml, only: [sigil_x: 2] + import ExAws.Iam.Utils, only: [response_metadata_path: 0] + + @doc """ + Parses XML from IAM `ListRoles` response. + + """ + def parse(xml, "ListRoles") do + SweetXml.xpath(xml, ~x"//ListRolesResponse", + list_roles_result: [ + ~x"//ListRolesResult", + is_truncated: ~x"./IsTruncated/text()"s, + marker: ~x"./Marker/text()"o, + roles: [ + ~x"./Roles/member"l, + path: ~x"./Path/text()"s, + role_name: ~x"./RoleName/text()"s, + arn: ~x"./Arn/text()"s, + role_id: ~x"./RoleId/text()"s, + create_date: ~x"./CreateDate/text()"s, + max_session_duration: ~x"./MaxSessionDuration/text()"s, + assume_role_policy_document: + ~x"./AssumeRolePolicyDocument/text()"s |> SweetXml.transform_by(&URI.decode/1) + ] + ], + response_metadata: response_metadata_path() + ) + end + + @doc """ + Parses XML from IAM `ListRoleTags` response. + + """ + def parse(xml, "ListRoleTags") do + SweetXml.xpath(xml, ~x"//ListRoleTagsResponse", + list_role_tags_result: [ + ~x"//ListRoleTagsResult", + is_truncated: ~x"./IsTruncated/text()"s, + marker: ~x"./Marker/text()"o, + tags: [ + ~x"./Tags/member"l, + key: ~x"./Key/text()"s, + value: ~x"./Value/text()"s + ] + ], + response_metadata: response_metadata_path() + ) + end +end diff --git a/test/lib/iam/parsers/role_test.exs b/test/lib/iam/parsers/role_test.exs new file mode 100644 index 0000000..9b9ddd3 --- /dev/null +++ b/test/lib/iam/parsers/role_test.exs @@ -0,0 +1,62 @@ +defmodule ExAws.Iam.Parsers.RoleTest do + use ExUnit.Case + + import ExAws.Iam.TestHelper, only: [read_file: 2] + + alias ExAws.Iam.Parser + + test "list_roles/2" do + xml = read_file("role", "list_roles") + response = {:ok, %{body: xml, status_code: 200}} + + expected = + {:ok, + %{ + body: %{ + list_roles_result: %{ + is_truncated: "false", + marker: nil, + roles: [ + %{ + arn: "arn:aws:iam::085326204011:role/foo", + assume_role_policy_document: + "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ec2.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}", + create_date: "2018-10-19T22:04:37Z", + max_session_duration: "3600", + path: "/", + role_id: "AGPAIDI3XY2DD433B73WG", + role_name: "foo" + } + ] + }, + response_metadata: %{request_id: "81ca4919-d3fb-11e8-986e-5fbe089ad211"} + }, + status_code: 200 + }} + + assert expected == Parser.parse(response, "ListRoles") + end + + test "list_role_tags/2" do + xml = read_file("role", "list_role_tags") + response = {:ok, %{body: xml, status_code: 200}} + + expected = + {:ok, + %{ + body: %{ + list_role_tags_result: %{ + is_truncated: "false", + marker: nil, + tags: [ + %{key: "UserRole", value: "developer"} + ] + }, + response_metadata: %{request_id: "81ca4919-d3fb-11e8-986e-5fbe089ad211"} + }, + status_code: 200 + }} + + assert expected == Parser.parse(response, "ListRoleTags") + end +end diff --git a/test/lib/iam_test.exs b/test/lib/iam_test.exs index 0975cbe..6529461 100644 --- a/test/lib/iam_test.exs +++ b/test/lib/iam_test.exs @@ -425,4 +425,46 @@ defmodule ExAws.IamTest do assert Iam.delete_group("my_group") == expected end end + + describe "Role" do + test "list_roles/0 returns an ExAws ListRoles op struct" do + opts = [ + marker: "abc", + max_items: 50, + path_prefix: "/prefix" + ] + + expected = %ExAws.Operation.Query{ + action: "ListRoles", + params: %{ + "Action" => "ListRoles", + "Marker" => "abc", + "MaxItems" => 50, + "PathPrefix" => "/prefix", + "Version" => "2010-05-08" + }, + parser: &Parser.parse/2, + path: "/", + service: :iam + } + + assert Iam.list_roles(opts) == expected + end + + test "list_role_tags/1 returns an ExAws ListRoleTags op struct" do + expected = %ExAws.Operation.Query{ + action: "ListRoleTags", + params: %{ + "Action" => "ListRoleTags", + "RoleName" => "foo", + "Version" => "2010-05-08" + }, + parser: &Parser.parse/2, + path: "/", + service: :iam + } + + assert Iam.list_role_tags("foo") == expected + end + end end diff --git a/test/support/responses/role/list_role_tags.xml b/test/support/responses/role/list_role_tags.xml new file mode 100644 index 0000000..9a0678d --- /dev/null +++ b/test/support/responses/role/list_role_tags.xml @@ -0,0 +1,14 @@ + + + false + + + developer + UserRole + + + + + 81ca4919-d3fb-11e8-986e-5fbe089ad211 + + diff --git a/test/support/responses/role/list_roles.xml b/test/support/responses/role/list_roles.xml new file mode 100644 index 0000000..9032fdf --- /dev/null +++ b/test/support/responses/role/list_roles.xml @@ -0,0 +1,19 @@ + + + false + + + / + %7B%22Version%22%3A%222012-10-17%22%2C%22Statement%22%3A%5B%7B%22Effect%22%3A%22Allow%22%2C%22Principal%22%3A%7B%22Service%22%3A%22ec2.amazonaws.com%22%7D%2C%22Action%22%3A%22sts%3AAssumeRole%22%7D%5D%7D + 3600 + AGPAIDI3XY2DD433B73WG + foo + arn:aws:iam::085326204011:role/foo + 2018-10-19T22:04:37Z + + + + + 81ca4919-d3fb-11e8-986e-5fbe089ad211 + +