Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ec2_ami: Add support for params BootMode, TpmSupport, UefiData #1037

Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
minor_changes:
- ec2_vpc_subnet - add support for BootMode, TpmSupport, UefiData params (https://github.com/ansible-collections/amazon.aws/pull/1037).
55 changes: 55 additions & 0 deletions plugins/modules/ec2_ami.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,27 @@
description:
- Set to simple to enable enhanced networking with the Intel 82599 Virtual Function interface for the AMI and any instances that you launch from the AMI.
type: str
boot_mode:
description:
- The boot mode of the AMI.
- See the AWS documentation for more detail U(https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ami-boot.html).
type: str
choices: ['legacy-bios', 'uefi']
tpm_support:
description:
- Set to v2.0 to enable Trusted Platform Module (TPM) support.
- If the image is configured for NitroTPM support, the value is v2.0 .
- Requires I(boot_mode) to be set to 'uefi'.
- Requires an instance type that is compatible with Nitro.
- Requires minimum botocore version 1.26.0.
mandar242 marked this conversation as resolved.
Show resolved Hide resolved
- See the AWS documentation for more detail U(https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/nitrotpm.html).
type: str
uefi_data:
description:
- Base64 representation of the non-volatile UEFI variable store.
- Requires minimum botocore version 1.26.0.
- See the AWS documentation for more detail U(https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/uefi-secure-boot.html).
type: str
author:
- "Evan Duffield (@scicoin-project) <[email protected]>"
- "Constantin Bugneac (@Constantin07) <[email protected]>"
Expand Down Expand Up @@ -214,6 +235,22 @@
- device_name: /dev/sdb
no_device: yes

- name: AMI Creation with boot_mode and tpm_support
amazon.aws.ec2_ami:
name: newtest
state: present
architecture: x86_64
virtualization_type: hvm
root_device_name: /dev/sda1
device_mapping:
- device_name: /dev/sda1
snapshot_id: "{{ snapshot_id }}"
wait: yes
region: us-east-1
boot_mode: uefi
uefi_data: data_file.bin
mandar242 marked this conversation as resolved.
Show resolved Hide resolved
tpm_support: v2.0

- name: Deregister/Delete AMI (keep associated snapshots)
amazon.aws.ec2_ami:
image_id: "{{ instance.image_id }}"
Expand Down Expand Up @@ -439,6 +476,12 @@ def create_image(module, connection):
billing_products = module.params.get('billing_products')
ramdisk_id = module.params.get('ramdisk_id')
sriov_net_support = module.params.get('sriov_net_support')
boot_mode = module.params.get('boot_mode')
tpm_support = module.params.get('tpm_support')
uefi_data = module.params.get('uefi_data')

if tpm_support and boot_mode != 'uefi':
module.fail_json(msg="To specify 'tpm_support', 'boot_mode' must be 'uefi'.")

if module.check_mode:
image = connection.describe_images(Filters=[{'Name': 'name', 'Values': [str(name)]}])
Expand Down Expand Up @@ -507,6 +550,12 @@ def create_image(module, connection):
params['KernelId'] = kernel_id
if root_device_name:
params['RootDeviceName'] = root_device_name
if boot_mode:
params['BootMode'] = boot_mode
if tpm_support:
params['TpmSupport'] = tpm_support
if uefi_data:
params['UefiData'] = uefi_data
image_id = connection.register_image(aws_retry=True, **params).get('ImageId')
except (botocore.exceptions.BotoCoreError, botocore.exceptions.ClientError) as e:
module.fail_json_aws(e, msg="Error registering image")
Expand Down Expand Up @@ -729,6 +778,9 @@ def main():
sriov_net_support=dict(),
tags=dict(type='dict', aliases=['resource_tags']),
purge_tags=dict(type='bool', default=True),
boot_mode=dict(type='str', choices=['legacy-bios', 'uefi']),
tpm_support=dict(type='str'),
uefi_data=dict(type='str'),
)

module = AnsibleAWSModule(
Expand All @@ -744,6 +796,9 @@ def main():
if not any([module.params['image_id'], module.params['name']]):
module.fail_json(msg="one of the following is required: name, image_id")

if any([module.params['tpm_support'], module.params['uefi_data']]):
module.require_botocore_at_least('1.26.0', reason='required for ec2.register_image with tpm_support or uefi_data')

connection = module.client('ec2', retry_decorator=AWSRetry.jittered_backoff())

if module.params.get('state') == 'absent':
Expand Down
3 changes: 3 additions & 0 deletions tests/integration/targets/ec2_ami/meta/main.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
dependencies:
- setup_ec2_facts
- role: setup_botocore_pip
vars:
botocore_version: '1.26.0'
72 changes: 72 additions & 0 deletions tests/integration/targets/ec2_ami/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
- amazon.aws
block:

# AWS CLI is needed until there's a module to get instance uefi data
- name: Install AWS CLI
pip:
name: awscli==1.25.83
state: present

# ============================================================

# SETUP: vpc, ec2 key pair, subnet, security group, ec2 instance, snapshot
Expand Down Expand Up @@ -74,6 +80,19 @@
state: present
register: setup_snapshot

- name: get instance UEFI data
command: aws ec2 get-instance-uefi-data --instance-id {{ ec2_instance_id }}
environment:
AWS_ACCESS_KEY_ID: "{{ aws_access_key }}"
AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}"
AWS_SESSION_TOKEN: "{{ security_token | default('') }}"
AWS_DEFAULT_REGION: "{{ aws_region }}"
register: instance_uefi_data_output

- name: Convert it to an object
set_fact:
instance_uefi_data: "{{ instance_uefi_data_output.stdout | from_json }}"

# ============================================================

- name: test clean failure if not providing image_id or name with state=present
Expand Down Expand Up @@ -628,6 +647,52 @@
- not result.changed
- not result.failed

# ============================================================

- name: create an image from the snapshot with boot_mode and tpm_support
ec2_ami:
name: '{{ ec2_ami_name }}_ami-boot-tpm'
description: '{{ ec2_ami_description }}'
state: present
boot_mode: uefi
tpm_support: v2.0
launch_permissions:
user_ids: []
tags:
Name: '{{ ec2_ami_name }}_ami-boot-tpm'
root_device_name: '{{ ec2_ami_root_disk }}'
device_mapping:
- device_name: '{{ ec2_ami_root_disk }}'
volume_type: gp2
size: 8
delete_on_termination: true
snapshot_id: '{{ setup_snapshot.snapshot_id }}'
register: result
ignore_errors: true
vars:
ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}"

- name: set image id fact for deletion later
set_fact:
ec2_ami_image_id_boot_tpm: "{{ result.image_id }}"
ec2_ami_snapshot_boot_tpm: "{{ result.block_device_mapping[ec2_ami_root_disk].snapshot_id }}"

- name: gather facts about the image created
ec2_ami_info:
image_ids: '{{ ec2_ami_image_id_boot_tpm }}'
register: ami_facts_result_boot_tpm
ignore_errors: true
vars:
ansible_python_interpreter: "{{ botocore_virtualenv_interpreter }}"

- name: assert that new ami has been created with desired options
assert:
that:
- "result.changed"
- "result.image_id.startswith('ami-')"
- ami_facts_result_boot_tpm.images[0].image_id | length != 0
- ami_facts_result_boot_tpm.images[0].boot_mode == 'uefi'
- ami_facts_result_boot_tpm.images[0].tpm_support == 'v2.0'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also test uefi_data?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trying to figure out what a valid uefi_data_file would look like, currently boto is throwing error on below task

    - name: AMI Creation with boot_mode and tpm_support
      amazon.aws.ec2_ami:
        name: newtest-uefi-file-data
        state: present
        architecture: x86_64
        virtualization_type: hvm
        root_device_name: /dev/sda1
        device_mapping:
          - device_name: /dev/sda1
            snapshot_id: snap-0f00cba7123456
        wait: yes
        region: us-east-2
        boot_mode: uefi
        uefi_data: "{{ lookup('file', 'uefi_data_file') | b64encode }}"
        tpm_support: v2.0
        tags:
          name: test-ami
botocore.exceptions.ClientError: An error occurred (InvalidParameterValue)
when calling the RegisterImage operation: Invalid uefiData.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest to use get_instance_uefi_data() https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ec2.html#EC2.Client.get_instance_uefi_data to get a working uefidata file and you can send it back later in the tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tried that but turns out it throws unauthorized error for the operator GetInstanceUefiData.
Would need to open a PR to get the permissions added to terminator repository.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the permission issue has been resolved, currently trying to solve error

An error occurred (InvalidInstanceID.NotFound) when calling the GetInstanceUefiData operation: 
Unknown virtIds for owner 'xxxxxxx': [ i-xxxxxxxxxx ]"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@goneri, it appears that there are currently no provided AMIs with uefi boot mode support for linux, also none of our currently supported instance types for integration tests support uefi boot mode.
I can test the code for UEFI boot mode and UEFI data manually but not sure if it's possible to add to integration tests.

Relevant links:
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/launch-instance-with-uefi-sb.html
https://docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/enable-nitrotpm-prerequisites.html
https://aws.amazon.com/blogs/aws/amazon-ec2-now-supports-nitrotpm-and-uefi-secure-boot/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be a good candidate for an unit-test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


# ============================================================

Expand All @@ -640,6 +705,13 @@
debug:
msg: "***** TESTING COMPLETE. COMMENCE TEARDOWN *****"

- name: delete ami
ec2_ami:
state: absent
image_id: "{{ ec2_ami_image_id_boot_tpm }}"
wait: yes
ignore_errors: yes

- name: delete ami
ec2_ami:
state: absent
Expand Down