aws.signature
aws.signature copied to clipboard
Generate a AWS predesigned URL with signature_v4_auth ?
Please specify whether your issue is about:
- [ ] a possible bug
- [x] a question about package functionality
- [ ] a suggested code or documentation change, improvement to the code, or feature request
Hello. I'm trying to generate a resigned URL using signature_v4_auth
. This was inspired by this. I add to make some changes according to the documentation, and use URLencode
a few times to make sure it matches what AWS is providing me with when I manually generate a presigned URL for the same test object.
Regardless of the change I do, I always get a signature mismatch. I've tried signing the body, or not.
I'm a little confused when I look at this documentation page. I'm not seeing the UNSIGNED-PAYLOAD
anywhere in the code, and so as a result using their parameter I do not end up with the same signature. In my signature$CanonicalRequest
I have the body hash instead.
My code so far:
get_aws_signed_url <- function(file,
bucket = "my_bucket_name",
timeout_seconds = 30,
key = "my_key",
secret = "my_secret",
token = "my_token",
region = "us-east-1") {
# API Implmented according to https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html#query-string-auth-v4-signing-example
algorithm <- "AWS4-HMAC-SHA256"
time <- Sys.time()
date_time <- format(time, "%Y%m%dT%H%M%SZ", tz = "UTC")
# Build query parameters
date <- glue::glue("/{format(time,'%Y%m%d', tz = 'UTC')}/") %>%
URLencode(reserved = TRUE)
region_encoded <- glue::glue("{region}/") %>% URLencode(reserved = TRUE)
amzn <- "s3/aws4_request" %>% URLencode(reserved = TRUE)
# Query parameters, this portion is implemented with the help of https://github.com/cloudyr/aws.s3/blob/master/R/s3HTTP.R
request_body <- ""
body_hash <- tolower(digest::digest(request_body,
file = is.character(request_body) &&
file.exists(request_body),
algo = "sha256", serialize = FALSE))
signature <- aws.signature::signature_v4_auth(datetime = date_time,
region = region,
service = "s3",
verb = "GET",
action = glue::glue("/{file}"),
key = key,
secret = secret,
session_token = URLencode(token, reserved = TRUE),
request_body = "",
signed_body = TRUE,
query_args = list(`X-Amz-Algorithm` = algorithm,
`X-Amz-Credential` = glue::glue("{key}{date}{region_encoded}{amzn}"),
`X-Amz-Date` = date_time,
`X-Amz-Expires` = timeout_seconds,
`X-Amz-SignedHeaders` = "host",
`x-amz-content-sha256` = body_hash
),
algorithm = algorithm,
canonical_headers = list(host = glue("{bucket}.s3.amazonaws.com")),
force_credentials = TRUE)
return(glue::glue("https://{bucket}.s3.{region}.amazonaws.com/{file}?X-Amz-Algorithm={signature$Query$`X-Amz-Algorithm`}&X-Amz-Credential={signature$Query$`X-Amz-Credential`}&X-Amz-Date={signature$Query$`X-Amz-Date`}&X-Amz-Expires={signature$Query$`X-Amz-Expires`}&X-Amz-SignedHeaders={signature$Query$`X-Amz-SignedHeaders`}&X-Amz-Signature={signature$Signature}&X-Amz-Security-Token={signature$SessionToken}&x-amz-content-sha256={signature$Query$`x-amz-content-sha256`}"))
}
## session info
> sessionInfo()
R version 4.2.1 (2022-06-23)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.1
Matrix products: default
LAPACK: /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] tictoc_1.0.1 glue_1.6.2 aws.signature_0.6.0 aws.s3_0.3.21 viridis_0.6.2 viridisLite_0.4.0
[7] DataExplorer_0.8.2 gt_0.6.0 DT_0.23 reactlog_1.1.0 shinydashboardPlus_2.0.3 shinycssloaders_1.0.0
[13] vroom_1.6.0 patchwork_1.1.1 rebus_0.1-3 forcats_0.5.1 stringr_1.4.0 dplyr_1.0.9
[19] purrr_0.3.4 readr_2.1.2 tidyr_1.2.0 tibble_3.1.8 tidyverse_1.3.1 shinyWidgets_0.7.5
[25] plotly_4.10.0 ggplot2_3.4.0 shinyjs_2.1.0 shinydashboard_0.7.2 shiny_1.7.1
loaded via a namespace (and not attached):
[1] colorspace_2.0-3 ellipsis_0.3.2 rprojroot_2.0.3 base64enc_0.1-3 fs_1.5.2 rstudioapi_0.14 farver_2.1.0
[8] bit64_4.0.5 fansi_1.0.3 lubridate_1.8.0 xml2_1.3.3 cachem_1.0.6 knitr_1.39 jsonlite_1.8.2
[15] broom_1.0.1 dbplyr_2.1.1 png_0.1-8 RAthena_2.6.0 compiler_4.2.1 httr_1.4.2 backports_1.4.1
[22] assertthat_0.2.1 Matrix_1.4-1 fastmap_1.1.0 lazyeval_0.2.2 cli_3.4.1 later_1.3.0 htmltools_0.5.3
[29] tools_4.2.1 igraph_1.3.2 gtable_0.3.0 rebus.base_0.0-3 Rcpp_1.0.9 cellranger_1.1.0 jquerylib_0.1.3
[36] vctrs_0.5.1 crosstalk_1.1.1 xfun_0.31 networkD3_0.4 rebus.datetimes_0.0-1 rvest_1.0.1 mime_0.12
[43] lifecycle_1.0.3 rebus.numbers_0.0-1 scales_1.2.1 hms_1.0.0 promises_1.2.0.1 parallel_4.2.1 yaml_2.3.5
[50] curl_4.3.2 reticulate_1.26 gridExtra_2.3 sass_0.4.1 stringi_1.7.6 checkmate_2.1.0 rlang_1.0.6
[57] pkgconfig_2.0.3 evaluate_0.15 lattice_0.20-45 fontawesome_0.4.0 labeling_0.4.2 htmlwidgets_1.5.4 bit_4.0.4
[64] tidyselect_1.1.2 here_1.0.1 magrittr_2.0.3 R6_2.5.1 generics_0.1.0 DBI_1.1.3 pillar_1.8.1
[71] haven_2.5.0 withr_2.5.0 rebus.unicode_0.0-2 modelr_0.1.8 crayon_1.4.1 utf8_1.2.2 tzdb_0.3.0
[78] rmarkdown_2.14 grid_4.2.1 readxl_1.4.0 data.table_1.14.2 reprex_2.0.1 digest_0.6.29 xtable_1.8-4
[85] httpuv_1.6.5 arrow_10.0.0 munsell_0.5.0 bslib_0.3.1
I somehow feel that some things in there could/should be simplified - like I have to manually generate the credentials, because signature$Credential
is not encoded properly, or I'm getting this completely backward. Apologies if that's the case.
Thanks ahead of time for the clarifications.