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:
...