Skip to content

Commit

Permalink
Docs & polishing
Browse files Browse the repository at this point in the history
  • Loading branch information
hadley committed Oct 23, 2024
1 parent 430de54 commit 9b2a2d1
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 18 deletions.
43 changes: 29 additions & 14 deletions R/req-auth-aws.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@

#' Sign a request with the AWS SigV4 signing protocol
#'
#' This is a custom auth protocol implemented by AWS.
#'
#' @inheritParams req_perform
#' @param aws_access_key_id,aws_secret_access_key AWS key and secret.
#' @param aws_session_token AWS session token, if required.
#' @param aws_service,aws_region The AWS service and region to use for the
#' request. If not supplied, will be automatically parsed from the URL
#' hostname.
#' @examples
#' creds <- paws.common::locate_credentials("bedrock")
#' @examplesIf httr2:::has_paws_credentials()
#' creds <- paws.common::locate_credentials()
#' model_id <- "anthropic.claude-3-5-sonnet-20240620-v1:0"
#' req <- request("https://bedrock-runtime.us-east-1.amazonaws.com")
#' # https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html
Expand All @@ -22,25 +28,21 @@
#' )
#' resp <- req_perform_connection(req)
#' str(resp_body_json(resp))
#'
# https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html
req_auth_aws_v4 <- function(req,
aws_access_key_id,
aws_secret_access_key,
aws_session_token = NULL,
aws_service = NULL,
aws_region = NULL,
current_time = Sys.time()) {
aws_access_key_id,
aws_secret_access_key,
aws_session_token = NULL,
aws_service = NULL,
aws_region = NULL) {

check_request(req)
check_string(aws_access_key_id)
check_string(aws_secret_access_key)
check_string(aws_session_token, allow_null = TRUE)
check_string(aws_service, allow_null = TRUE)
check_string(aws_region, allow_null = TRUE)
if (length(current_time) != 1 || !inherits(current_time, "POSIXct")) {
stop_input_type(current_time, "a single POSIXct")
}

current_time <- Sys.time()

Check warning on line 45 in R/req-auth-aws.R

View check run for this annotation

Codecov / codecov/patch

R/req-auth-aws.R#L45

Added line #L45 was not covered by tests

body_sha256 <- openssl::sha256(req_body_get(req))

Check warning on line 47 in R/req-auth-aws.R

View check run for this annotation

Codecov / codecov/patch

R/req-auth-aws.R#L47

Added line #L47 was not covered by tests

Expand Down Expand Up @@ -76,6 +78,7 @@ req_aws_headers <- function(req, current_time, aws_session_token, body_sha256) {
)

Check warning on line 78 in R/req-auth-aws.R

View check run for this annotation

Codecov / codecov/patch

R/req-auth-aws.R#L74-L78

Added lines #L74 - L78 were not covered by tests
}

# https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-create-signed-request.html
aws_v4_signature <- function(method,
url,
headers,
Expand Down Expand Up @@ -177,3 +180,15 @@ aws_v4_signature <- function(method,
hmac_sha256 <- function(key, value) {
openssl::sha256(charToRaw(value), key)
}

has_paws_credentials <- function() {
tryCatch(
{
paws.common::locate_credentials()
TRUE

Check warning on line 188 in R/req-auth-aws.R

View check run for this annotation

Codecov / codecov/patch

R/req-auth-aws.R#L188

Added line #L188 was not covered by tests
},
error = function(e) {
FALSE
}
)
}
52 changes: 52 additions & 0 deletions man/req_auth_aws_v4.Rd

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

28 changes: 28 additions & 0 deletions tests/testthat/_snaps/req-auth-aws.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# validates its inputs

Code
req_auth_aws_v4(1)
Condition
Error in `req_auth_aws_v4()`:
! `req` must be an HTTP request object, not the number 1.
Code
req_auth_aws_v4(req, 1)
Condition
Error in `req_auth_aws_v4()`:
! `aws_access_key_id` must be a single string, not the number 1.
Code
req_auth_aws_v4(req, "", "", aws_session_token = 1)
Condition
Error in `req_auth_aws_v4()`:
! `aws_session_token` must be a single string or `NULL`, not the number 1.
Code
req_auth_aws_v4(req, "", "", aws_service = 1)
Condition
Error in `req_auth_aws_v4()`:
! `aws_service` must be a single string or `NULL`, not the number 1.
Code
req_auth_aws_v4(req, "", "", aws_region = 1)
Condition
Error in `req_auth_aws_v4()`:
! `aws_region` must be a single string or `NULL`, not the number 1.

18 changes: 14 additions & 4 deletions tests/testthat/test-req-auth-aws.R
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
test_that("can correctly sign a request", {
tryCatch(
creds <- paws.common::locate_credentials(),
error = function(cnd) skip("Can't locate AWS credentials")
)
skip_if_not(has_paws_credentials())
creds <- paws.common::locate_credentials()


# https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html
req <- request("https://sts.amazonaws.com/")
Expand Down Expand Up @@ -48,3 +47,14 @@ test_that("signing agrees with glacier example", {

expect_equal(signature_pieces, known_signature)
})

test_that("validates its inputs", {
req <- request("https://sts.amazonaws.com/")
expect_snapshot(error = TRUE, {
req_auth_aws_v4(1)
req_auth_aws_v4(req, 1)
req_auth_aws_v4(req, "", "", aws_session_token = 1)
req_auth_aws_v4(req, "", "", aws_service = 1)
req_auth_aws_v4(req, "", "", aws_region = 1)
})
})

0 comments on commit 9b2a2d1

Please sign in to comment.