maybe super basic questions but i don't really know how to do this. I had a service that was uploading files to s3 automatically using aws cli (babashka). Service was moved to k8 cluster and all was well. There was a request to stop using aws cli and start using aws-api https://github.com/cognitect-labs/aws-api/ (and make service jvm) After short port and testing of functionality locally - all is good but once it was deployed to k8 cluster put-object was failing because access was denied. After looking further i realized that that credentials are different. Aws cli - uses pod role (as expected) aws-api - uses ec2 role (wrong) I found https://github.com/cognitect-labs/aws-api/blob/main/examples/assume_role_example.clj#L48 but role can't be assumed because sts client picks up node credentials which is wrong. https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html - has assume role https://github.com/cognitect-labs/aws-api/blob/0f0089f42c189ddf60b6ba2e0286bb71974aed63/src/cognitect/aws/credentials.clj#L321 - doesn't have assume role Is there a way for me to implement this? I can't be the first one that came across this?
What do you mean by sts client picks up node creds? I don't see an sts client in the line you linked?
How is/was the AWS cli finding the pod role?
How is/was the AWS cli finding the pod role?
I am assuming by default because when exec -it into the pod and do
aws sts get-caller-identity
it pulls POD role.
Here is the link to sts client:https://github.com/cognitect-labs/aws-api/blob/main/examples/assume_role_example.clj#L12Ah, yes, sorry the example has an sts client at the top. Yeah the assume role stuff doesn't change the existing client/credentials it makes a new client with new credentials for the assumed role
https://github.com/cognitect-labs/aws-api/blob/main/src/cognitect/aws/credentials.clj#L332 is the code and the order in which different credential providers are checked
Yeah i saw that and hoped i can extend it or something 😄
You can, the assumed role is an example of that, it uses it's own provider
Yeah but it doesn't work in my case as it's picking up node credentials.
Or i am missing something?
I think you need to back up, did you do any assume role stuff with aws-cli?
not manually, i honestly didn't do anything. I was little bit magical
(is assume role the problem you are trying to solve, or is assume role a new problem with what could be a solution to the problem)
So forget assume role
The issue is just aws-cli got the right credentials somehow, but aws-api is not
Ok yes
If you can get aws-cli to tell you where it is getting creds from that would be great
Alternatively you can go down the list of cred providers (in the order in the code there) checking to see if the env variables or system properties are being set somewhere
Ok, gonna start looking on how/where aws cli got the creds
You may just need to set AWS_CONTAINER_CREDENTIALS_RELATIVE_URI in the environment
this kinda tells me
2024-04-23 20:04:18,215 - MainThread - botocore.credentials - DEBUG - Looking for credentials via: env
2024-04-23 20:04:18,215 - MainThread - botocore.credentials - DEBUG - Looking for credentials via: assume-role
2024-04-23 20:04:18,215 - MainThread - botocore.credentials - DEBUG - Looking for credentials via: assume-role-with-web-identity
2024-04-23 20:04:18,216 - MainThread - botocore.loaders - DEBUG - Loading JSON file: /usr/local/aws-cli/v2/2.15.40/dist/awscli/botocore/data/endpoints.json
2024-04-23 20:04:18,229 - MainThread - botocore.hooks - DEBUG - Event choose-service-name: calling handler <function handle_service_name_alias at 0xffffa82f91c0>that it's assume-role-with-web-identity right?
ran
aws s3 ls --debug
and bunch of things happenedsame for aws sts get-caller-identity --debug
tested upload with
import boto3
def upload_file_to_s3(file_name, bucket, object_name=None):
"""
Upload a file to an Amazon S3 bucket
:param file_name: File to upload
:param bucket: Bucket to upload to
:param object_name: S3 object name. If not specified, file_name is used
:return: True if file was uploaded, else False
"""
# If S3 object_name was not specified, use file_name
if object_name is None:
object_name = file_name
# Create an S3 client
s3_client = boto3.client('s3')
try:
# Upload the file
response = s3_client.upload_file(file_name, bucket, object_name)
except Exception as e:
print(f'Error uploading file: {e}')
return False
return True
# Example usage
file_name = 'example.txt' # This is the file to upload
bucket_name = 'your-bucket-name' # Replace with your S3 bucket name
object_name = 'dest_filename.txt' # S3 object name (optional)
uploaded = upload_file_to_s3(file_name, bucket_name, object_name)
if uploaded:
print('File was uploaded successfully')
else:
print('Failed to upload file')
File was uploaded without any permissions issuesSo it's something with aws-api
I don't know that the list output there actually tells you where the initial set of credentials came from
the last credential thing logged is for assume-role-with-web-identity, so that might be where the final set of credentials came from, but assuming "assume-role" in the name there means it is using the assume role api stuff, then it must have found some earlier set of credentials that had the permissions to assume the role
ah, assume-role-with-web-identity stuff might actually mean another set of environment variables, not actually calling the assume role api at all
AWS_WEB_IDENTITY_TOKEN_FILE
doesn't appear in aws-api at allso aws-api doesn't know about https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html#envvars-list-AWS_WEB_IDENTITY_TOKEN_FILE
so you might be able to follow the assume rule example, but swap out https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html for the AssumeRole op and grab the parameters it needs from the env vars in the docs
so you are thinking about https://github.com/cognitect-labs/aws-api/blob/main/examples/assume_role_example.clj#L18 instead of using AssumeRole to use AssumeRoleWithWebIdentity operation and then pass everything just like in the example?
Did i understand you correctly?
no, the args to AssumeRoleWithWebIdentity are different, and it is likely aws-cli is grabbing them from the environment AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_ARN, and AWS_ROLE_SESSION_NAME so you'll need to adjust that too
AWS_WEB_IDENTITY_TOKEN_FILE, AWS_ROLE_ARN, are in the pod will see if it's possible to attempt this. Thank you so much i will let you know how it goes. Maybe PR to aws-cli so that no one else has to deal with this 😄
✅ solved with https://gist.github.com/gws/130ad8bfec5495c25c3dbc0ed2a69d42