anomalizer / ngx_aws_auth

nginx module to proxy to authenticated AWS services
BSD 2-Clause "Simplified" License
470 stars 143 forks source link

Credentials that required AWS_SESSION_TOKEN don't work. #26

Open mostrows2 opened 8 years ago

mostrows2 commented 8 years ago

I'm using temporary credentials acquired via "assume role". I need to include AWS_SESSION_TOKEN as part of the credentials I use. This patch works for me.

0001-Support-optional-AWS_SESSION_TOKEN.patch.txt

anomalizer commented 8 years ago

The better way to fix this is my simply including all the x-amz- headers for signing

philsnow commented 7 years ago

@anomalizer can you be more specific with how you would prefer for this to be done? ngx_aws_auth__canonize_headers pieces together the x-amz- headers from its arguments.

I would like to see this issue fixed in master, but don't particularly care if the above patch is merged or something else is done instead.

bigkraig commented 7 years ago

👍

universam1 commented 6 years ago

@anomalizer do you have a solution for this already? I'm facing this problem as well.

asottile commented 6 years ago

I've revived this patch and can confirm it works: https://github.com/asottile/ngx_aws_auth/commit/768e8b6efec3a53b25ab7317ab49048a24766f81

I'm seeding this information using the aws metadata service:

URL = 'http://169.254.169.254/latest/meta-data/iam/security-credentials/{}'
TMPL = '''\
daemon off;
pid {pidfile};
error_log /dev/stdout;
worker_processes 4;
events {{
    worker_connections 1024;
}}

http {{
    access_log /dev/stdout;

    server {{
        listen 8000;

        aws_access_key {access_key};
        aws_key_scope {scope};
        aws_security_token {token};
        aws_signing_key {key};

        location / {{
            aws_s3_bucket ...;
            aws_sign;
            proxy_pass https://....s3.amazonaws.com;
        }}
    }}
}}
'''

# https://github.com/anomalizer/ngx_aws_auth/blob/master/generate_signing_key
def scope_and_signature(secret_key: str) -> Tuple[str, str]:
    k = f'AWS4{secret_key}'.encode()
    dt = datetime.datetime.utcnow().date().strftime('%Y%m%d')
    scope = f'{dt}/us-east-1/s3/aws4_request'
    for v in scope.split('/'):
        k = hmac.new(k, v.encode(), hashlib.sha256).digest()
    return scope, base64.b64encode(k).decode()

def main(argv: Optional[Sequence[str]] = None) -> int:
    ...
    role_name, _, _ = os.environ['IAM_ROLE'].partition('@')
    resp = json.loads(urllib.request.urlopen(URL.format(role_name)).read())

    access_key, token = resp['AccessKeyId'], resp['Token']
    scope, key = scope_and_signature(resp['SecretAccessKey'])

    cfg = TMPL.format(
        pidfile=args.pidfile,
        access_key=access_key, scope=scope, key=key, token=token,
    )

    ...