getwilds / sixtyfour

🚚 CEO, entrepreneur
https://getwilds.org/sixtyfour/
Other
11 stars 1 forks source link

Simulate user #57

Open sckott opened 5 months ago

sckott commented 5 months ago

The code below was originally part of the https://github.com/getwilds/sixtyfour/pull/55 pull request, but was removed as it wasn't completely working and deemed not important enough to spend more time on now to make it work.

check_simulated_user was called as the last stop before finishing in six_admin_setup

#' Check if a user has access to an AWS service
#' @export
#' @param fun (funcction) a function. required
#' @param ... additional named args passed to `fun`
#' @return single boolean. checks [rlang::is_null()] against `$error` result of
#' call to [purrr::safely()]
#' @details really just a generic check that any function can run with
#' its inputs; not specific to AWS or any particular function
has_access <- function(fun, ...) {
  rlang::is_null(purrr::safely(fun, FALSE)(...)$error)
}

#' @importFrom dplyr any_of
check_simulated_user <- function(group) {
  rlang::check_installed("callr")
  cli_info("Checking that a simulated user can access {.strong {group}} group")
  randuser <- random_user()
  creds <- suppm(six_user_create(randuser))
  aws_user_add_to_group(randuser, group)

  creds_mapper <- c(
    "AWS_ACCESS_KEY_ID" = "AccessKeyId",
    "AWS_SECRET_ACCESS_KEY" = "SecretAccessKey",
    "AWS_REGION" = "AwsRegion"
  )
  creds_lst <- as_tibble(creds) %>%
    rename(any_of(creds_mapper)) %>%
    select(starts_with("AWS")) %>%
    as.list()

  all_checks <- callr::r(function(creds) {
    withr::with_envvar(
      creds,
      {
        check_iam <- sixtyfour::has_access(sixtyfour::aws_user)
        check_rds <- sixtyfour::has_access(sixtyfour::aws_db_instance_details)
        check_rs <- sixtyfour::has_access(sixtyfour::aws_db_cluster_details)
        check_s3 <- sixtyfour::has_access(sixtyfour::aws_buckets)
        check_bil <- sixtyfour::has_access(sixtyfour::aws_billing_raw,
          date_start = Sys.Date() - 1,
          metrics = "BlendedCost"
        )
        list(
          IAM = check_iam,
          RDS = check_rds,
          Redshift = check_rs,
          S3 = check_s3,
          Billing = check_bil
        )
      }
    )
  }, args = list(creds_lst))

  if (all(unlist(all_checks))) {
    cli_success("  All checks passed!")
  } else {
    cli_warning(c(
      "  At least one check didn't pass ",
      "({names(keep(all_checks, isFALSE))}) ",
      "try again or open an issue"
    ))
  }

  cli_info("  Cleaning up simulated user")
  aws_user_remove_from_group(randuser, group)
  suppm(six_user_delete(randuser))
  cli_alert_info("") # nolint
}

Notes

The parts that were not working:

six_admin_setup("uzers", "zadmin")
#> ℹ whoami: scott (account: 744061095407)
#> ℹ
#> ! uzers group NOT created - a uzers group already exists in your account
#> ℹ Not adding policies to the uzers group
#> ℹ
#> ! zadmin group NOT created - an zadmin group already exists in your account
#> ℹ Not adding policies to the zadmin group
#> ℹ
#> ℹ Checking that a simulated user can access uzers group
#> Error:
#> ! in callr subprocess.
#> Caused by error:
#> ! InvalidClientTokenId (HTTP 403). The security token included in the request is invalid.
#> Type .Last.error to see the more details.
#> 
#> :p .Last.error
#> <callr_error/rlib_error_3_0/rlib_error/error>
#> Error:
#> ! in callr subprocess.
#> Caused by error:
#> ! InvalidClientTokenId (HTTP 403). The security token included in the request is invalid.
#> ---
#> Backtrace:
#> 1. sixtyfour::six_admin_setup("uzers", "zadmin")
#> 2. sixtyfour:::check_simulated_user(users_group) at admin.R:113:3
#> 3. callr::r(function(creds) { … at admin.R:155:3
#> 4. callr:::get_result(output = out, options)
#> 5. callr:::throw(callr_remote_error(remerr, output), parent = fix_msg(remerr[[3]]))
#> ---
#> Subprocess backtrace:
#> 1. sixtyfour::aws_user()
#> 2. env64$iam$get_user(username)$User %>% list(.) %>% user_list_tidy()
#> 3. sixtyfour:::user_list_tidy(.)
#> 4. rlang::is_empty(x)
#> 5. env64$iam$get_user(username)
#> 6. paws.common::send_request(request)
#> 7. paws.common:::retry(request)
#> 8. paws.common:::run(request, retry)
#> 9. handler$fn(request)
#> 10. base::stop(error)
#> 11. global (function (e) …