From b7c4d8260c6beb403a2f2cc7d91de9dd7a63f1ea Mon Sep 17 00:00:00 2001 From: "Tony S. Wu" Date: Sun, 4 Aug 2024 23:43:44 -0700 Subject: [PATCH] Add option "metadata_token_ttl_seconds" to ec2_metadata_facts module. (#2209) Fixes: #2205 SUMMARY ec2_metadata_facts sometimes returns 401 unauthorized if the IMDSv2 token times out. The token TTL is currently hardcoded to 60, this pull request aims to make it configurable. ISSUE TYPE Feature Pull Request COMPONENT NAME ec2_metadata_facts Reviewed-by: Mark Chappell --- ...a_facts-add-configurable-ttl-parameter.yml | 3 +++ plugins/modules/ec2_metadata_facts.py | 26 +++++++++++++++++-- .../playbooks/test_metadata.yml | 16 ++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/2209-ec2_metadata_facts-add-configurable-ttl-parameter.yml diff --git a/changelogs/fragments/2209-ec2_metadata_facts-add-configurable-ttl-parameter.yml b/changelogs/fragments/2209-ec2_metadata_facts-add-configurable-ttl-parameter.yml new file mode 100644 index 00000000000..76cbd4e4335 --- /dev/null +++ b/changelogs/fragments/2209-ec2_metadata_facts-add-configurable-ttl-parameter.yml @@ -0,0 +1,3 @@ +--- +minor_changes: + - ec2_metadata_facts - Add parameter ``metadata_token_ttl_seconds`` (https://github.com/ansible-collections/amazon.aws/pull/2209). diff --git a/plugins/modules/ec2_metadata_facts.py b/plugins/modules/ec2_metadata_facts.py index 83fdd441783..db955f0ae0d 100644 --- a/plugins/modules/ec2_metadata_facts.py +++ b/plugins/modules/ec2_metadata_facts.py @@ -23,12 +23,24 @@ is set to disabled for the EC2 instance, the module will return an error while retrieving a session token. notes: - Parameters to filter on ec2_metadata_facts may be added later. +options: + metadata_token_ttl_seconds: + description: + - Specify a value for the C(X-aws-ec2-metadata-token-ttl-seconds) header. + - Value must be between V(1) and V(21600). + type: int + default: 60 + version_added: 8.2.0 """ EXAMPLES = r""" # Gather EC2 metadata facts - amazon.aws.ec2_metadata_facts: +# Set a bigger value for X-aws-ec2-metadata-token-ttl-seconds header +- amazon.aws.ec2_metadata_facts: + metadata_token_ttl_seconds: 240 + - debug: msg: "This instance is a t1.micro" when: ansible_ec2_instance_type == "t1.micro" @@ -610,7 +622,8 @@ def fix_invalid_varnames(self, data): def fetch_session_token(self, uri_token): """Used to get a session token for IMDSv2""" - headers = {"X-aws-ec2-metadata-token-ttl-seconds": "60"} + metadata_token_ttl_seconds = self.module.params.get("metadata_token_ttl_seconds") + headers = {"X-aws-ec2-metadata-token-ttl-seconds": metadata_token_ttl_seconds} response, info = fetch_url(self.module, uri_token, method="PUT", headers=headers, force=True) if info.get("status") == 403: @@ -657,11 +670,20 @@ def run(self): def main(): + argument_spec = dict( + metadata_token_ttl_seconds=dict(required=False, default=60, type="int", no_log=False), + ) + module = AnsibleModule( - argument_spec={}, + argument_spec=argument_spec, supports_check_mode=True, ) + metadata_token_ttl_seconds = module.params.get("metadata_token_ttl_seconds") + + if metadata_token_ttl_seconds <= 0 or metadata_token_ttl_seconds > 21600: + module.fail_json(msg="The option 'metadata_token_ttl_seconds' must be set to a value between 1 and 21600.") + ec2_metadata_facts = Ec2Metadata(module).run() ec2_metadata_facts_result = dict(changed=False, ansible_facts=ec2_metadata_facts) diff --git a/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml b/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml index d055480f7aa..158fda20ac5 100644 --- a/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml +++ b/tests/integration/targets/ec2_metadata_facts/playbooks/test_metadata.yml @@ -15,3 +15,19 @@ - ansible_ec2_user_data == "None" - ansible_ec2_instance_tags_keys is defined - ansible_ec2_instance_tags_keys | length == 3 + + - name: Clear facts for another test + ansible.builtin.meta: clear_facts + + - amazon.aws.ec2_metadata_facts: + metadata_token_ttl_seconds: 240 + + - name: Assert initial metadata for the instance + ansible.builtin.assert: + that: + - ansible_ec2_ami_id == image_id + - ansible_ec2_placement_availability_zone == availability_zone + - ansible_ec2_security_groups == resource_prefix+"-sg" + - ansible_ec2_user_data == "None" + - ansible_ec2_instance_tags_keys is defined + - ansible_ec2_instance_tags_keys | length == 3