ThouCheese / cloud-storage-rs

A crate for uploading files to Google cloud storage, and for generating download urls.
MIT License
123 stars 88 forks source link

Allow custom signed headers in Signed URLs #130

Open bluelhf opened 1 year ago

bluelhf commented 1 year ago

Support for custom signed headers in Signed URLs would allow, for example, limiting the file size of an upload by specifying a signed Content-Length value :)

ollyde commented 9 months ago

Also required @ThouCheese without this users can upload 5TB files openly..

bluelhf commented 9 months ago

Also required @ThouCheese without this users can upload 5TB files openly..

For now, the google-cloud-storage crate supports signed headers :)

ollyde commented 9 months ago

@bluelhf any example? Can't seem to find one with signed headers

ollyde commented 9 months ago

@bluelhf I try this for example, but it doesn't work, it's ignored.

 // We have to use two differnt libs to create the signed url and upload the file
    let url_for_upload = get_storage_client()
        .await?
        .signed_url(
            env_vars().google_cloud_storage_bucket.as_str(),
            name_of_file.as_str(),
            None,
            None,
            SignedURLOptions {
                method: SignedURLMethod::PUT,
                // Max size
                headers: vec!["content-length;24".to_string()],
                ..Default::default()
            },
        )
        .await
        .map_err(|op| {
            eprintln!("Error creating signed url: {0:?}", op);
            ApiError {
                status: "issue-creating-signed-url".to_string(),
                message: "Error creating signed url".to_string(),
            }
        })?;
ollyde commented 9 months ago

@bluelhf there is no way to put content length on google_cloud_storage looking at the source code.

bluelhf commented 9 months ago

@bluelhf there is no way to put content length on google_cloud_storage looking at the source code.

I am using it in my own code like this:

        let uuid = Uuid::new_v4();

        let url = self.client.signed_url(
            &self.bucket_name,
            &uuid.to_string(),
            None, None, SignedURLOptions {
                method: SignedURLMethod::PUT,
                headers: vec![format!("Content-Length: {length}")],
                expires: Duration::from_secs(1800),
                ..Default::default()
            }
        ).await?;

        Ok(UploadHandle { url, uuid })

(from here)

ollyde commented 9 months ago

@bluelhf that only 'allows' client side headers on request which means users can still upload 5TB files to you service. It does not enforce a file size limit.

ollyde commented 9 months ago

@bluelhf just try it, set the content size really low, then upload a larger file with the url. Nothing will happen or reject. Very dangerous to allow that.

bluelhf commented 9 months ago

@bluelhf just try it, set the content size really low, then upload a larger file with the url. Nothing will happen or reject. Very dangerous to allow that.

I remember trying it and the request getting rejected after the file exceeded the reported size. Maybe I'm misremembering though, I'll have to try

ollyde commented 9 months ago

@bluelhf I just tried it before, it wasn't working as intended. I could upload files way past the content length.