From d91e2bd4f05630bbe589c226197dd25387b2bb41 Mon Sep 17 00:00:00 2001 From: Scott Chamberlain Date: Wed, 6 Dec 2023 16:01:18 -0800 Subject: [PATCH] change aws_role, aws_group, aws_user to return similarly formatted results - add create and delete methods for role - add create and delete methods for group - policies: add fxn as_policy_arn to coerce/check policy names/arns before using them - policies: use the as_policy_arn fxn throughout policy fxns where applicable - import two new pkgs: memoise, withr --- .Rbuildignore | 1 + DESCRIPTION | 8 +- NAMESPACE | 8 + R/globals.R | 2 + R/groups.R | 43 ++++- R/policies.R | 106 +++++++++-- R/roles.R | 101 ++++++++++- R/users.R | 10 +- man/as_policy_arn.Rd | 31 ++++ man/aws_group.Rd | 8 +- man/aws_group_create.Rd | 29 ++++ man/aws_group_delete.Rd | 26 +++ man/aws_policies.Rd | 15 +- man/aws_policy.Rd | 5 +- man/aws_policy_attach.Rd | 6 +- man/aws_policy_detach.Rd | 2 +- man/aws_policy_exists.Rd | 4 +- man/aws_role.Rd | 20 ++- man/aws_role_create.Rd | 71 ++++++++ man/aws_role_delete.Rd | 26 +++ man/aws_user.Rd | 2 +- man/aws_user_create.Rd | 2 +- tests/fixtures/aws_policy_detach.yml | 251 ++++++++++++++++++++++----- 23 files changed, 682 insertions(+), 95 deletions(-) create mode 100644 man/as_policy_arn.Rd create mode 100644 man/aws_group_create.Rd create mode 100644 man/aws_group_delete.Rd create mode 100644 man/aws_role_create.Rd create mode 100644 man/aws_role_delete.Rd diff --git a/.Rbuildignore b/.Rbuildignore index cbf7dc4..569f1cf 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -7,3 +7,4 @@ ^pkgdown$ ^.lintr$ ^README\.Rmd$ +^data-raw$ diff --git a/DESCRIPTION b/DESCRIPTION index e0b02f0..d16aaa7 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -24,13 +24,17 @@ Imports: fs, s3fs (>= 0.1.3), cli, - glue + glue, + memoise Suggests: roxyglobals, testthat (>= 3.0.0), - vcr (>= 0.6.0) + vcr (>= 0.6.0), + withr Config/roxyglobals/filename: globals.R Config/roxyglobals/unique: FALSE Config/testthat/edition: 3 Remotes: sckott/s3fs@sckott/file_download_vec +Depends: + R (>= 2.10) diff --git a/NAMESPACE b/NAMESPACE index 20ec8b1..b636ce5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +export(as_policy_arn) export(aws_bucket_acl_get) export(aws_bucket_acl_modify) export(aws_bucket_create) @@ -16,6 +17,8 @@ export(aws_file_download) export(aws_file_exists) export(aws_file_upload) export(aws_group) +export(aws_group_create) +export(aws_group_delete) export(aws_groups) export(aws_iam_client) export(aws_policies) @@ -24,6 +27,8 @@ export(aws_policy_attach) export(aws_policy_detach) export(aws_policy_exists) export(aws_role) +export(aws_role_create) +export(aws_role_delete) export(aws_roles) export(aws_user) export(aws_user_access_key) @@ -35,7 +40,10 @@ export(billing) export(s3_path) export(set_s3_interface) importFrom(cli,cli_inform) +importFrom(dplyr,bind_rows) +importFrom(dplyr,filter) importFrom(dplyr,mutate) +importFrom(dplyr,pull) importFrom(fs,file_exists) importFrom(fs,fs_bytes) importFrom(glue,glue) diff --git a/R/globals.R b/R/globals.R index 08b1d55..a570ec6 100644 --- a/R/globals.R +++ b/R/globals.R @@ -3,6 +3,8 @@ utils::globalVariables(c( ".", # ".", # + "PolicyName", # + "Arn", # ".", # "PasswordLastUsed", # "CreateDate", # diff --git a/R/groups.R b/R/groups.R index f7a073c..74484bc 100644 --- a/R/groups.R +++ b/R/groups.R @@ -34,9 +34,11 @@ aws_groups <- function(username = NULL, ...) { #' #' @export #' @param name (character) the group name -#' @return A list with two elements: -#' - group: tibble with information about the group -#' - users: tibble with users in the group +#' @return a named list with slots for: +#' - group: information about the group (tibble) +#' - users: users in the group (tibble) +#' - policies (character) +#' - attached_policies (tibble) #' @details see docs #' @autoglobal #' @examples \dontrun{ @@ -46,6 +48,39 @@ aws_group <- function(name) { x <- env64$iam$get_group(name) list( group = x$Group %>% list(.) %>% group_list_tidy(), - users = x$Users %>% user_list_tidy() + users = x$Users %>% user_list_tidy(), + policies = policies("group", name), + attached_policies = policies_attached("group", name) ) } + +#' Create a group +#' +#' @export +#' @param name (character) A group name. required +#' @param path (character) The path for the group name. optional. +#' If it is not included, it defaults to a slash (/). +#' @return A tibble with information about the group created +#' @details See +#' docs for details on the parameters +#' @examples \dontrun{ +#' aws_group_create("testgroup") +#' } +aws_group_create <- function(name, path = NULL) { + env64$iam$create_group(Path = path, GroupName = name) %>% + group_list_tidy() +} + +#' Delete a group +#' +#' @export +#' @inheritParams aws_group_create +#' @return an empty list +#' @details See +#' docs for more details +#' @examples \dontrun{ +#' aws_group_delete(name = "testgroup") +#' } +aws_group_delete <- function(name) { + env64$iam$delete_group(name) +} diff --git a/R/policies.R b/R/policies.R index 3daa940..08c1b8a 100644 --- a/R/policies.R +++ b/R/policies.R @@ -14,29 +14,43 @@ policy_list_tidy <- function(x) { tidy_generator(vars)(x) } +all_policies <- memoise::memoise(function(...) { + if (Sys.getenv("TESTING64", FALSE)) { + return(policies_sample) + } + paginate_aws(env64$iam$list_policies, "Policies", ...) %>% policy_list_tidy() +}) + #' List policies #' #' @export -#' @param ... parameters passed on to the `paws` -#' [list_users](https://www.paws-r-sdk.com/docs/iam_list_policies/) method +#' @param refresh (logical) refresh results? default: `FALSE`. to invalidate +#' cache and refresh policy data, set `refresh=TRUE` +#' @param ... parameters passed on to +#' [list_policies](https://www.paws-r-sdk.com/docs/iam_list_policies/) +#' @details uses `memoise` internally to cache results to speed up all +#' subsequent calls to the function #' @return A tibble with information about policies #' @examples \dontrun{ #' aws_policies() +#' aws_policies() +#' aws_policies(refresh = TRUE) #' } -aws_policies <- function(...) { - paginate_aws(env64$iam$list_policies, "Policies") %>% - policy_list_tidy() +aws_policies <- function(refresh = FALSE, ...) { + if (refresh) memoise::forget(all_policies) + all_policies(...) } #' Get a policy #' #' @export -#' @param name (character) the policy name +#' @param name (character) a policy name or ARN #' @return a tibble with policy details #' @details see docs #' @autoglobal #' @examples \dontrun{ -#' aws_policy(name = "ReadOnlyAccess") +#' aws_policy("ReadOnlyAccess") +#' aws_policy("arn:aws:iam::aws:policy/ReadOnlyAccess") #' } aws_policy <- function(name) { env64$iam$get_policy(as_policy_arn(name))$Policy %>% @@ -47,18 +61,59 @@ aws_policy <- function(name) { #' Get a policy #' #' @export -#' @param name (character) the policy name +#' @param name (character) a policy name #' @return a tibble with policy details #' @details see docs #' @examples \dontrun{ -#' aws_policy(name = "ReadOnlyAccess") +#' aws_policy_exists("ReadOnlyAccess") #' } aws_policy_exists <- function(name) { !is.null(purrr::safely(aws_policy)(name)$result) } +#' Convert a policy name to a policy ARN +#' +#' @export +#' @importFrom dplyr filter pull +#' @param name (character) a policy name or arn +#' @note uses exact matching; fails with error if there's no match; +#' beware as there is no validation is done of a user input policy arn +#' @return a policy ARN +#' @autoglobal +#' @examples \dontrun{ +#' as_policy_arn("ReadOnlyAccess") +#' as_policy_arn("arn:aws:iam::aws:policy/ReadOnlyAccess") +#' as_policy_arn("AmazonRDSDataFullAccess") +#' # as_policy_arn("Blarp") +#' # as_policy_arn(letters) +#' # as_policy_arn(5) +#' } as_policy_arn <- function(name) { - glue::glue("arn:aws:iam::aws:policy/{name}") + stopifnot(is.character(name)) + stopifnot(length(name) == 1) + if (grepl("^arn:", name)) { + return(name) + } + pols <- aws_policies() + if (!name %in% pols$PolicyName) { + stop(glue::glue( + "'{name}' not associated with a known policy\n", + "this function only checks against the policies listed with the\n", + "https://www.paws-r-sdk.com/docs/iam_list_policies/ method" + )) + } + pols %>% + filter(PolicyName == name) %>% + pull(Arn) +} + +call_x_method <- function(x) { + fun <- switch(entity_type(x), + user = aws_user, + role = aws_role, + group = aws_group + ) + fun(entity_value(x)) } #' Attach a policy to a user, group, or role @@ -66,11 +121,11 @@ as_policy_arn <- function(name) { #' @export #' @param .x result of a call to create or get method for user, #' group, or role -#' @param policy (character) a policy name +#' @param policy (character) a policy name or ARN #' @return A tibble with information about policies #' @examples \dontrun{ -#' aws_user() %>% -#' aws_policy_attach("AmazonRDSDataFullAccess") +#' aws_policy("AmazonRDSDataFullAccess") +#' aws_user() %>% aws_policy_attach("AmazonRDSDataFullAccess") #' aws_user()$attached_policies #' #' # aws_role("OrganizationAccountSecurityRole") %>% @@ -79,6 +134,7 @@ as_policy_arn <- function(name) { aws_policy_attach <- function(.x, policy) { method <- glue::glue("attach_{entity_type(.x)}_policy") env64$iam[[method]](entity_value(.x), as_policy_arn(policy)) + call_x_method(.x) } #' Detach a policy from a user, group, or role @@ -86,7 +142,7 @@ aws_policy_attach <- function(.x, policy) { #' @export #' @param .x result of a call to create or get method for user, #' group, or role -#' @param policy (character) a policy name +#' @param policy (character) a policy name or ARN #' @return A tibble with information about policies #' @examples \dontrun{ #' aws_user() %>% @@ -99,6 +155,7 @@ aws_policy_attach <- function(.x, policy) { aws_policy_detach <- function(.x, policy) { method <- glue::glue("detach_{entity_type(.x)}_policy") env64$iam[[method]](entity_value(.x), as_policy_arn(policy)) + call_x_method(.x) } # FIXME: this is probably fragile @@ -126,3 +183,24 @@ entity_value <- function(x) { x[[1]][[names(x[[1]])[1]]] } } + +#' @param which (character) one of role, user, or group +#' @param name (character) the name of a role, user or group +#' @return a tibble +#' @noRd +#' @keywords internal +policies <- function(which, name) { + method <- glue::glue("list_{which}_policies") + env64$iam[[method]](name)$PolicyNames +} +#' @importFrom dplyr bind_rows +#' @param which (character) one of role, user, or group +#' @param name (character) the name of a role, user or group +#' @return a tibble +#' @noRd +#' @keywords internal +policies_attached <- function(which, name) { + method <- glue::glue("list_attached_{which}_policies") + res <- env64$iam[[method]](name) + res$AttachedPolicies %>% bind_rows() +} diff --git a/R/roles.R b/R/roles.R index 6e3c8e0..41cb7cd 100644 --- a/R/roles.R +++ b/R/roles.R @@ -4,11 +4,12 @@ #' @param x (list) a nested list, from a call to #' [list_users](https://www.paws-r-sdk.com/docs/iam_list_roles/) #' @keywords internal -#' @note leaves out: PermissionsBoundary, Tags, RoleLastUsed +#' @note leaves out: PermissionsBoundary, Tags, RoleLastUsed, +#' MaxSessionDuration role_list_tidy <- function(x) { vars <- c( "RoleName", "RoleId", "Path", "Arn", "CreateDate", - "AssumeRolePolicyDocument", "Description", "MaxSessionDuration" + "Description", "AssumeRolePolicyDocument" ) tidy_generator(vars)(x) } @@ -30,14 +31,102 @@ aws_roles <- function(...) { #' #' @export #' @param name (character) the role name -#' @return a tibble with role details -#' @details see docs +#' @return a named list with slots for: +#' - role (tibble) +#' - policies (character) +#' - attached_policies (tibble) +#' @details see docs ; +#' also includes policies and attached policies by calling `list_role_policies` +#' and `list_attached_role_policies` #' @autoglobal #' @examples \dontrun{ -#' aws_role(name = "OrganizationAccountSecurityRole") +#' res <- aws_role(name = "OrganizationAccountSecurityRole") +#' res +#' res$role +#' res$policies +#' res$attached_policies +#' +#' aws_role("AWSServiceRoleForCloudTrail") +#' aws_role("AWSServiceRoleForRedshift") #' } aws_role <- function(name) { - env64$iam$get_role(name)$Role %>% + df <- env64$iam$get_role(name)$Role %>% list(.) %>% role_list_tidy() + list( + role = df, + policies = policies("role", name), + attached_policies = policies_attached("role", name) + ) +} + +#' Create a role +#' +#' @export +#' @param name (character) A role name. required +#' @param path (character) The path for the role name. optional. +#' If it is not included, it defaults to a slash (/). +#' @param assume_role_policy_document (character) The trust relationship policy +#' document that grants an entity permission to assume the role. json as string. +#' required +#' @param description (character) a description fo the role. optional +#' @param max_session_duration (character) The maximum session duration +#' (in seconds) that you want to set for the specified role. optional +#' @param permission_boundary (character) The ARN of the managed policy +#' that is used to set the permissions boundary for the role. optional +#' @param tags (list) A list of tags that you want to attach to the new user. +#' optional +#' @return A tibble with information about the role created +#' @details See +#' docs for details on the parameters +#' @examples \dontrun{ +#' role_name <- "MyRole" +#' trust_policy <- list( +#' Version = "2012-10-17", +#' Statement = list( +#' list( +#' Effect = "Allow", +#' Principal = list( +#' Service = "lambda.amazonaws.com" +#' ), +#' Action = "sts:AssumeRole" +#' ) +#' ) +#' ) +#' doc <- jsonlite::toJSON(trust_policy, auto_unbox = TRUE) +#' desc <- "My test role" +#' z <- aws_role_create(role_name, assume_role_policy_document = doc, +#' description = desc) +#' z +#' # attach a policy +#' z %>% aws_policy_attach("AWSLambdaBasicExecutionRole") +#' } +aws_role_create <- function( + name, assume_role_policy_document, path = NULL, + description = NULL, max_session_duration = NULL, permission_boundary = NULL, + tags = NULL) { + env64$iam$create_role( + Path = path, + RoleName = name, + AssumeRolePolicyDocument = assume_role_policy_document, + Description = description, + MaxSessionDuration = max_session_duration, + PermissionsBoundary = permission_boundary, + Tags = tags + ) %>% + role_list_tidy() +} + +#' Delete a role +#' +#' @export +#' @inheritParams aws_role_create +#' @return an empty list +#' @details See +#' docs for more details +#' @examples \dontrun{ +#' aws_role_delete(name = "MyRole") +#' } +aws_role_delete <- function(name) { + env64$iam$delete_role(name) } diff --git a/R/users.R b/R/users.R index 7af364d..ff94118 100644 --- a/R/users.R +++ b/R/users.R @@ -36,8 +36,8 @@ aws_users <- function(...) { #' @return a named list with slots for: #' - user (tibble) #' - policies (list) -#' - groups (list) #' - attached_policies (list) +#' - groups (list) #' @details See the following docs links for details #' - #' - @@ -60,9 +60,9 @@ aws_user <- function(username = NULL) { if (is.null(username)) username <- x$UserName list( user = x, - policies = env64$iam$list_user_policies(username), - groups = env64$iam$list_groups_for_user(username), - attached_policies = env64$iam$list_attached_user_policies(username) + policies = policies("user", username), + attached_policies = policies_attached("user", username), + groups = env64$iam$list_groups_for_user(username) ) } @@ -84,7 +84,7 @@ aws_user_current <- function() { #' that is used to set the permissions boundary for the user. optional #' @param tags (list) A list of tags that you want to attach to the new user. #' optional -#' @return A tibble with information about user accounts +#' @return A tibble with information about the user created #' @details See #' docs for details on the parameters #' @examples \dontrun{ diff --git a/man/as_policy_arn.Rd b/man/as_policy_arn.Rd new file mode 100644 index 0000000..0abee9d --- /dev/null +++ b/man/as_policy_arn.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/policies.R +\name{as_policy_arn} +\alias{as_policy_arn} +\title{Convert a policy name to a policy ARN} +\usage{ +as_policy_arn(name) +} +\arguments{ +\item{name}{(character) a policy name or arn} +} +\value{ +a policy ARN +} +\description{ +Convert a policy name to a policy ARN +} +\note{ +uses exact matching; fails with error if there's no match; +beware as there is no validation is done of a user input policy arn +} +\examples{ +\dontrun{ +as_policy_arn("ReadOnlyAccess") +as_policy_arn("arn:aws:iam::aws:policy/ReadOnlyAccess") +as_policy_arn("AmazonRDSDataFullAccess") +# as_policy_arn("Blarp") +# as_policy_arn(letters) +# as_policy_arn(5) +} +} diff --git a/man/aws_group.Rd b/man/aws_group.Rd index 3970848..1c65a1b 100644 --- a/man/aws_group.Rd +++ b/man/aws_group.Rd @@ -10,10 +10,12 @@ aws_group(name) \item{name}{(character) the group name} } \value{ -A list with two elements: +a named list with slots for: \itemize{ -\item group: tibble with information about the group -\item users: tibble with users in the group +\item group: information about the group (tibble) +\item users: users in the group (tibble) +\item policies (character) +\item attached_policies (tibble) } } \description{ diff --git a/man/aws_group_create.Rd b/man/aws_group_create.Rd new file mode 100644 index 0000000..84c1639 --- /dev/null +++ b/man/aws_group_create.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/groups.R +\name{aws_group_create} +\alias{aws_group_create} +\title{Create a group} +\usage{ +aws_group_create(name, path = NULL) +} +\arguments{ +\item{name}{(character) A group name. required} + +\item{path}{(character) The path for the group name. optional. +If it is not included, it defaults to a slash (/).} +} +\value{ +A tibble with information about the group created +} +\description{ +Create a group +} +\details{ +See \url{https://www.paws-r-sdk.com/docs/iam_create_group/} +docs for details on the parameters +} +\examples{ +\dontrun{ +aws_group_create("testgroup") +} +} diff --git a/man/aws_group_delete.Rd b/man/aws_group_delete.Rd new file mode 100644 index 0000000..490b0eb --- /dev/null +++ b/man/aws_group_delete.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/groups.R +\name{aws_group_delete} +\alias{aws_group_delete} +\title{Delete a group} +\usage{ +aws_group_delete(name) +} +\arguments{ +\item{name}{(character) A group name. required} +} +\value{ +an empty list +} +\description{ +Delete a group +} +\details{ +See \url{https://www.paws-r-sdk.com/docs/iam_delete_group/} +docs for more details +} +\examples{ +\dontrun{ +aws_group_delete(name = "testgroup") +} +} diff --git a/man/aws_policies.Rd b/man/aws_policies.Rd index c85d7e9..426bde1 100644 --- a/man/aws_policies.Rd +++ b/man/aws_policies.Rd @@ -4,11 +4,14 @@ \alias{aws_policies} \title{List policies} \usage{ -aws_policies(...) +aws_policies(refresh = FALSE, ...) } \arguments{ -\item{...}{parameters passed on to the \code{paws} -\href{https://www.paws-r-sdk.com/docs/iam_list_policies/}{list_users} method} +\item{refresh}{(logical) refresh results? default: \code{FALSE}. to invalidate +cache and refresh policy data, set \code{refresh=TRUE}} + +\item{...}{parameters passed on to +\href{https://www.paws-r-sdk.com/docs/iam_list_policies/}{list_policies}} } \value{ A tibble with information about policies @@ -16,8 +19,14 @@ A tibble with information about policies \description{ List policies } +\details{ +uses \code{memoise} internally to cache results to speed up all +subsequent calls to the function +} \examples{ \dontrun{ aws_policies() +aws_policies() +aws_policies(refresh = TRUE) } } diff --git a/man/aws_policy.Rd b/man/aws_policy.Rd index f9f94b0..605b797 100644 --- a/man/aws_policy.Rd +++ b/man/aws_policy.Rd @@ -7,7 +7,7 @@ aws_policy(name) } \arguments{ -\item{name}{(character) the policy name} +\item{name}{(character) a policy name or ARN} } \value{ a tibble with policy details @@ -20,6 +20,7 @@ see docs \url{https://www.paws-r-sdk.com/docs/iam_get_policy/} } \examples{ \dontrun{ -aws_policy(name = "ReadOnlyAccess") +aws_policy("ReadOnlyAccess") +aws_policy("arn:aws:iam::aws:policy/ReadOnlyAccess") } } diff --git a/man/aws_policy_attach.Rd b/man/aws_policy_attach.Rd index 391b090..4038e60 100644 --- a/man/aws_policy_attach.Rd +++ b/man/aws_policy_attach.Rd @@ -10,7 +10,7 @@ aws_policy_attach(.x, policy) \item{.x}{result of a call to create or get method for user, group, or role} -\item{policy}{(character) a policy name} +\item{policy}{(character) a policy name or ARN} } \value{ A tibble with information about policies @@ -20,8 +20,8 @@ Attach a policy to a user, group, or role } \examples{ \dontrun{ -aws_user() \%>\% - aws_policy_attach("AmazonRDSDataFullAccess") +aws_policy("AmazonRDSDataFullAccess") +aws_user() \%>\% aws_policy_attach("AmazonRDSDataFullAccess") aws_user()$attached_policies # aws_role("OrganizationAccountSecurityRole") \%>\% diff --git a/man/aws_policy_detach.Rd b/man/aws_policy_detach.Rd index c06ac41..fffa1f2 100644 --- a/man/aws_policy_detach.Rd +++ b/man/aws_policy_detach.Rd @@ -10,7 +10,7 @@ aws_policy_detach(.x, policy) \item{.x}{result of a call to create or get method for user, group, or role} -\item{policy}{(character) a policy name} +\item{policy}{(character) a policy name or ARN} } \value{ A tibble with information about policies diff --git a/man/aws_policy_exists.Rd b/man/aws_policy_exists.Rd index 5d72494..e480c77 100644 --- a/man/aws_policy_exists.Rd +++ b/man/aws_policy_exists.Rd @@ -7,7 +7,7 @@ aws_policy_exists(name) } \arguments{ -\item{name}{(character) the policy name} +\item{name}{(character) a policy name} } \value{ a tibble with policy details @@ -20,6 +20,6 @@ see docs \url{https://www.paws-r-sdk.com/docs/iam_get_policy/} } \examples{ \dontrun{ -aws_policy(name = "ReadOnlyAccess") +aws_policy_exists("ReadOnlyAccess") } } diff --git a/man/aws_role.Rd b/man/aws_role.Rd index c643b65..51f184a 100644 --- a/man/aws_role.Rd +++ b/man/aws_role.Rd @@ -10,16 +10,30 @@ aws_role(name) \item{name}{(character) the role name} } \value{ -a tibble with role details +a named list with slots for: +\itemize{ +\item role (tibble) +\item policies (character) +\item attached_policies (tibble) +} } \description{ Get a role } \details{ -see docs \url{https://www.paws-r-sdk.com/docs/iam_get_role/} +see docs \url{https://www.paws-r-sdk.com/docs/iam_get_role/}; +also includes policies and attached policies by calling \code{list_role_policies} +and \code{list_attached_role_policies} } \examples{ \dontrun{ -aws_role(name = "OrganizationAccountSecurityRole") +res <- aws_role(name = "OrganizationAccountSecurityRole") +res +res$role +res$policies +res$attached_policies + +aws_role("AWSServiceRoleForCloudTrail") +aws_role("AWSServiceRoleForRedshift") } } diff --git a/man/aws_role_create.Rd b/man/aws_role_create.Rd new file mode 100644 index 0000000..5a60c90 --- /dev/null +++ b/man/aws_role_create.Rd @@ -0,0 +1,71 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/roles.R +\name{aws_role_create} +\alias{aws_role_create} +\title{Create a role} +\usage{ +aws_role_create( + name, + assume_role_policy_document, + path = NULL, + description = NULL, + max_session_duration = NULL, + permission_boundary = NULL, + tags = NULL +) +} +\arguments{ +\item{name}{(character) A role name. required} + +\item{assume_role_policy_document}{(character) The trust relationship policy +document that grants an entity permission to assume the role. json as string. +required} + +\item{path}{(character) The path for the role name. optional. +If it is not included, it defaults to a slash (/).} + +\item{description}{(character) a description fo the role. optional} + +\item{max_session_duration}{(character) The maximum session duration +(in seconds) that you want to set for the specified role. optional} + +\item{permission_boundary}{(character) The ARN of the managed policy +that is used to set the permissions boundary for the role. optional} + +\item{tags}{(list) A list of tags that you want to attach to the new user. +optional} +} +\value{ +A tibble with information about the role created +} +\description{ +Create a role +} +\details{ +See \url{https://www.paws-r-sdk.com/docs/iam_create_role/} +docs for details on the parameters +} +\examples{ +\dontrun{ +role_name <- "MyRole" +trust_policy <- list( + Version = "2012-10-17", + Statement = list( + list( + Effect = "Allow", + Principal = list( + Service = "lambda.amazonaws.com" + ), + Action = "sts:AssumeRole" + ) + ) +) +doc <- jsonlite::toJSON(trust_policy, auto_unbox = TRUE) +desc <- "My test role" +z <- aws_role_create(role_name, assume_role_policy_document = doc, + description = desc) +z +# attach a policy +z \%>\% aws_policy_attach("AWSLambdaBasicExecutionRole") +} +} diff --git a/man/aws_role_delete.Rd b/man/aws_role_delete.Rd new file mode 100644 index 0000000..eabe402 --- /dev/null +++ b/man/aws_role_delete.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/roles.R +\name{aws_role_delete} +\alias{aws_role_delete} +\title{Delete a role} +\usage{ +aws_role_delete(name) +} +\arguments{ +\item{name}{(character) A role name. required} +} +\value{ +an empty list +} +\description{ +Delete a role +} +\details{ +See \url{https://www.paws-r-sdk.com/docs/iam_delete_role/} +docs for more details +} +\examples{ +\dontrun{ +aws_role_delete(name = "MyRole") +} +} diff --git a/man/aws_user.Rd b/man/aws_user.Rd index 9f402f4..e7d34e6 100644 --- a/man/aws_user.Rd +++ b/man/aws_user.Rd @@ -14,8 +14,8 @@ a named list with slots for: \itemize{ \item user (tibble) \item policies (list) -\item groups (list) \item attached_policies (list) +\item groups (list) } } \description{ diff --git a/man/aws_user_create.Rd b/man/aws_user_create.Rd index d2552bb..0b996a0 100644 --- a/man/aws_user_create.Rd +++ b/man/aws_user_create.Rd @@ -19,7 +19,7 @@ that is used to set the permissions boundary for the user. optional} optional} } \value{ -A tibble with information about user accounts +A tibble with information about the user created } \description{ Create a user diff --git a/tests/fixtures/aws_policy_detach.yml b/tests/fixtures/aws_policy_detach.yml index afd6d27..d9e644b 100644 --- a/tests/fixtures/aws_policy_detach.yml +++ b/tests/fixtures/aws_policy_detach.yml @@ -10,7 +10,7 @@ http_interactions: Accept: application/xml Content-Type: application/x-www-form-urlencoded; charset=utf-8 Content-Length: '52' - X-Amz-Date: 20231206T212914Z + X-Amz-Date: 20231207T000005Z Authorization: redacted response: status: @@ -19,10 +19,10 @@ http_interactions: reason: OK message: 'Success: (200) OK' headers: - x-amzn-requestid: 4b860140-a819-41b4-bb3c-a035ee481166 + x-amzn-requestid: 254c4f72-3f85-458b-8405-eb96e4480b61 content-type: text/xml content-length: '467' - date: Wed, 06 Dec 2023 21:29:14 GMT + date: Thu, 07 Dec 2023 00:00:04 GMT body: encoding: '' file: no @@ -38,10 +38,10 @@ http_interactions: - 4b860140-a819-41b4-bb3c-a035ee481166 + 254c4f72-3f85-458b-8405-eb96e4480b61 - recorded_at: 2023-12-06 21:29:15 GMT + recorded_at: 2023-12-07 00:00:07 GMT recorded_with: vcr/1.2.2, webmockr/0.9.0 - request: method: post @@ -54,7 +54,7 @@ http_interactions: Accept: application/xml Content-Type: application/x-www-form-urlencoded; charset=utf-8 Content-Length: '61' - X-Amz-Date: 20231206T212914Z + X-Amz-Date: 20231207T000005Z Authorization: redacted response: status: @@ -63,10 +63,10 @@ http_interactions: reason: OK message: 'Success: (200) OK' headers: - x-amzn-requestid: 17d4d274-9f21-4518-8ddf-a3933f328f22 + x-amzn-requestid: 6ccbcc59-54fd-48f9-9ec2-6dd51826ba73 content-type: text/xml content-length: '323' - date: Wed, 06 Dec 2023 21:29:14 GMT + date: Thu, 07 Dec 2023 00:00:05 GMT body: encoding: '' file: no @@ -77,10 +77,10 @@ http_interactions: - 17d4d274-9f21-4518-8ddf-a3933f328f22 + 6ccbcc59-54fd-48f9-9ec2-6dd51826ba73 - recorded_at: 2023-12-06 21:29:15 GMT + recorded_at: 2023-12-07 00:00:07 GMT recorded_with: vcr/1.2.2, webmockr/0.9.0 - request: method: post @@ -93,7 +93,7 @@ http_interactions: Accept: application/xml Content-Type: application/x-www-form-urlencoded; charset=utf-8 Content-Length: '69' - X-Amz-Date: 20231206T212914Z + X-Amz-Date: 20231207T000005Z Authorization: redacted response: status: @@ -102,10 +102,10 @@ http_interactions: reason: OK message: 'Success: (200) OK' headers: - x-amzn-requestid: 6ee3d4ae-124b-4f83-8c03-5ee5da649eb6 + x-amzn-requestid: 86209ae5-d0fa-48a9-ae43-f16e2f574db8 content-type: text/xml content-length: '554' - date: Wed, 06 Dec 2023 21:29:14 GMT + date: Thu, 07 Dec 2023 00:00:05 GMT body: encoding: '' file: no @@ -121,10 +121,10 @@ http_interactions: - 6ee3d4ae-124b-4f83-8c03-5ee5da649eb6 + 86209ae5-d0fa-48a9-ae43-f16e2f574db8 - recorded_at: 2023-12-06 21:29:15 GMT + recorded_at: 2023-12-07 00:00:07 GMT recorded_with: vcr/1.2.2, webmockr/0.9.0 - request: method: post @@ -137,7 +137,7 @@ http_interactions: Accept: application/xml Content-Type: application/x-www-form-urlencoded; charset=utf-8 Content-Length: '62' - X-Amz-Date: 20231206T212914Z + X-Amz-Date: 20231207T000005Z Authorization: redacted response: status: @@ -146,10 +146,10 @@ http_interactions: reason: OK message: 'Success: (200) OK' headers: - x-amzn-requestid: 182f530f-7eb8-4dd9-812a-92a15668965d + x-amzn-requestid: 8ceac547-3ba0-43f5-9398-0c4e7b481f40 content-type: text/xml content-length: '322' - date: Wed, 06 Dec 2023 21:29:14 GMT + date: Thu, 07 Dec 2023 00:00:05 GMT body: encoding: '' file: no @@ -160,10 +160,10 @@ http_interactions: - 182f530f-7eb8-4dd9-812a-92a15668965d + 8ceac547-3ba0-43f5-9398-0c4e7b481f40 - recorded_at: 2023-12-06 21:29:15 GMT + recorded_at: 2023-12-07 00:00:07 GMT recorded_with: vcr/1.2.2, webmockr/0.9.0 - request: method: post @@ -176,7 +176,7 @@ http_interactions: Accept: application/xml Content-Type: application/x-www-form-urlencoded; charset=utf-8 Content-Length: '52' - X-Amz-Date: 20231206T212914Z + X-Amz-Date: 20231207T000005Z Authorization: redacted response: status: @@ -185,10 +185,10 @@ http_interactions: reason: OK message: 'Success: (200) OK' headers: - x-amzn-requestid: d15cc30f-0af0-4c27-9f6d-8ef565dfe27c + x-amzn-requestid: 270ed36c-a1d2-4455-86d1-416452bdaa0b content-type: text/xml content-length: '467' - date: Wed, 06 Dec 2023 21:29:14 GMT + date: Thu, 07 Dec 2023 00:00:05 GMT body: encoding: '' file: no @@ -204,10 +204,10 @@ http_interactions: - d15cc30f-0af0-4c27-9f6d-8ef565dfe27c + 270ed36c-a1d2-4455-86d1-416452bdaa0b - recorded_at: 2023-12-06 21:29:15 GMT + recorded_at: 2023-12-07 00:00:07 GMT recorded_with: vcr/1.2.2, webmockr/0.9.0 - request: method: post @@ -220,7 +220,7 @@ http_interactions: Accept: application/xml Content-Type: application/x-www-form-urlencoded; charset=utf-8 Content-Length: '61' - X-Amz-Date: 20231206T212915Z + X-Amz-Date: 20231207T000006Z Authorization: redacted response: status: @@ -229,10 +229,10 @@ http_interactions: reason: OK message: 'Success: (200) OK' headers: - x-amzn-requestid: b2330651-c9fa-4023-a2b2-bd87a6ab88c7 + x-amzn-requestid: bb285892-ad5e-4be3-8ecd-efcbabb08e67 content-type: text/xml content-length: '323' - date: Wed, 06 Dec 2023 21:29:14 GMT + date: Thu, 07 Dec 2023 00:00:05 GMT body: encoding: '' file: no @@ -243,10 +243,10 @@ http_interactions: - b2330651-c9fa-4023-a2b2-bd87a6ab88c7 + bb285892-ad5e-4be3-8ecd-efcbabb08e67 - recorded_at: 2023-12-06 21:29:15 GMT + recorded_at: 2023-12-07 00:00:07 GMT recorded_with: vcr/1.2.2, webmockr/0.9.0 - request: method: post @@ -259,7 +259,7 @@ http_interactions: Accept: application/xml Content-Type: application/x-www-form-urlencoded; charset=utf-8 Content-Length: '69' - X-Amz-Date: 20231206T212915Z + X-Amz-Date: 20231207T000006Z Authorization: redacted response: status: @@ -268,10 +268,10 @@ http_interactions: reason: OK message: 'Success: (200) OK' headers: - x-amzn-requestid: d760a3b2-b72d-46e0-9d5d-826d91747bab + x-amzn-requestid: ee727d85-0ecf-423b-a1e8-dd5e4135bc19 content-type: text/xml content-length: '554' - date: Wed, 06 Dec 2023 21:29:15 GMT + date: Thu, 07 Dec 2023 00:00:05 GMT body: encoding: '' file: no @@ -287,10 +287,10 @@ http_interactions: - d760a3b2-b72d-46e0-9d5d-826d91747bab + ee727d85-0ecf-423b-a1e8-dd5e4135bc19 - recorded_at: 2023-12-06 21:29:15 GMT + recorded_at: 2023-12-07 00:00:07 GMT recorded_with: vcr/1.2.2, webmockr/0.9.0 - request: method: post @@ -303,7 +303,7 @@ http_interactions: Accept: application/xml Content-Type: application/x-www-form-urlencoded; charset=utf-8 Content-Length: '62' - X-Amz-Date: 20231206T212915Z + X-Amz-Date: 20231207T000006Z Authorization: redacted response: status: @@ -312,10 +312,10 @@ http_interactions: reason: OK message: 'Success: (200) OK' headers: - x-amzn-requestid: 479b479e-55ff-4d51-88a9-96bb3e0ccc52 + x-amzn-requestid: e9f166f2-5962-42c5-8663-97cbafd1d3e6 content-type: text/xml content-length: '322' - date: Wed, 06 Dec 2023 21:29:15 GMT + date: Thu, 07 Dec 2023 00:00:05 GMT body: encoding: '' file: no @@ -326,10 +326,10 @@ http_interactions: - 479b479e-55ff-4d51-88a9-96bb3e0ccc52 + e9f166f2-5962-42c5-8663-97cbafd1d3e6 - recorded_at: 2023-12-06 21:29:15 GMT + recorded_at: 2023-12-07 00:00:07 GMT recorded_with: vcr/1.2.2, webmockr/0.9.0 - request: method: post @@ -342,7 +342,7 @@ http_interactions: Accept: application/xml Content-Type: application/x-www-form-urlencoded; charset=utf-8 Content-Length: '133' - X-Amz-Date: 20231206T212915Z + X-Amz-Date: 20231207T000006Z Authorization: redacted response: status: @@ -351,18 +351,179 @@ http_interactions: reason: OK message: 'Success: (200) OK' headers: - x-amzn-requestid: 92a8f365-afad-40e2-9c6d-64e959e4792a + x-amzn-requestid: 4c5c5aa1-7647-4a40-9766-b4252155ed64 content-type: text/xml content-length: '212' - date: Wed, 06 Dec 2023 21:29:15 GMT + date: Thu, 07 Dec 2023 00:00:06 GMT body: encoding: '' file: no string: | - 92a8f365-afad-40e2-9c6d-64e959e4792a + 4c5c5aa1-7647-4a40-9766-b4252155ed64 - recorded_at: 2023-12-06 21:29:15 GMT + recorded_at: 2023-12-07 00:00:07 GMT + recorded_with: vcr/1.2.2, webmockr/0.9.0 +- request: + method: post + uri: https://iam.amazonaws.com/ + body: + encoding: '' + string: Action=GetUser&UserName=testUser2&Version=2010-05-08 + headers: + User-Agent: paws/0.6.1 (R4.3.2; darwin20; aarch64) + Accept: application/xml + Content-Type: application/x-www-form-urlencoded; charset=utf-8 + Content-Length: '52' + X-Amz-Date: 20231207T000006Z + Authorization: redacted + response: + status: + status_code: 200 + category: Success + reason: OK + message: 'Success: (200) OK' + headers: + x-amzn-requestid: 1f4371af-0924-4b0e-877a-078d449764d6 + content-type: text/xml + content-length: '467' + date: Thu, 07 Dec 2023 00:00:06 GMT + body: + encoding: '' + file: no + string: | + + + + / + testUser2 + arn:aws:iam::510628056329:user/testUser2 + AIDAXNY6NZUEXZFJQI2I2 + 2023-08-08T20:27:04Z + + + + 1f4371af-0924-4b0e-877a-078d449764d6 + + + recorded_at: 2023-12-07 00:00:07 GMT + recorded_with: vcr/1.2.2, webmockr/0.9.0 +- request: + method: post + uri: https://iam.amazonaws.com/ + body: + encoding: '' + string: Action=ListUserPolicies&UserName=testUser2&Version=2010-05-08 + headers: + User-Agent: paws/0.6.1 (R4.3.2; darwin20; aarch64) + Accept: application/xml + Content-Type: application/x-www-form-urlencoded; charset=utf-8 + Content-Length: '61' + X-Amz-Date: 20231207T000006Z + Authorization: redacted + response: + status: + status_code: 200 + category: Success + reason: OK + message: 'Success: (200) OK' + headers: + x-amzn-requestid: 61a8ccaa-b150-404a-ac25-210c72b0a4e9 + content-type: text/xml + content-length: '323' + date: Thu, 07 Dec 2023 00:00:06 GMT + body: + encoding: '' + file: no + string: | + + + false + + + + 61a8ccaa-b150-404a-ac25-210c72b0a4e9 + + + recorded_at: 2023-12-07 00:00:07 GMT + recorded_with: vcr/1.2.2, webmockr/0.9.0 +- request: + method: post + uri: https://iam.amazonaws.com/ + body: + encoding: '' + string: Action=ListAttachedUserPolicies&UserName=testUser2&Version=2010-05-08 + headers: + User-Agent: paws/0.6.1 (R4.3.2; darwin20; aarch64) + Accept: application/xml + Content-Type: application/x-www-form-urlencoded; charset=utf-8 + Content-Length: '69' + X-Amz-Date: 20231207T000006Z + Authorization: redacted + response: + status: + status_code: 200 + category: Success + reason: OK + message: 'Success: (200) OK' + headers: + x-amzn-requestid: ddff6e09-5605-4b24-adf2-b893661bacd0 + content-type: text/xml + content-length: '360' + date: Thu, 07 Dec 2023 00:00:06 GMT + body: + encoding: '' + file: no + string: | + + + false + + + + ddff6e09-5605-4b24-adf2-b893661bacd0 + + + recorded_at: 2023-12-07 00:00:07 GMT + recorded_with: vcr/1.2.2, webmockr/0.9.0 +- request: + method: post + uri: https://iam.amazonaws.com/ + body: + encoding: '' + string: Action=ListGroupsForUser&UserName=testUser2&Version=2010-05-08 + headers: + User-Agent: paws/0.6.1 (R4.3.2; darwin20; aarch64) + Accept: application/xml + Content-Type: application/x-www-form-urlencoded; charset=utf-8 + Content-Length: '62' + X-Amz-Date: 20231207T000007Z + Authorization: redacted + response: + status: + status_code: 200 + category: Success + reason: OK + message: 'Success: (200) OK' + headers: + x-amzn-requestid: 31a670b9-d038-465b-82fa-29ce1d6b33a6 + content-type: text/xml + content-length: '322' + date: Thu, 07 Dec 2023 00:00:06 GMT + body: + encoding: '' + file: no + string: | + + + false + + + + 31a670b9-d038-465b-82fa-29ce1d6b33a6 + + + recorded_at: 2023-12-07 00:00:07 GMT recorded_with: vcr/1.2.2, webmockr/0.9.0