Package: ec2-metadata
An easy interface to query the EC2 metadata API (version 2), with caching.A quick example:>>>fromec2_metadataimportec2_metadata>>>print(ec2_metadata.region)us-east-1>>>print(ec2_metadata.instance_id)i-123456InstallationUsepip:python-mpipinstallec2-metadataPython 3.8 to 3.12 supported.Working on a Django project?Improve your skills withone of my books.Why?botocame with a utility function to retrieve the instance metadata as a
lazy loading dictionary,boto.utils.get_instance_metadata, but this has not
been ported toboto3, as perthis issue. I thought that rather than
building a new version insideboto3it would work well as a standalone
library.Instance Metadata Service Version 2In November 2019, AWS releasedversion 2of the instance metadata service. It’s more secure against Server Side Request
Forgery (SSRF) attacks.ec2-metadatanow uses it exclusively. You can therefore consider disabling
version 1, as perAWS’ guide.Note:Instance Metadata Service v2 has a default IP hop limit of 1.
This can mean that you can seerequests.exceptions.ReadTimeouterrors from within Docker containers.
To solve this, reconfigure your EC2 instance’s metadata options to allow three hops withaws ec2modify-instance-metadata-options:awsec2modify-instance-metadata-options--instance-id<instance-id>--http-put-response-hop-limit3APIEC2Metadata(session=None)A container that represents the data available on the EC2 metadata service.
Attributes don’t entirely correspond to the paths in the metadata service -
they have been ‘cleaned up’. You may also want to refer to themetadata
service docsto understand the exact contents.There’s a singleton instance of it at the nameec2_metadatawhich should
cover 90% of use cases. Use it like:fromec2_metadataimportec2_metadataec2_metadata.regionThesessionargument, if provided, should be an instance ofrequests.Session, allowing you to customize the way requests are made.Most of the attributes are cached, except where noted below. This is because
they are mostly immutable, or at least require an instance stop to change.
However some cached attributes do represent things that can change without an
instance stop, but rarely do, such as network devices.The caching is done with@cached_property, so they cache on first access.
If you want to clear the cache of one attribute you can justdelit:delec2_metadata.network_interfacesTo clear all, use theclear_all()method as per below.account_id: strThe current AWS account ID, e.g.'123456789012'.ami_id: strThe ID of the AMI used to launch the instance, e.g.'ami-123456'.autoscaling_target_lifecycle_state: str | NoneUncached.The target Auto Scaling lifecycle state that the instance is transitionioning to, orNoneif the instance is not in an autoscaling group.
See AWS docs pageRetrieve the target lifecycle state through instance metadata.availability_zone: strThe name of the current AZ e.g.'eu-west-1a'.availability_zone_id: str | NoneThe unique, cross-account ID of the current AZ e.g.'use1-az6'.
See AWS docs pageAZ IDs for your AWS resources.ami_launch_index: intThe index of the instance in the launch request, zero-based, e.g.0.ami_manifest_path: strThe path to the AMI manifest file in Amazon S3, or'(unknown)'on
EBS-backed AMI’s.clear_all()->NoneClear all the cached attributes on the class, meaning their next access will
re-fetch the data from the metadata API. This includes clearing the token used
to authenticate with the service.domain: strThe domain for AWS resources for the region. E.g.'amazonaws.com'for the
standard AWS regions and GovCloud (US), or'amazonaws.com.cn'for China.iam_info: IamInfoDict | NoneA dictionary of data for the IAM role attached to the instance, orNoneif no role is attached.
The dict has this type, based on what the metadata service returns:classIamInfoDict(TypedDict):InstanceProfileArn:strInstanceProfileId:strLastUpdated:striam_security_credentials: IamSecurityCredentialsDict | NoneA dictionary of data for the security credentials associated with the IAM role attached to the instance, orNoneif no role is attached.
See theAWS docs section “Retrieve security credentials from instance metadata”for details.
The dict has this type, based on that document:classIamSecurityCredentialsDict(TypedDict):LastUpdated:strType:strAccessKeyId:strSecretAccessKey:strToken:strExpiration:strinstance_action: strUncached.A state that notifies if the instance will reboot in preparation
for bundling. See theAWS docs section “Instance Metadata Categories”for the valid values.instance_id: strThe current instance’s ID, e.g.'i-123456'instance_identity_document: InstanceIdentityDocumentDictA dictionary of dynamic data about the instance.
See theAWS docs page “Instance Identity Documents”for an explanation of the contents.
The dict has this type, based on that document:classInstanceIdentityDocumentDict(TypedDict):accountId:strarchitecture:Literal["i386","x86_64","arm64"]availabilityZone:strbillingProducts:list[str]|NonemarketplaceProductCodes:list[str]|NoneimageId:strinstanceId:strinstanceType:strkernelId:str|NonependingTime:strprivateIp:strramdiskId:str|Noneregion:strversion:strinstance_profile_arn: str | NoneThe ARN of the IAM role/instance profile attached to the instance, taken fromiam_info, orNoneif no role is attached.instance_profile_id: str | NoneThe ID of the IAM role/instance profile attached to the instance, taken fromiam_info, orNoneif no role is attached.instance_profile_name: str | NoneThe instance profile name, extracted frominstance_profile_arn, orNoneif no role is attached.instance_type: strThe current instance’s type, e.g.'t2.nano'kernel_id: str | NoneThe current instance’s kernel ID, orNoneif it doesn’t have one, e.g.'aki-dc9ed9af'.mac : strThe instance’s MAC address, e.g.'0a:d2:ae:4d:f3:12'network_interfaces: dict[str, NetworkInterface]A dictionary of mac address toNetworkInterface, which represents the data
available on a network interface - see below. E.g.{'01:23:45:67:89:ab':NetworkInterface('01:23:45:67:89:ab')}partition: strThe AWS partition where the instance is running. E.g.'aws'for the
standard AWS regions,'aws-us-gov'for GovCloud (US), or'aws-cn'for China.private_hostname : strThe private IPv4 DNS hostname of the instance, e.g.'ip-172-30-0-0.eu-west-1.compute.internal'.private_ipv4: strThe private IPv4 of the instance, e.g.'172.30.0.0'.public_hostname : str | NoneThe public DNS hostname of the instance, orNoneif the instance is not
public, e.g.'ec2-1-2-3-4.compute-1.amazonaws.com'.public_ipv4: str | NoneThe public IPv4 address of the instance, orNoneif the instance is not
public, e.g.'1.2.3.4'.region: strThe region the instance is running in, e.g.'eu-west-1'.reservation_id: strThe ID of the reservation used to launch the instance, e.g.'r-12345678901234567'.security_groups : list[str]List of security groups by name, e.g.['ssh-access','custom-sg-1'].spot_instance_action: SpotInstanceAction | NoneUncached.An object describing an action about to happen to this spot instance.
ReturnsNoneif the instance is not spot, or not marked for termination.TheSpotInstanceActionobject has two attributes:action: str- the action about to happen, one of"hibernate","stop", or"terminate".time: datetime- the approximate UTC datetime when the action will occur.SeeAWS docs sectionfor a little more information.tags: InstanceTagsA dict-like mapping of the tags for the instance (documented below).
This requires you toexplicitly enable the featurefor the instance.
If the feature is not enabled, accessing this attribute raises an error.(It also seems that there is a bug where if the feature is enabled and then disabled, the metadata service returns an empty response.
This is indistinguishable from “no tags”, so beware that in that case,InstanceTagswill just look like an empty mapping.)user_data: bytes | NoneThe raw user data assigned to the instance (not base64 encoded), orNoneif
there is none.InstanceTagsA dict-like mapping of tag names to values (bothstrs).
To avoid unnecessary requests, the mapping is lazy: values are only fetched when required.
(Names are known on construction though, from the first request inEC2Metadata.tags.)The metadata service will receive tag updates on some instance types, as perthe AWS documentation:If you add or remove an instance tag, the instance metadata is updated while the instance is running for instances built on the Nitro System, without needing to stop and then start the instance.
For all other instances, to update the tags in the instance metadata, you must stop and then start the instance.BecauseInstanceTagsis cached, it won’t reflect such updates on Nitro instances unless you clear it first:delec2_metadata.tagsec2_metadata.tags["Name"]# freshNetworkInterfaceRepresents a single network interface, as retrieved fromEC2Metadata.network_interfaces. Again likeEC2Metadataall its
attributes cache on first access, and can be cleared withdelor
itsclear_all()method.device_number: intThe unique device number associated with that interface, e.g.0.interface_id: strThe unique id used to identify the Elastic Network Interface, e.g.'eni-12345'.ipv4_associations: dict[str, list[str]]A dictionary mapping public IP addresses on the interface to the list of
private IP addresses associated with that public IP, for each public IP that is
associated with the interface, e.g.{'54.0.0.1':['172.30.0.0']}.ipv6s: list[str]The IPv6 addresses associated with the interface, e.g.['2001:db8:abcd:ef00::1234'].mac: strThe MAC address of the interface, e.g.'01:23:45:67:89:ab'.owner_id: strThe AWS Account ID of the owner of the network interface, e.g.'123456789012'.private_hostname: strThe interface’s local/private hostname, e.g.'ip-172-30-0-0.eu-west-1.compute.internal'.private_ipv4s: list[str]The private IPv4 addresses associated with the interface, e.g.['172.30.0.0'].public_hostname: str | NoneThe interface’s public DNS (IPv4), e.g.'ec2-54-0-0-0.compute-1.amazonaws.com'.public_ipv4s: list[str]The Elastic IP addresses associated with the interface, e.g.['54.0.0.0'].security_groups: list[str]The names of the security groups to which the network interface belongs, e.g.['ssh-access','custom-sg-1'].security_group_ids: list[str]The names of the security groups to which the network interface belongs, e.g.['sg-12345678','sg-12345679'].subnet_id: strThe ID of the subnet in which the interface resides, e.g.'subnet-12345678'.subnet_ipv4_cidr_block: str | NoneThe IPv4 CIDR block of the subnet in which the interface resides, orNoneif there is none, e.g.'172.30.0.0/24'.subnet_ipv6_cidr_blocks: list[str]The list of IPv6 CIDR blocks of the subnet in which the interface resides, e.g.['2001:db8:abcd:ef00::/64']. If the subnet does not have any IPv6 CIDR
blocks or the instance isn’t in a VPC, the list will be empty, e.g.[].vpc_id: strThe ID of the VPC in which the interface resides, e.g.'vpc-12345678'.vpc_ipv4_cidr_block: str | NoneThe IPv4 CIDR block of the VPC, orNoneif the instance isn’t in a VPC,
e.g.'172.30.0.0/16'.vpc_ipv4_cidr_blocks: list[str]The list of IPv4 CIDR blocks e.g.['172.30.0.0/16']. If the interface
doesn’t have any such CIDR blocks, the list will be empty.vpc_ipv6_cidr_blocks: list[str]The list of IPv6 CIDR blocks of the VPC in which the interface resides, e.g.['2001:db8:abcd:ef00::/56']. If the VPC does not have any IPv6 CIDR blocks
or the instance isn’t in a VPC, the list will be empty, e.g.[].