Can't get AWS SSM to touch a file in an ubuntu EC2

First off, version information

AWS session-manager-plugin (1.2.707.0-1) ...

ansible --version
ansible [core 2.18.6]
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /builds/venv/lib/python3.12/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /builds/venv/bin/ansible
  python version = 3.12.3 (main, Jun 18 2025, 17:59:45) [GCC 13.3.0] (/builds/venv/bin/python)
  jinja version = 3.1.6
  libyaml = True

The Inventory

cat ansible-ec2-deploy/inventory.yaml
all:
  hosts:
    i-ec2id1234567:
      ansible_connection: community.aws.aws_ssm
      aws_ssm_region: us-west-1
      aws_ssm_bucket_name: my-bucket-name
      aws_ssm_bucket_prefix: ansible-ssm/

playbook

- hosts: all
  gather_facts: false
  become: true
  become_user: ubuntu
  vars:
    ansible_connection: community.aws.aws_ssm
    ansible_aws_ssm_region: us-west-1 
  tasks:
    - name: Touch HELLOWORLD file
      file:
        path: /home/ubuntu/ansible-hello.txt
        state: touch

I am very new to ansible but.. in AWS I’ve setup a descrete User / Credential.. here’s the Permissions on the Host executing the playbook

{
    "Statement": [
        {
            "Action": [
                "ssm:SendCommand",
                "ssm:GetParameter",
                "ssm:DescribeInstanceInformation",
                "ssm:GetCommandInvocation"
            ],
            "Effect": "Allow",
            "Resource": "*"
        },
        {
            "Action": [
                "ec2:DescribeInstances"
            ],
            "Effect": "Allow",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:ListBucket",
                "s3:DeleteObject",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::*-ssm-ansible"
        }
    ],
    "Version": "2012-10-17"
}

But everytime I’m executing it complains I am not setting some string… there’s so many ways to set a variable in ansible I am a bit over my head here.. please advise?

ansible-playbook -i ansible-ec2-deploy/inventory.yaml ansible-ec2-deploy/playbook.yaml -vvv
ansible-playbook [core 2.18.6]
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /builds/venv/lib/python3.12/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /builds/venv/bin/ansible-playbook
  python version = 3.12.3 (main, Jun 18 2025, 17:59:45) [GCC 13.3.0] (/builds/venv/bin/python)
  jinja version = 3.1.6
  libyaml = True
No config file found; using defaults
host_list declined parsing /builds/ansible-ec2-deploy/inventory.yaml as it did not pass its verify_file() method
script declined parsing /builds/ansible-ec2-deploy/inventory.yaml as it did not pass its verify_file() method
Parsed /builds/ansible-ec2-deploy/inventory.yaml inventory source with yaml plugin
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.
PLAYBOOK: playbook.yaml ********************************************************
1 plays in ansible-ec2-deploy/playbook.yaml
PLAY [all] *********************************************************************
TASK [Touch HELLOWORLD file] ***************************************************
task path: /builds/ansible-ec2-deploy/playbook.yaml:5
<i-MYID12345676> ESTABLISH SSM CONNECTION TO: i-MYID12345676
<i-MYID12345676> ssm_retry: attempt: 0, caught exception(expected string or bytes-like object, got 'NoneType')from cmd (echo ~ubuntu...),pausing for 0 seconds
<i-MYID12345676> ESTABLISH SSM CONNECTION TO: i-MYID12345676
<i-MYID12345676> ssm_retry: attempt: 1, caught exception(expected string or bytes-like object, got 'NoneType')from cmd (echo ~ubuntu...),pausing for 1 seconds
<i-MYID12345676> ESTABLISH SSM CONNECTION TO: i-MYID12345676
<i-MYID12345676> ssm_retry: attempt: 2, caught exception(expected string or bytes-like object, got 'NoneType')from cmd (echo ~ubuntu...),pausing for 3 seconds
<i-MYID12345676> ESTABLISH SSM CONNECTION TO: i-MYID12345676
The full traceback is:
Traceback (most recent call last):
  File "/builds/venv/lib/python3.12/site-packages/ansible/executor/task_executor.py", line 176, in run
    res = self._execute()
          ^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/ansible/executor/task_executor.py", line 673, in _execute
    result = self._handler.run(task_vars=vars_copy)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/ansible/plugins/action/normal.py", line 38, in run
    result = merge_hash(result, self._execute_module(task_vars=task_vars, wrap_async=wrap_async))
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/ansible/plugins/action/__init__.py", line 1029, in _execute_module
    self._make_tmp_path()
  File "/builds/venv/lib/python3.12/site-packages/ansible/plugins/action/__init__.py", line 469, in _make_tmp_path
    tmpdir = self._remote_expand_user(self.get_shell_option('remote_tmp', default='~/.ansible/tmp'), sudoable=False)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/ansible/plugins/action/__init__.py", line 905, in _remote_expand_user
    data = self._low_level_execute_command(cmd, sudoable=False)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/ansible/plugins/action/__init__.py", line 1319, in _low_level_execute_command
    rc, stdout, stderr = self._connection.exec_command(cmd, in_data=in_data, sudoable=sudoable)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/ansible_collections/community/aws/plugins/plugin_utils/ssm/common.py", line 33, in wrapped
    return_tuple = func(self, *args, **kwargs)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/ansible_collections/community/aws/plugins/connection/aws_ssm.py", line 648, in exec_command
    super().exec_command(cmd, in_data=in_data, sudoable=sudoable)
  File "/builds/venv/lib/python3.12/site-packages/ansible/plugins/connection/__init__.py", line 44, in wrapped
    self._connect()
  File "/builds/venv/lib/python3.12/site-packages/ansible_collections/community/aws/plugins/connection/aws_ssm.py", line 498, in _connect
    self.start_session()
  File "/builds/venv/lib/python3.12/site-packages/ansible_collections/community/aws/plugins/connection/aws_ssm.py", line 576, in start_session
    self._init_clients()
  File "/builds/venv/lib/python3.12/site-packages/ansible_collections/community/aws/plugins/connection/aws_ssm.py", line 511, in _init_clients
    self.s3_manager
  File "/builds/venv/lib/python3.12/site-packages/ansible_collections/community/aws/plugins/connection/aws_ssm.py", line 447, in s3_manager
    s3_endpoint_url, s3_region_name = S3ClientManager.get_bucket_endpoint(
                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/ansible_collections/community/aws/plugins/plugin_utils/ssm/s3clientmanager.py", line 86, in get_bucket_endpoint
    head_bucket = tmp_s3_client.head_bucket(Bucket=(bucket_name))
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/botocore/client.py", line 595, in _api_call
    return self._make_api_call(operation_name, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/botocore/context.py", line 123, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/botocore/client.py", line 999, in _make_api_call
    api_params = self._emit_api_params(
                 ^^^^^^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/botocore/client.py", line 1118, in _emit_api_params
    self.meta.events.emit(
  File "/builds/venv/lib/python3.12/site-packages/botocore/hooks.py", line 412, in emit
    return self._emitter.emit(aliased_event_name, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/botocore/hooks.py", line 256, in emit
    return self._emit(event_name, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/botocore/hooks.py", line 239, in _emit
    response = handler(**kwargs)
               ^^^^^^^^^^^^^^^^^
  File "/builds/venv/lib/python3.12/site-packages/botocore/handlers.py", line 292, in validate_bucket_name
    if not VALID_BUCKET.search(bucket) and not VALID_S3_ARN.search(bucket):
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: expected string or bytes-like object, got 'NoneType'
fatal: [i-MYID12345676]: FAILED! => {
    "msg": "Unexpected failure during module execution: expected string or bytes-like object, got 'NoneType'",
    "stdout": ""
}
PLAY RECAP *********************************************************************
i-MYID12345676        : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
Cleaning up project directory and file based variables 00:00
ERROR: Job failed: exit code 1

If you set gather_facts: true, does the gather facts step work? Your traceback is complaining about getting a NoneType when searching for valid buckets in S3.

Based on the community.aws.aws_ssm connection — Ansible Community Documentation, you’re missing the variable prefix ansible_ for two of the aws_ssm variables, and 1 of the 3 variables doesn’t exist. S3 files will be created with the EC2 host ID as the prefix.

Making the follow changes may resolve your connection issue:

The Inventory

cat ansible-ec2-deploy/inventory.yaml
all:
  hosts:
    i-ec2id1234567:
      ansible_connection: community.aws.aws_ssm
-      aws_ssm_region: us-west-1
-      aws_ssm_bucket_name: my-bucket-name
-      aws_ssm_bucket_prefix: ansible-ssm/
+      ansible_aws_ssm_region: us-west-1
+      ansible_aws_ssm_bucket_name: my-bucket-name

On another note, you may want to try using a dynamic inventory plugin instead of a static inventory using amazon.aws.aws_ec2 inventory – EC2 inventory source — Ansible Community Documentation.

2 Likes

Thank you Caleb,

I ended up hammering again and again on the .yaml playbook and finally something worked.. here’s what I got for the playbook

- hosts: all
  gather_facts: false
  become_user: ubuntu
  vars:
    ansible_connection: community.aws.aws_ssm
    ansible_aws_ssm_region: us-west-1
    ansible_aws_ssm_bucket_name: 'some-bucket-name'
  tasks:
...

Your traceback is complaining about getting a NoneType when searching for valid buckets in S3.

@EMCP Would you mind opening a bug report?

While it’s expected that what you were doing wouldn’t work (because necessary variables weren’t set), you should have received a clean error message that told you the variable hadn’t been set rather than a big stack trace.

Please also be aware, that the current implementation of the AWS SSM connection plugin is rather slow as it opens fresh SSM connections for every task (with the standard SSH connection plugin, there’s some SSH magic that’s often used to significantly improve performance)

1 Like

Full warning that output was with full verbose on, should I still file ?

It’s still a bug :slight_smile:, so yes please