エスケープ処理されたJSON文字列を整形して必要な情報を抽出してみた
こんにちは!コンサル部のinomaso(@inomasosan)です。
前回、AWS Config アグリゲータで、Advanced Queryに対応していない起動テンプレートの情報を取得するためのサンプルコードを作成してみました。
ただ、出力結果の一部にエスケープ処理されたJSON文字列がありました。
そこから必要な情報を取得しようとしたところ、なかなか時間がかかってしまったので備忘として残しておきます。
エスケープ処理されたJSON文字列とは?
以下は起動テンプレートの出力結果となります。
{ "ConfigurationItem": { "version": "1.3", "accountId": "1234567890", "configurationItemCaptureTime": "2023-09-14T08:53:54.339000+00:00", "configurationItemStatus": "OK", "configurationStateId": "1694681634339", "configurationItemMD5Hash": "", "arn": "arn:aws:ec2:ap-northeast-1:1234567890:launch-template/lt-07cae1e5cb08b09f7", "resourceType": "AWS::EC2::LaunchTemplate", "resourceId": "lt-07cae1e5cb08b09f7", "resourceName": "asg-web-template", "awsRegion": "ap-northeast-1", "availabilityZone": "Regional", "tags": {}, "relatedEvents": [], "relationships": [], "configuration": "{\"LaunchTemplateName\":\"asg-web-template\",\"Id\":\"lt-07cae1e5cb08b09f7\",\"LaunchTemplateData\":{\"EbsOptimized\":false,\"BlockDeviceMappings\":[{\"DeviceName\":\"/dev/xvda\",\"Ebs\":{\"Encrypted\":false,\"DeleteOnTermination\":true,\"VolumeSize\":8,\"VolumeType\":\"gp2\"}}],\"NetworkInterfaces\":[{\"AssociatePublicIpAddress\":true,\"DeleteOnTermination\":true,\"Description\":\"Primary network interface\",\"DeviceIndex\":0,\"Groups\":[\"sg-07b90410018cd1533\"],\"Ipv6Addresses\":[],\"PrivateIpAddresses\":[],\"Ipv4Prefixes\":[],\"Ipv6Prefixes\":[]}],\"ImageId\":\"ami-09ebacdc178ae23b7\",\"InstanceType\":\"t2.micro\",\"KeyName\":\"aws-ssh-key\",\"Monitoring\":{\"Enabled\":false},\"Placement\":{\"Tenancy\":\"default\"},\"DisableApiTermination\":false,\"UserData\":\"IyEvYmluL2Jhc2gKeXVtIHVwZGF0ZSAteQp5dW0gaW5zdGFsbCAteSBodHRwZApzeXN0ZW1jdGwgc3RhcnQgaHR0cGQuc2VydmljZQpzeXN0ZW1jdGwgZW5hYmxlIGh0dHBkLnNlcnZpY2UKZWNobyDigJxIZWxsbyBXb3JsZCBmcm9tICQoaG9zdG5hbWUgLWYp4oCdID4gL3Zhci93d3cvaHRtbC9pbmRleC5odG1s\",\"TagSpecifications\":[],\"ElasticGpuSpecifications\":[],\"ElasticInferenceAccelerators\":[],\"SecurityGroupIds\":[],\"SecurityGroups\":[],\"CreditSpecification\":{\"CpuCredits\":\"standard\"},\"CapacityReservationSpecification\":{\"CapacityReservationPreference\":\"open\"},\"LicenseSpecifications\":[],\"MetadataOptions\":{\"HttpTokens\":\"optional\",\"HttpPutResponseHopLimit\":1,\"HttpEndpoint\":\"enabled\"}},\"DefaultVersionNumber\":\"1\",\"LatestVersionNumber\":\"2\",\"TagSpecifications\":[]}", "supplementaryConfiguration": {} } }
18行目の"configuration"
を見て頂けると分かる通り、JSONの中にJSONが埋まる形でエスケープ処理されたJSON文字列が出力されています。
ここから特定の値を取得するためには、前処理として整形から実施していく必要があります。
エスケープ処理された文字列を整形
まずは、エスケープ処理されたjson文字列を、fromjson
で見やすく整形していきます。
aws configservice list-aggregate-discovered-resources \ --configuration-aggregator-name hoge \ --resource-type AWS::EC2::LaunchTemplate \ --query "ResourceIdentifiers[*].[SourceAccountId, SourceRegion, ResourceId, ResourceType]" \ --output text | while read line do SourceAccountId=$(echo $line | awk '{print $1}') SourceRegion=$(echo $line | awk '{print $2}') ResourceId=$(echo $line | awk '{print $3}') ResourceType=$(echo $line | awk '{print $4}') #EOSの行はスペースを省略しないとエラーになる。ただし一つ目のEOSの行はスペースがあっても良い json=$(tr -d ' |\n' << EOS { "SourceAccountId" : "$SourceAccountId", "SourceRegion" : "$SourceRegion", "ResourceId" : "$ResourceId", "ResourceType" : "$ResourceType" } EOS ) aws configservice get-aggregate-resource-config \ --configuration-aggregator-name hoge \ --resource-identifier $json \ | jq '.ConfigurationItem.configuration | fromjson' done
エスケープ処理された出力結果と比較して、だいぶ見やすくなったことがわかります。
{ "LaunchTemplateName": "asg-web-template", "Id": "lt-07cae1e5cb08b09f7", "LaunchTemplateData": { "EbsOptimized": false, "BlockDeviceMappings": [ { "DeviceName": "/dev/xvda", "Ebs": { "Encrypted": false, "DeleteOnTermination": true, "VolumeSize": 8, "VolumeType": "gp2" } } ], "NetworkInterfaces": [ { "AssociatePublicIpAddress": true, "DeleteOnTermination": true, "Description": "Primary network interface", "DeviceIndex": 0, "Groups": [ "sg-07b90410018cd1533" ], "Ipv6Addresses": [], "PrivateIpAddresses": [], "Ipv4Prefixes": [], "Ipv6Prefixes": [] } ], "ImageId": "ami-09ebacdc178ae23b7", "InstanceType": "t2.micro", "KeyName": "aws-ssh-key", "Monitoring": { "Enabled": false }, "Placement": { "Tenancy": "default" }, "DisableApiTermination": false, "UserData": "IyEvYmluL2Jhc2gKeXVtIHVwZGF0ZSAteQp5dW0gaW5zdGFsbCAteSBodHRwZApzeXN0ZW1jdGwgc3RhcnQgaHR0cGQuc2VydmljZQpzeXN0ZW1jdGwgZW5hYmxlIGh0dHBkLnNlcnZpY2UKZWNobyDigJxIZWxsbyBXb3JsZCBmcm9tICQoaG9zdG5hbWUgLWYp4oCdID4gL3Zhci93d3cvaHRtbC9pbmRleC5odG1s", "TagSpecifications": [], "ElasticGpuSpecifications": [], "ElasticInferenceAccelerators": [], "SecurityGroupIds": [], "SecurityGroups": [], "CreditSpecification": { "CpuCredits": "standard" }, "CapacityReservationSpecification": { "CapacityReservationPreference": "open" }, "LicenseSpecifications": [], "MetadataOptions": { "HttpTokens": "optional", "HttpPutResponseHopLimit": 1, "HttpEndpoint": "enabled" } }, "DefaultVersionNumber": "1", "LatestVersionNumber": "2", "TagSpecifications": [] }
整形した文字列から必要な情報を抽出
先ほど整形した文字列から、JSON形式でセキュリティグループID関連の情報を取得してみます。
aws configservice list-aggregate-discovered-resources \ --configuration-aggregator-name hoge \ --resource-type AWS::EC2::LaunchTemplate \ --query "ResourceIdentifiers[*].[SourceAccountId, SourceRegion, ResourceId, ResourceType]" \ --output text | while read line do SourceAccountId=$(echo $line | awk '{print $1}') SourceRegion=$(echo $line | awk '{print $2}') ResourceId=$(echo $line | awk '{print $3}') ResourceType=$(echo $line | awk '{print $4}') #EOSの行はスペースを省略しないとエラーになる。ただし一つ目のEOSの行はスペースがあっても良い json=$(tr -d ' |\n' << EOS { "SourceAccountId" : "$SourceAccountId", "SourceRegion" : "$SourceRegion", "ResourceId" : "$ResourceId", "ResourceType" : "$ResourceType" } EOS ) aws configservice get-aggregate-resource-config \ --configuration-aggregator-name hoge \ --resource-identifier $json \ | jq '.ConfigurationItem.configuration | fromjson' | jq '{LaunchTemplateName: .LaunchTemplateName, Id: .Id,Groups: .LaunchTemplateData.NetworkInterfaces[].Groups[]}' done
{ "LaunchTemplateName": "asg-web-template", "Id": "lt-07cae1e5cb08b09f7", "Groups": "sg-07b90410018cd1533" }
まとめ
エスケープ処理されたJSON文字列を最初に見たときは面食らいました。
jq
での必要な情報の抽出は、インターネット上での情報収集に苦労したため今回まとめてみました。
この記事が、どなたかのお役に立てば幸いです。それでは!