--- title: "Managing buckets in a small group of users" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Managing buckets in a small group of users} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- A common use case is to manage a small group of users and their access to AWS resources. This can be done using the `sixtyfour` package, which provides a set of high-level functions to make your life easier. ## Installation ``` r library(sixtyfour) library(purrr) ``` ## User groups First, create two user groups - `admin` and `users` - with the `six_admin_setup()` function. ``` r six_admin_setup(users_group = "myusers", admin_group = "myadmin") #> ℹ whoami: ***** #> ℹ #> ℹ myusers group created - add users to this group that do not require admin permissions #> ℹ Added policies to the myusers group: AmazonRDSReadOnlyAccess, AmazonRedshiftReadOnlyAccess, AmazonS3ReadOnlyAccess, #> AWSBillingReadOnlyAccess, and IAMReadOnlyAccess #> ℹ #> ℹ myadmin group created - add users to this group that require admin permissions #> ℹ Added policies to the myadmin group: AdministratorAccess, Billing, CostOptimizationHubAdminAccess, AWSBillingReadOnlyAccess, and #> AWSCostAndUsageReportAutomationPolicy #> ℹ #> ℹ Done! ``` ## Users Next, create five users - one in the `admin` group, three in the `users` group, and one not in either group. The admin user: ``` r name_admin <- random_user() user_admin <- six_user_create(name_admin, copy_to_cb = FALSE) #> ℹ Added policy UserInfo to SleepySubsidy #> ✔ Key pair created for SleepySubsidy #> ℹ AccessKeyId: ***** #> ℹ SecretAccessKey: ***** aws_user_add_to_group(name_admin, "myadmin") ``` The non-admin users: ``` r users_non_admin <- map(1:3, \(x) { six_user_create(random_user(), copy_to_cb = FALSE) }) #> ℹ Added policy UserInfo to NoncommercialPub #> ✔ Key pair created for NoncommercialPub #> ℹ AccessKeyId: ***** #> ℹ SecretAccessKey: ***** #> ℹ Added policy UserInfo to BridgedSomewhere #> ✔ Key pair created for BridgedSomewhere #> ℹ AccessKeyId: ***** #> ℹ SecretAccessKey: ***** #> ℹ Added policy UserInfo to DoctrinalSeating #> ✔ Key pair created for DoctrinalSeating #> ℹ AccessKeyId: ***** #> ℹ SecretAccessKey: ***** invisible(map(users_non_admin, \(x) { aws_user_add_to_group(x$UserName, "myusers") })) names_users <- map_chr(users_non_admin, \(x) x$UserName) ``` And last, create a user that is not part of either of the above groups. ``` r name_user_wo <- random_user() user_wo_access <- six_user_create(name_user_wo, copy_to_cb = FALSE) #> ℹ Added policy UserInfo to BrimmingAviation #> ✔ Key pair created for BrimmingAviation #> ℹ AccessKeyId: ***** #> ℹ SecretAccessKey: ***** ``` ## Buckets and files Create a bucket, and put a file in it. ``` r bucket <- random_bucket() demo_rds_file <- file.path(system.file(), "Meta/demo.rds") six_bucket_upload(path = demo_rds_file, remote = bucket, force = TRUE) #> [1] "s3://bucket-cuwgyafqtleomkhd/demo.rds" ``` ## Check access Then check access for the user that should not have access ``` r withr::with_envvar( c("AWS_REGION" = user_wo_access$AwsRegion, "AWS_ACCESS_KEY_ID" = user_wo_access$AccessKeyId, "AWS_SECRET_ACCESS_KEY" = user_wo_access$SecretAccessKey ), aws_bucket_list_objects(bucket) ) #> Error: AccessDenied (HTTP 403). User: arn:aws:iam::*****:user/BrimmingAviation is not authorized to perform: s3:ListBucket on resource: "arn:aws:s3:::bucket-cuwgyafqtleomkhd" because no identity-based policy allows the s3:ListBucket action ``` User BrimmingAviation does not have access (read or write), as intended. Then check access for a user that should have read access and NOT write access: ``` r # Read withr::with_envvar( c("AWS_REGION" = users_non_admin[[1]]$AwsRegion, "AWS_ACCESS_KEY_ID" = users_non_admin[[1]]$AccessKeyId, "AWS_SECRET_ACCESS_KEY" = users_non_admin[[1]]$SecretAccessKey ), { aws_bucket_list_objects(bucket) } ) #> # A tibble: 1 × 8 #> bucket key uri size type etag lastmodified storageclass #> #> 1 bucket-cuwgyaf… demo… s3:/… 256 file "\"7… 2025-03-12 22:51:04 STANDARD ``` ``` r # Write withr::with_envvar( c("AWS_REGION" = users_non_admin[[1]]$AwsRegion, "AWS_ACCESS_KEY_ID" = users_non_admin[[1]]$AccessKeyId, "AWS_SECRET_ACCESS_KEY" = users_non_admin[[1]]$SecretAccessKey ), { links_rds_file <- file.path(system.file(), "Meta/links.rds") six_bucket_upload(path = links_rds_file, remote = bucket, force = TRUE) } ) #> Error in `map()`: #> ℹ In index: 1. #> Caused by error: #> ! AccessDenied (HTTP 403). User: arn:aws:iam::*****:user/NoncommercialPub is not authorized to perform: s3:PutObject on resource: "arn:aws:s3:::bucket-cuwgyafqtleomkhd/links.rds" because no identity-based policy allows the s3:PutObject action ``` User NoncommercialPub does have access for read and NOT for write, as intended. And make sure the admin has read and write access ``` r # Read withr::with_envvar( c("AWS_REGION" = user_admin$AwsRegion, "AWS_ACCESS_KEY_ID" = user_admin$AccessKeyId, "AWS_SECRET_ACCESS_KEY" = user_admin$SecretAccessKey ), { aws_bucket_list_objects(bucket) } ) #> # A tibble: 1 × 8 #> bucket key uri size type etag lastmodified storageclass #> #> 1 bucket-cuwgyaf… demo… s3:/… 256 file "\"7… 2025-03-12 22:51:04 STANDARD ``` ``` r # Write withr::with_envvar( c("AWS_REGION" = user_admin$AwsRegion, "AWS_ACCESS_KEY_ID" = user_admin$AccessKeyId, "AWS_SECRET_ACCESS_KEY" = user_admin$SecretAccessKey ), { links_rds_file <- file.path(system.file(), "Meta/links.rds") six_bucket_upload(path = links_rds_file, remote = bucket, force = TRUE) } ) #> [1] "s3://bucket-cuwgyafqtleomkhd/links.rds" ``` User SleepySubsidy DOES have access for read and write, as intended. ## Cleanup Then cleanup the users, groups and buckets: ``` r # Users map(c(name_admin, names_users, name_user_wo), six_user_delete) # Groups map(c("myadmin", "myusers"), six_group_delete) # Bucket six_bucket_delete(bucket, force = TRUE) ```