11/* Copyright (C) 2020 NooBaa */
2- /*eslint max-lines: ["error", 2200 ]*/
2+ /*eslint max-lines: ["error", 2500 ]*/
33/*eslint max-lines-per-function: ["error", 1300]*/
44/*eslint max-statements: ["error", 80, { "ignoreTopLevelFunctions": true }]*/
55'use strict' ;
@@ -12,10 +12,16 @@ const util = require('util');
1212const http = require ( 'http' ) ;
1313const mocha = require ( 'mocha' ) ;
1414const assert = require ( 'assert' ) ;
15+ const http_utils = require ( '../../util/http_utils' ) ;
1516const config = require ( '../../../config' ) ;
1617const fs_utils = require ( '../../util/fs_utils' ) ;
17- const { stat, open } = require ( '../../util/nb_native' ) ( ) . fs ;
18+ const fetch = require ( 'node-fetch' ) ;
19+ const P = require ( '../../util/promise' ) ;
20+ const cloud_utils = require ( '../../util/cloud_utils' ) ;
21+ const SensitiveString = require ( '../../util/sensitive_string' ) ;
22+ const S3Error = require ( '../../../src/endpoint/s3/s3_errors' ) . S3Error ;
1823const test_utils = require ( '../system_tests/test_utils' ) ;
24+ const { stat, open } = require ( '../../util/nb_native' ) ( ) . fs ;
1925const { get_process_fs_context } = require ( '../../util/native_fs_utils' ) ;
2026const { TYPES } = require ( '../../manage_nsfs/manage_nsfs_constants' ) ;
2127const ManageCLIError = require ( '../../manage_nsfs/manage_nsfs_cli_errors' ) . ManageCLIError ;
@@ -1848,3 +1854,140 @@ async function update_account_nsfs_config(email, default_resource, new_nsfs_acco
18481854 }
18491855}
18501856
1857+ mocha . describe ( 'Presigned URL tests' , function ( ) {
1858+ this . timeout ( 50000 ) ; // eslint-disable-line no-invalid-this
1859+ const nsr = 'presigned_url_nsr' ;
1860+ const account_name = 'presigned_url_account' ;
1861+ const fs_path = path . join ( TMP_PATH , 'presigned_url_tests/' ) ;
1862+ const presigned_url_bucket = 'presigned-url-bucket' ;
1863+ const presigned_url_object = 'presigned-url-object.txt' ;
1864+ const presigned_body = 'presigned_body' ;
1865+ let s3_client ;
1866+ let access_key ;
1867+ let secret_key ;
1868+ CORETEST_ENDPOINT = coretest . get_http_address ( ) ;
1869+ let valid_default_presigned_url ;
1870+ let presigned_url_params ;
1871+
1872+ mocha . before ( async function ( ) {
1873+ await fs_utils . create_fresh_path ( fs_path ) ;
1874+ await rpc_client . pool . create_namespace_resource ( { name : nsr , nsfs_config : { fs_root_path : fs_path } } ) ;
1875+ const new_buckets_path = '/' ; // manual fix for 5.16/5.15 since we didn't backport the related test refactoring
1876+ const nsfs_account_config = {
1877+ uid : process . getuid ( ) , gid : process . getgid ( ) , new_buckets_path, nsfs_only : true
1878+ } ;
1879+ const account_params = { ...new_account_params , email : `${ account_name } @noobaa.io` , name : account_name , default_resource : nsr , nsfs_account_config } ;
1880+ const res = await rpc_client . account . create_account ( account_params ) ;
1881+ access_key = res . access_keys [ 0 ] . access_key ;
1882+ secret_key = res . access_keys [ 0 ] . secret_key ;
1883+ s3_client = generate_s3_client ( access_key . unwrap ( ) , secret_key . unwrap ( ) , CORETEST_ENDPOINT ) ;
1884+ await s3_client . createBucket ( { Bucket : presigned_url_bucket } ) ;
1885+ await s3_client . putObject ( { Bucket : presigned_url_bucket , Key : presigned_url_object , Body : presigned_body } ) ;
1886+
1887+ presigned_url_params = {
1888+ bucket : new SensitiveString ( presigned_url_bucket ) ,
1889+ key : presigned_url_object ,
1890+ endpoint : CORETEST_ENDPOINT ,
1891+ access_key : access_key ,
1892+ secret_key : secret_key
1893+ } ;
1894+ valid_default_presigned_url = cloud_utils . get_signed_url ( presigned_url_params ) ;
1895+ } ) ;
1896+
1897+ mocha . after ( async function ( ) {
1898+ if ( ! is_nc_coretest ) return ;
1899+ await s3_client . deleteObject ( { Bucket : presigned_url_bucket , Key : presigned_url_object } ) ;
1900+ await s3_client . deleteBucket ( { Bucket : presigned_url_bucket } ) ;
1901+ await rpc_client . account . delete_account ( { email : `${ account_name } @noobaa.io` } ) ;
1902+ await fs_utils . folder_delete ( fs_path ) ;
1903+ } ) ;
1904+
1905+ it ( 'fetch valid presigned URL - 604800 seconds - epoch expiry - should return object data' , async ( ) => {
1906+ const data = await fetchData ( valid_default_presigned_url ) ;
1907+ assert . equal ( data , presigned_body ) ;
1908+ } ) ;
1909+
1910+ it ( 'fetch valid presigned URL - 604800 seconds - should return object data - with valid date + expiry in seconds' , async ( ) => {
1911+ const now = new Date ( ) ;
1912+ const valid_url_with_date = valid_default_presigned_url + '&X-Amz-Date=' + now . toISOString ( ) + '&X-Amz-Expires=' + 604800 ;
1913+ const data = await fetchData ( valid_url_with_date ) ;
1914+ assert . equal ( data , presigned_body ) ;
1915+ } ) ;
1916+
1917+ it ( 'fetch invalid presigned URL - 604800 seconds - epoch expiry + with future date' , async ( ) => {
1918+ const now = new Date ( ) ;
1919+ // Add one hour (3600000 milliseconds)
1920+ const one_hour_in_ms = 60 * 60 * 1000 ;
1921+ const one_hour_from_now = new Date ( now . getTime ( ) + one_hour_in_ms ) ;
1922+ const future_presigned_url = valid_default_presigned_url + '&X-Amz-Date=' + one_hour_from_now . toISOString ( ) ;
1923+ const expected_err = new S3Error ( S3Error . RequestNotValidYet ) ;
1924+ await assert_throws_async ( fetchData ( future_presigned_url ) , expected_err . message ) ;
1925+ } ) ;
1926+
1927+ it ( 'fetch invalid presigned URL - 604800 expiry seconds + with future date' , async ( ) => {
1928+ const now = new Date ( ) ;
1929+ // Add one hour (3600000 milliseconds)
1930+ const one_hour_in_ms = 60 * 60 * 1000 ;
1931+ const one_hour_from_now = new Date ( now . getTime ( ) + one_hour_in_ms ) ;
1932+ const future_presigned_url = valid_default_presigned_url + '&X-Amz-Date=' + one_hour_from_now . toISOString ( ) + '&X-Amz-Expires=' + 604800 ;
1933+ const expected_err = new S3Error ( S3Error . RequestNotValidYet ) ;
1934+ await assert_throws_async ( fetchData ( future_presigned_url ) , expected_err . message ) ;
1935+ } ) ;
1936+
1937+ it ( 'fetch invalid presigned URL - 604800 seconds - epoch expiry - URL expired' , async ( ) => {
1938+ const expired_presigned_url = cloud_utils . get_signed_url ( presigned_url_params , 1 ) ;
1939+ // wait for 2 seconds before fetching the url
1940+ await P . delay ( 2000 ) ;
1941+ const expected_err = new S3Error ( S3Error . RequestExpired ) ;
1942+ await assert_throws_async ( fetchData ( expired_presigned_url ) , expected_err . message ) ;
1943+ } ) ;
1944+
1945+ it ( 'fetch invalid presigned URL - 604800 expiry seconds - URL expired' , async ( ) => {
1946+ const now = new Date ( ) ;
1947+ const expired_presigned_url = cloud_utils . get_signed_url ( presigned_url_params , 1 ) + '&X-Amz-Date=' + now . toISOString ( ) + '&X-Amz-Expires=' + 1 ;
1948+ // wait for 2 seconds before fetching the url
1949+ await P . delay ( 2000 ) ;
1950+ const expected_err = new S3Error ( S3Error . RequestExpired ) ;
1951+ await assert_throws_async ( fetchData ( expired_presigned_url ) , expected_err . message ) ;
1952+ } ) ;
1953+
1954+ it ( 'fetch invalid presigned URL - expiry expoch - expire in bigger than limit' , async ( ) => {
1955+ const invalid_expiry = 604800 + 10 ;
1956+ const invalid_expiry_presigned_url = cloud_utils . get_signed_url ( presigned_url_params , invalid_expiry ) ;
1957+ const expected_err = new S3Error ( S3Error . AuthorizationQueryParametersError ) ;
1958+ await assert_throws_async ( fetchData ( invalid_expiry_presigned_url ) , expected_err . message ) ;
1959+ } ) ;
1960+
1961+ it ( 'fetch invalid presigned URL - expire in bigger than limit' , async ( ) => {
1962+ const now = new Date ( ) ;
1963+ const invalid_expiry = 604800 + 10 ;
1964+ const invalid_expiry_presigned_url = cloud_utils . get_signed_url ( presigned_url_params , invalid_expiry ) + '&X-Amz-Date=' + now . toISOString ( ) + '&X-Amz-Expires=' + invalid_expiry ;
1965+ const expected_err = new S3Error ( S3Error . AuthorizationQueryParametersError ) ;
1966+ await assert_throws_async ( fetchData ( invalid_expiry_presigned_url ) , expected_err . message ) ;
1967+ } ) ;
1968+ } ) ;
1969+
1970+ async function fetchData ( presigned_url ) {
1971+ const response = await fetch ( presigned_url , { agent : new http . Agent ( { keepAlive : false } ) } ) ;
1972+ let data ;
1973+ if ( ! response . ok ) {
1974+ data = ( await response . text ( ) ) . trim ( ) ;
1975+ const err_json = ( await http_utils . parse_xml_to_js ( data ) ) . Error ;
1976+ const err = new Error ( err_json . Message ) ;
1977+ err . code = err_json . Code ;
1978+ throw err ;
1979+ }
1980+ data = await response . text ( ) ;
1981+ return data . trim ( ) ;
1982+ }
1983+
1984+ async function assert_throws_async ( promise , expected_message = 'Access Denied' ) {
1985+ try {
1986+ await promise ;
1987+ assert . fail ( 'Test was suppose to fail on ' + expected_message ) ;
1988+ } catch ( err ) {
1989+ if ( err . message !== expected_message ) {
1990+ throw err ;
1991+ }
1992+ }
1993+ }
0 commit comments