Repository: cloud-custodian/cloud-custodian

Issue:
Elasticsearch policy sending DomainName as Dict, expect STR
**Describe the bug**
Lambdas created using the Elasticsearch policy are passing the DomainName to the AWS API as a dictionary, and the API needs it to be a string. You can find a gist of the full error here:  https://gist.github.com/theotherothermatt/199f78ee33c0044dd2365583c9c3f604

Rolled back to version 0.9.1 and problem does not exist. There were commits to elasticsearch.py in both 0.9.2 and 0.9.3, so I think that the problem resides somewhere in those bug fixes.
 
**To Reproduce**
With c7n==0.9.3, use policy:
```yaml
    mode:
        type: cloudtrail
        role: arn:aws:iam::<$account-id>:role/the-correct-role
        events:
         - source: es.amazonaws.com
           event: CreateElasticsearchDomain
           ids: "requestParameters.domainName"
    filters:
      - type: value
        key: "EncryptionAtRestOptions.Enabled"
        value: false
    actions:
        - type: delete
```
Then create an ES domain that is not encrypted at rest. Error will be in log stream.

Roll back to c7n==0.9.1
Try the above policy again (on a new lambda of course)
Domain will be deleted with no error

**Expected behavior**
The ES Domain will be deleted

**Background (please complete the following information):**
 - OS: OSx 10.15.5
 - Python Version: python 3.7.7
 - Custodian Version: 0.9.3
 - Cloud Provider: AWS
 - Policy: [please exclude any account/sensitive information]
```yaml
    mode:
        type: cloudtrail
        role: arn:aws:iam::<$account-id>:role/the-correct-role
        events:
         - source: es.amazonaws.com
           event: CreateElasticsearchDomain
           ids: "requestParameters.domainName"
    filters:
      - type: value
        key: "EncryptionAtRestOptions.Enabled"
        value: false
    actions:
        - type: delete
```
 - `custodian version --debug` output
Custodian:   0.9.3
Python:      3.7.7 (default, Mar 10 2020, 15:43:03)
             [Clang 11.0.0 (clang-1100.0.33.17)]
Platform:    posix.uname_result(sysname='Darwin', nodename='', release='19.5.0', version='Darwin Kernel Version 19.5.0: Tue May 26 20:41:44 PDT 2020; root:xnu-6153.121.2~2/RELEASE_X86_64', machine='x86_64')
Using venv:  False
Docker: False
Installed:

argcomplete==1.11.1
attrs==19.3.0
boto3==1.13.24
botocore==1.16.24
docutils==0.15.2
importlib-metadata==1.6.1
jmespath==0.10.0
jsonschema==3.2.0
pyrsistent==0.16.0
python-dateutil==2.8.1
pyyaml==5.3.1
s3transfer==0.3.3
setuptools==46.0.0
six==1.15.0
tabulate==0.8.7
urllib3==1.25.9
zipp==3.1.0



Discussion:
I think this was fixed in #5796 (trunk only) but worth confirming


Resolving patch:
diff --git a/c7n/resources/elasticsearch.py b/c7n/resources/elasticsearch.py
--- a/c7n/resources/elasticsearch.py
+++ b/c7n/resources/elasticsearch.py
@@ -27,9 +27,8 @@
 class DescribeDomain(DescribeSource):
 
     def get_resources(self, resource_ids):
-        client = local_session(self.manager.session_factory).client('es')
-        return client.describe_elasticsearch_domains(
-            DomainNames=resource_ids)['DomainStatusList']
+        # augment will turn these into resource dictionaries
+        return resource_ids
 
     def augment(self, domains):
         client = local_session(self.manager.session_factory).client('es')


Test patch:
diff --git a/tests/data/placebo/test_elasticsearch_get/es.DescribeElasticsearchDomains_1.json b/tests/data/placebo/test_elasticsearch_get/es.DescribeElasticsearchDomains_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_elasticsearch_get/es.DescribeElasticsearchDomains_1.json
@@ -0,0 +1,73 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "DomainStatusList": [
+            {
+                "DomainId": "644160558196/devx",
+                "DomainName": "devx",
+                "ARN": "arn:aws:es:us-east-1:644160558196:domain/devx",
+                "Created": true,
+                "Deleted": false,
+                "Endpoint": "search-devx-ndp75qp7n4kaeh6fzvgngtputa.us-east-1.es.amazonaws.com",
+                "Processing": false,
+                "UpgradeProcessing": false,
+                "ElasticsearchVersion": "7.4",
+                "ElasticsearchClusterConfig": {
+                    "InstanceType": "r5.large.elasticsearch",
+                    "InstanceCount": 1,
+                    "DedicatedMasterEnabled": false,
+                    "ZoneAwarenessEnabled": false,
+                    "WarmEnabled": false
+                },
+                "EBSOptions": {
+                    "EBSEnabled": true,
+                    "VolumeType": "gp2",
+                    "VolumeSize": 10
+                },
+                "AccessPolicies": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":\"es:*\",\"Resource\":\"arn:aws:es:us-east-1:644160558196:domain/devx/*\"}]}",
+                "SnapshotOptions": {},
+                "CognitoOptions": {
+                    "Enabled": false
+                },
+                "EncryptionAtRestOptions": {
+                    "Enabled": true,
+                    "KmsKeyId": "arn:aws:kms:us-east-1:644160558196:key/6917a312-adce-4bbc-8202-958f2db490fa"
+                },
+                "NodeToNodeEncryptionOptions": {
+                    "Enabled": true
+                },
+                "AdvancedOptions": {
+                    "rest.action.multi.allow_explicit_index": "true"
+                },
+                "ServiceSoftwareOptions": {
+                    "CurrentVersion": "R20200522-p1",
+                    "NewVersion": "",
+                    "UpdateAvailable": false,
+                    "Cancellable": false,
+                    "UpdateStatus": "COMPLETED",
+                    "Description": "There is no software update available for this domain.",
+                    "AutomatedUpdateDate": {
+                        "__class__": "datetime",
+                        "year": 1969,
+                        "month": 12,
+                        "day": 31,
+                        "hour": 19,
+                        "minute": 0,
+                        "second": 0,
+                        "microsecond": 0
+                    },
+                    "OptionalDeployment": true
+                },
+                "DomainEndpointOptions": {
+                    "EnforceHTTPS": true,
+                    "TLSSecurityPolicy": "Policy-Min-TLS-1-0-2019-07"
+                },
+                "AdvancedSecurityOptions": {
+                    "Enabled": true,
+                    "InternalUserDatabaseEnabled": false
+                }
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_elasticsearch_get/es.ListTags_1.json b/tests/data/placebo/test_elasticsearch_get/es.ListTags_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_elasticsearch_get/es.ListTags_1.json
@@ -0,0 +1,7 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "TagList": []
+    }
+}
\ No newline at end of file
diff --git a/tests/test_elasticsearch.py b/tests/test_elasticsearch.py
--- a/tests/test_elasticsearch.py
+++ b/tests/test_elasticsearch.py
@@ -18,6 +18,17 @@
 
 class ElasticSearch(BaseTest):
 
+    def test_get_resources(self):
+        factory = self.replay_flight_data('test_elasticsearch_get')
+        p = self.load_policy({
+            'name': 'es-get',
+            'resource': 'aws.elasticsearch'},
+            session_factory=factory)
+        resources = p.resource_manager.get_resources(['devx'])
+        self.assertEqual(len(resources), 1)
+        self.assertEqual(
+            resources[0]['DomainName'], 'devx')
+
     def test_resource_manager(self):
         factory = self.replay_flight_data("test_elasticsearch_query")
         p = self.load_policy(