Skip to content

Commit

Permalink
users and policy changes
Browse files Browse the repository at this point in the history
- users: add aws_user_add_to_rds fxn to give a user IAM access to an RDS database - not working yet!
- policies: add two fxns for policy create and create a policy document
- a few helper fxns added for stop if and stop if not
  • Loading branch information
sckott committed Feb 27, 2024
1 parent 080d8bc commit de0d397
Show file tree
Hide file tree
Showing 14 changed files with 311 additions and 0 deletions.
6 changes: 6 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ export(aws_iam_client)
export(aws_policies)
export(aws_policy)
export(aws_policy_attach)
export(aws_policy_create)
export(aws_policy_detach)
export(aws_policy_document_create)
export(aws_policy_exists)
export(aws_role)
export(aws_role_create)
Expand All @@ -52,6 +54,7 @@ export(aws_secrets_update)
export(aws_user)
export(aws_user_access_key)
export(aws_user_add_to_group)
export(aws_user_add_to_rds)
export(aws_user_create)
export(aws_user_current)
export(aws_user_delete)
Expand All @@ -75,8 +78,11 @@ importFrom(cli,cli_progress_update)
importFrom(cli,pb_spin)
importFrom(dplyr,bind_rows)
importFrom(dplyr,filter)
importFrom(dplyr,last_col)
importFrom(dplyr,mutate)
importFrom(dplyr,pull)
importFrom(dplyr,relocate)
importFrom(dplyr,select)
importFrom(fs,file_exists)
importFrom(fs,fs_bytes)
importFrom(glue,glue)
Expand Down
6 changes: 6 additions & 0 deletions R/globals.R
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
# Generated by roxyglobals: do not edit by hand

utils::globalVariables(c(
"DBInstanceArn", # <aws_db_rds_list>
".", # <aws_group>
".", # <aws_policy>
"PolicyName", # <as_policy_arn>
"Arn", # <as_policy_arn>
".", # <aws_role>
".", # <aws_secrets_all>
"arn", # <aws_secrets_all>
"created_date", # <aws_secrets_all>
"secret_raw", # <aws_secrets_rotate>
"secret_str", # <aws_secrets_rotate>
"PasswordLastUsed", # <user_list_tidy>
"DBInstanceIdentifier", # <aws_user_add_to_rds>
"arn", # <aws_user_add_to_rds>
"CreateDate", # <tidy_generator>
"IpPermissions", # <security_group_handler>
NULL
Expand Down
81 changes: 81 additions & 0 deletions R/policies.R
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,87 @@ aws_policy_exists <- function(name) {
!is.null(purrr::safely(aws_policy)(name)$result)
}

#' Create a policy
#'
#' @export
#' @param name (character) a policy name. required
#' @param document (character) the policy document you want to use
#' as the content for the new policy. required.
#' @param path (character) the path for the policy. if not given
#' default is "/". optional
#' @param description (character) a friendly description of the policy.
#' optional. cannot be changed after assigning it
#' @param tags (character) a vector of tags that you want to attach to
#' the new IAM policy. Each tag consists of a key name and an associated
#' value. optional
#' @return a tibble with policy details
#' @details see docs <https://www.paws-r-sdk.com/docs/iam_create_policy/>
#' @family policies
#' @examples \dontrun{
#' aws_db_rds_list()
#' aws_policy_document_create()
#' aws_policy_create("RdsAllow", document = doc)
#' }
aws_policy_create <- function(name, document, path = NULL,
description = NULL, tags = NULL) {

Check warning on line 99 in R/policies.R

View workflow job for this annotation

GitHub Actions / lint

file=R/policies.R,line=99,col=2,[indentation_linter] Hanging indent should be 30 spaces but is 2 spaces.
env64$iam$create_policy(
PolicyName = name,
PolicyDocument = document,
Path = path,
Description = description,
Tags = tags
)
}

#' Create a policy document
#'
#' @export
#' @param region (character) the AWS Region for the DB instance. length==1
#' @param account_id (character) the AWS account number for the DB instance.
#' length==1. The user must be in the same account as the account for the
#' DB instance
#' @param resource_id (character) the identifier for the DB instance. length==1
#' @param user (character) a user name that has an IAM account. length>=1
#' @param effect (character) valid values: "Allow" (default), "Deny". length==1
#' @param ... named args passed to [jsonlite::toJSON()]
#' @references #no lint start
#' https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements.html

Check warning on line 121 in R/policies.R

View workflow job for this annotation

GitHub Actions / lint

file=R/policies.R,line=121,col=81,[line_length_linter] Lines should not be more than 80 characters. This line is 84 characters.
#' #no lint end
#' @return a json class string. use [as.character()] to coerce to a regular
#' string
#' @note a few document items are hard-coded:
#' - `Version` is set to 2012-10-17"
#' - `Action` is set to "rds-db:connect"
#' @examplesIf interactive()
#' ### DB account = user in a database that has access to it
#' # all DB instances & DB accounts for a AWS account and AWS Region
#' aws_policy_document_create("us-east-2", "1234567890", "*", "*")
#' # all DB instances for a AWS account and AWS Region, single DB account
#' aws_policy_document_create("us-east-2", "1234567890", "*", "jane_doe")
#' # single DB instasnce, single DB account
#' aws_policy_document_create("us-east-2",
#' "1234567890", "db-ABCDEFGHIJKL01234", "jane_doe")
#' # single DB instance, many users
#' aws_policy_document_create("us-east-2", "1234567890",
#' "db-ABCDEFGHIJKL01234", c("jane_doe", "mary_roe"))
aws_policy_document_create <- function(region, account_id, resource_id, user,
effect = "Allow", ...) {

Check warning on line 141 in R/policies.R

View workflow job for this annotation

GitHub Actions / lint

file=R/policies.R,line=141,col=2,[indentation_linter] Hanging indent should be 39 spaces but is 2 spaces.

resource <- glue(
"arn:aws:rds-db:{region}:{account_id}:dbuser:{resource_id}/{user}")

Check warning on line 144 in R/policies.R

View workflow job for this annotation

GitHub Actions / lint

file=R/policies.R,line=144,col=4,[indentation_linter] Hanging indent should be 19 spaces but is 4 spaces.
doc <- list(
Version = "2012-10-17",
Statement = list(
list(
Effect = effect,
Action = "rds-db:connect",
Resource = resource
)
)
)
jsonlite::toJSON(doc, auto_unbox = TRUE, ...)
}

#' Convert a policy name to a policy ARN
#'
#' @export
Expand Down
68 changes: 68 additions & 0 deletions R/users.R
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,71 @@ aws_user_add_to_group <- function(username, groupname) {
env64$iam$add_user_to_group(groupname, username)
aws_user(username)
}

#' Grant a user access to an RDS database
#'
#' @export
#' @param user (character) an IAM username. required
#' @param id (character) instance identifier. required
#' @return xxx
#' @autoglobal
#' @examples \dontrun{
#' aws_user_add_to_rds(user = "sean", id = "bluebird")
#' }
aws_user_add_to_rds <- function(user, id) {
# error handling
checked_user <- check_aws_user(user)
stop_if(rlang::is_error(checked_user$error),
glue("user `{user}` does not exist"))

Check warning on line 199 in R/users.R

View workflow job for this annotation

GitHub Actions / lint

file=R/users.R,line=199,col=4,[indentation_linter] Hanging indent should be 10 spaces but is 4 spaces.
dbs <- aws_db_rds_list()
picked <- dplyr::filter(dbs, DBInstanceIdentifier == {{ id }})
stop_if_not(NROW(picked) > 0,
glue("database `{id}` does not exist"))

Check warning on line 203 in R/users.R

View workflow job for this annotation

GitHub Actions / lint

file=R/users.R,line=203,col=4,[indentation_linter] Hanging indent should be 14 spaces but is 4 spaces.

# policy handling
doc <- aws_policy_document_create(
picked$Region,
picked$AccountId,
picked$DbiResourceId,
user
)
policy_name <- glue("RdsAllow{id}{user}")
policy <- aws_policy_create(policy_name, doc)

Check warning on line 213 in R/users.R

View workflow job for this annotation

GitHub Actions / lint

file=R/users.R,line=213,col=3,[object_usage_linter] local variable 'policy' assigned but may not be used
invisible(aws_policies(refresh = TRUE)) # refresh policy data
checked_user$result %>% aws_policy_attach(policy_name)

# database user
current_user <- aws_user()

Check warning on line 218 in R/users.R

View workflow job for this annotation

GitHub Actions / lint

file=R/users.R,line=218,col=3,[object_usage_linter] local variable 'current_user' assigned but may not be used
# current_user$user$UserName
secrets <- aws_secrets_all()
sec <- dplyr::filter(secrets, grepl(id, arn))
if (NROW(sec) == 0) {
rlang::abort("no secrets found for current user and database")
}
if (NROW(sec) == 1) {
con <- aws_db_rds_con(sec$username, sec$password, id = id)
on.exit(DBI::dbDisconnect(con))
qry <- glue::glue_sql("
CREATE USER {`user`}
IDENTIFIED WITH AWSAuthenticationPlugin
AS 'RDS'",
.con = con
)
# DBI::dbSendQuery(con, qry)
res <- DBI::dbSendQuery(con, "CREATE USER ? IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS'")
DBI::dbBind(res, list(user))
DBI::dbFetch(res, n = 3)
DBI::dbClearResult(res)

query <- glue::glue_sql("CREATE USER {user} IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS'", .con = con)
out <- DBI::dbGetQuery(con, query)
# head(df, 3)

qry <- glue::glue("CREATE USER {user}
IDENTIFIED WITH AWSAuthenticationPlugin
AS 'RDS'")
out <- DBI::dbGetQuery(con, qry)
} else {
rlang::abort("more than one set of secrets found")
}
}
7 changes: 7 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,10 @@ is_class <- function(x, class) {
)
}
}

stop_if_not <- function(cond, msg) {
if (!cond) rlang::abort(msg)
}
stop_if <- function(cond, msg) {
if (cond) rlang::abort(msg)
}
1 change: 1 addition & 0 deletions man/as_policy_arn.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/aws_policies.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/aws_policy.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/aws_policy_attach.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions man/aws_policy_create.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/aws_policy_detach.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 63 additions & 0 deletions man/aws_policy_document_create.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/aws_policy_exists.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit de0d397

Please sign in to comment.