Source code for insights.parsers.aws_instance_id

"""
AWSInstanceID
=============

These parsers read the output of commands to collect identify information
from AWS instances.

AWSInstanceIdDoc - ``curl -s http://169.254.169.254/latest/dynamic/instance-identity/document``
-----------------------------------------------------------------------------------------------

AWSInstanceIdPkcs7 - ``curl -s http://169.254.169.254/latest/dynamic/instance-identity/pkcs7``
----------------------------------------------------------------------------------------------

AWSPublicIpv4Addresses - ``curl -s http://169.254.169.254/latest/meta-data/public-ipv4``
----------------------------------------------------------------------------------------

AWSPublicHostname ``curl -s http://169.254.169.254/latest/meta-data/public-hostname``
-------------------------------------------------------------------------------------

"""
from __future__ import print_function
import json

from insights.core import CommandParser
from insights.core.exceptions import ParseException, SkipComponent
from insights.core.plugins import parser
from insights.specs import Specs

_aws_curl_invalid_keyworks = [
    'curl: ',
    '<?xml ',
]


def _validate_content(content, length=0):
    if (not content or                                 # Empty content
            (length > 0 and len(content) > length) or  # Too many lines
            any(item in content[0]                     # Unexpected keywords
                for item in _aws_curl_invalid_keyworks)):
        raise SkipComponent()


[docs] @parser(Specs.aws_instance_id_doc) class AWSInstanceIdDoc(CommandParser, dict): """ Class for parsing the AWS Instance Identity Document returned by the command:: curl -s http://169.254.169.254/latest/dynamic/instance-identity/document Typical output of this command is:: { "devpayProductCodes" : null, "marketplaceProductCodes" : [ "1abc2defghijklm3nopqrs4tu" ], "availabilityZone" : "us-west-2b", "privateIp" : "10.158.112.84", "version" : "2017-09-30", "instanceId" : "i-1234567890abcdef0", "billingProducts" : [ "bp-6ba54002" ], "instanceType" : "t2.micro", "accountId" : "123456789012", "imageId" : "ami-5fb8c835", "pendingTime" : "2016-11-19T16:32:11Z", "architecture" : "x86_64", "kernelId" : null, "ramdiskId" : null, "region" : "us-west-2" } Raises: SkipComponent: When content is empty or cannot be parsed. ParseException: When type cannot be recognized. Attributes: dict: Parser object is a dictionary that is a direct translation of the input key:value pairs. json (str): Input in JSON string format. Examples: >>> print(aws_id_doc['billingProducts'][0]) bp-6ba54002 >>> 'version' in aws_id_doc True >>> print(aws_id_doc['version']) 2017-09-30 """
[docs] def parse_content(self, content): _validate_content(content) # Just in case curl stats are present in data startline = 0 for l in content: if l.strip().startswith('{'): break startline += 1 self.json = '\n'.join([l.rstrip() for l in content[startline:]]) try: doc_values = json.loads(self.json) self.update(doc_values) except ValueError as e: raise ParseException('Failed to parse json with error: %s', str(e))
[docs] @parser(Specs.aws_instance_id_pkcs7) class AWSInstanceIdPkcs7(CommandParser): """ Class for parsing the AWS Instance Identity PKCS7 signature returned by the command:: curl -s http://169.254.169.254/latest/dynamic/instance-identity/pkcs7 Typical output of this command is:: MIICiTCCAfICCQD6m7oRw0uXOjANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMC VVMxCzAJBgNVBAgTAldBMRAwDgYDVQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6 b24xFDASBgNVBAsTC0lBTSBDb25zb2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAd BgkqhkiG9w0BCQEWEG5vb25lQGFtYXpvbi5jb20wHhcNMTEwNDI1MjA0NTIxWhcN MTIwNDI0MjA0NTIxWjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAldBMRAwDgYD VQQHEwdTZWF0dGxlMQ8wDQYDVQQKEwZBbWF6b24xFDASBgNVBAsTC0lBTSBDb25z b2xlMRIwEAYDVQQDEwlUZXN0Q2lsYWMxHzAdBgkqhkiG9w0BCQEWEG5vb25lQGFt YXpvbi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMaK0dn+a4GmWIWJ 21uUSfwfEvySWtC2XADZ4nB+BLYgVIk60CpiwsZ3G93vUEIO3IyNoH/f0wYK8m9T rDHudUZg3qX4waLG5M43q7Wgc/MbQITxOUSQv7c7ugFFDzQGBzZswY6786m86gpE Ibb3OhjZnzcvQAaRHhdlQWIMm2nrAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAtCu4 nUhVVxYUntneD9+h8Mg9q6q+auNKyExzyLwaxlAoo7TJHidbtS4J5iNmZgXL0Fkb FFBjvSfpJIlJ00zbhNYS5f6GuoEDmFJl0ZxBHjJnyp378OD8uTs7fLvjx79LjSTb NYiytVbZPQUQ5Yaxu2jXnimvw3rrszlaEXAMPLE Raises: SkipComponent: When content is empty or cannot be parsed. Attributes: signature (str): PKCS7 signature string including header and footer. Examples: >>> aws_id_sig.signature.startswith('-----BEGIN PKCS7-----\\nMIICiTCCAfICCQD6m7oRw0uXOjANBgkqhkiG9w0BAQUFADCBiDELMAkGA1UEBhMC\\n') True >>> aws_id_sig.signature.endswith('NYiytVbZPQUQ5Yaxu2jXnimvw3rrszlaEXAMPLE\\n-----END PKCS7-----') True """
[docs] def parse_content(self, content): _validate_content(content) # Just in case curl stats are present in data startline = 0 for l in content: if ' ' not in l.strip() and len(l.strip()) > 0: break startline += 1 self.signature = '-----BEGIN PKCS7-----\n' + '\n'.join([l.rstrip() for l in content[startline:]]) + "\n-----END PKCS7-----"
[docs] @parser(Specs.aws_public_ipv4_addresses) class AWSPublicIpv4Addresses(CommandParser, list): """ Class for parsing the AWS public IP. At the moment, a single instance can only have assigned one public IPv4 address on AWS EC2. This parsers takes the value and makes it a list just in case the capability is added later. The data is fetched via curl -s http://169.254.169.254/latest/meta-data/public-ipv4 command and contains a pure string, e.g. "1.2.3.4" without newline. Raises: SkipComponent: When content is empty or cannot be parsed. """
[docs] def parse_content(self, content): _validate_content(content, length=1) self.append(content[0])
[docs] @parser(Specs.aws_public_hostnames) class AWSPublicHostnames(CommandParser, list): """ Class for parsing the AWS public hostname. At the moment, a single instance can only have assigned one public IPv4 address on AWS EC2. This parsers takes the value and makes it a list just in case the capability is added later. The data is fetched via curl -s http://169.254.169.254/latest/meta-data/public-hostname command and contains a pure string, e.g. "ec2-1-2-3-4.us-east-1.awscloud.com" without newline. Raises: SkipComponent: When content is empty or cannot be parsed. """
[docs] def parse_content(self, content): _validate_content(content, length=1) self.append(content[0])