Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate a AWS predesigned URL with signature_v4_auth ? #66

Open
1 of 3 tasks
homer3018 opened this issue Dec 16, 2022 · 0 comments
Open
1 of 3 tasks

Generate a AWS predesigned URL with signature_v4_auth ? #66

homer3018 opened this issue Dec 16, 2022 · 0 comments

Comments

@homer3018
Copy link

homer3018 commented Dec 16, 2022

Please specify whether your issue is about:

  • a possible bug
  • 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant