Skip to content

[BUG] salt-cloud using ec2 fails to authenticate properly when a AWS SESSION TOKEN is required. FIX INCLUDED #64533

Description

@matthewsht

Description
My organization has configured AWS to require an ID, a KEY and a session token when authenticating to the API.

So we set (in a shell environement)

$ export AWS_ACCESS_KEY_ID="******"
$ export AWS_SECRET_ACCESS_KEY="******"
$ export AWS_SESSION_TOKEN="******"

and everything works.
Note that this is from a laptop/workstation outside of AWS itself - I am NOT on an instance.

salt-cloud using the ec2 driver should be able to auth with all 3 when required.

No, I cannot redo our aws config to change this - its done by a cloud team.

Setup
From my /etc/salt/cloud.providers.d/ec2.conf :

 # Set the EC2 access credentials (see below)
  id: "******"
  key: "******"
 
  # If 'role_arn' is specified the above credentials are used to
  # to assume to the role. By default, role_arn is set to None.
  #role_arn: arn:aws:iam::207348486369:role/NIH-AWS-SystemAdministrator-SSA

Steps to Reproduce the behavior

  1. set only id and key in the relevant config
  2. attempt to use the AWS api - I picked --list-locations for simplicity

salt-cloud --list-locations ec2
[ERROR ] AWS Response Status Code and Error: [401 401 Client Error: Unauthorized for url: https://ec2.us-east-1.amazonaws.com/?Action=DescribeRegions&Version=2016-11-15] {'Errors': {'Error': {'Code': 'AuthFailure', 'Message': 'AWS was not able to validate the provided access credentials'}}, 'RequestID': '8ed6a97c-ff13-4a1d-9ef7-c6af19a1f8ba'}
[ERROR ] Failed to get the output of 'ec2.avail_locations()': string indices must be integers
aws-ssa:
----------

Expected behavior
If needed, a 3rd authentication variable for the "token" should be accepted and used.

MINIMUM FIX
https://github.com/saltstack/salt/blob/b0bf7eba9b6c98153fb328ac823be421c92f524d/salt/utils/aws.py#L175C22-L175C22

line #175 should be changed to

        ret_credentials = provider["id"], provider["key"], provider["token"]

and then the user can set the "token" variable in the config.
For users not needing a token, an empty string should work (I can't test this obviously).

MORE COMPLETE FIX
For line #175, code like this should cover both kinds of users:

       if provider.get("token") is not None:
            ret_credentials = provider["id"], provider["key"], provider["token"]
        else:
            ret_credentials = provider["id"], provider["key"], ""

I believe similar code should be used for lines

return provider["id"], provider["key"], ""

return provider["id"], provider["key"], ""

Versions Report

> salt --versions-report

Salt Version:
          Salt: 3005

Dependency Versions:
          cffi: 1.14.6
      cherrypy: unknown
      dateutil: 2.8.0
     docker-py: Not Installed
         gitdb: 4.0.5
     gitpython: 3.1.12
        Jinja2: 3.1.0
       libgit2: 1.6.4
      M2Crypto: Not Installed
          Mako: 1.1.4
       msgpack: 1.0.2
  msgpack-pure: Not Installed
  mysql-python: Not Installed
     pycparser: 2.21
      pycrypto: 3.15.0
  pycryptodome: 3.9.8
        pygit2: 1.12.0
        Python: 3.10.12 (main, Jun 15 2023, 07:47:12) [Clang 14.0.0 (clang-1400.0.29.202)]
  python-gnupg: 0.4.8
        PyYAML: 5.4.1
         PyZMQ: 23.2.0
         smmap: 3.0.2
       timelib: 0.2.4
       Tornado: 4.5.3
           ZMQ: 4.3.4

System Versions:
          dist: darwin 21.6.0
        locale: utf-8
       machine: arm64
       release: 21.6.0
        system: Darwin
       version: 12.6.5 arm64

This was installed on monterey via brew.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugbroken, incorrect, or confusing behavior

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions