2

Our company has software stored in folders in an Amazon S3 bucket, this software needs to be downloaded by third party companies. We want to be able to control access to the software by giving out a URL.

I've looked into pre-signed URLs however they expire which is no good because the third parties need permanent access.

Below is a link to a different question in stack overflow: How secure are Amazon AWS Access keys?

The poster (AyKarsi) is using the URL - https://mywebsite.s3.amazonaws.com/40.pdf?AWSAccessKeyId=[my access key]&Expires=1433297453&Signature=[this random set of numbers]

His question is sort of answered by Tom Andersen. I tired to flow Tom's steps without the URL expiring:

First I created an IAM User and attached a permissions policy with the following:

{
"Version": "2012-10-17",
  "Statement": [
    {
        "Sid": "Stmt14350*******0",
        "Effect": "Allow",
        "Action": [
            "s3:ListBucket", 
            "GetObject"
        ],
        "Resource": [
            "arn:aws:s3:::bucket-name/folder-name/*"
        ]
    }
  ]
}

I then took the access key for this user and placed it in the following URL: https://s3.amazonaws.com/bucket-name/folder-name/file-name.msi?AWSAccessKeyId=AKIAJO4RIDGETCCAH55Q

Unfortunately this just returns the error code Access Denied:

<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>8B394885E81B29A7</RequestId>
<HostId>fpaNduIOIkWGetgWECQMI/mm5rL2GpJ+6P+P5En0LODJDpKWrUwYn+dXbqvgFrb4
</HostId>
</Error>

What is wrong with my method above? Is it possible to do it this way? Finally what method would you use?

Community
  • 1
  • 1
Pop2DTop
  • 23
  • 2

1 Answers1

2

What is wrong with my method above?

I think you may have oversimplified the answer to the other question. The point was that, let's say you have an IAM user with permission to write to a bucket. When generating signed URLs, don't use that privileged user's credentials to sign publicly-distributed links. Instead, create a different IAM user with only read permissions, and use the less-privileged user's credentials when generating the signed URL.

Your solution is simple, assuming you have some kind of site, a web application that authorized users log in to. If that's true, then you create a "download here" link that hits an endpoint in your web application, which checks the user's credentials, and if the download is authorized, sign a URL with a short expiration time, and redirect the browser to the signed URL with an HTTP 302 redirect.

If you don't have that, then another option is a setup where you assign long, opaque URLs (e.g. https://example.com/download/aoHxT9x88e1TTrID9VepHfjovG3TtN2iTQLU4N6B/filename.msi) where valid combinations are computationally infeasible to guess, giving each user a unique link ... along with a back-end system which based on the validity of such a string, will either fetch and return (proxy) the download from S3 or will generate a signed URL with a short expiration time, and redirect the requester.

Note that in the above example, that's not a path to a copy of the file, it just gives that appearance. I have a system that operates like this, storing the "token" (the random string of digits, which has absolutely no meaning, it only maps to a file and an authorized user, all of which is stored in the database, not embedded in the URL) for each authorized download in the database, looking it up with each incoming request, and deciding based on what it finds, whether to redirect or to deny the request (after a delay) with a 404.

There's no simple and obvious way to do what you want with "just" S3.

Michael - sqlbot
  • 169,571
  • 25
  • 353
  • 427