We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
aws.cloudtrail status IsLogging fails with KeyError: 'c7n:TrailStatus'
**Describe the bug**
cloudtrail status / IsLogging returns key error KeyError: 'c7n:TrailStatus'

https://cloudcustodian.io/docs/aws/resources/cloudtrail.html#status indicates this should work.

**To Reproduce**
Authenticate to an account that has both an Organizational trail and local trail.

Policy file:
```yaml
  - name: awslogs-cloudtrail
    resource: aws.cloudtrail
    filters:
      - type: status
        key: IsLogging
        value: True
```

Output is:
```
2020-05-05 09:03:16,332: custodian.commands:ERROR Error while executing policy awslogs-cloudtrail, continuing
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/c7n/commands.py", line 281, in run
    policy()
  File "/usr/local/lib/python3.7/site-packages/c7n/policy.py", line 1062, in __call__
    resources = mode.run()
  File "/usr/local/lib/python3.7/site-packages/c7n/policy.py", line 291, in run
    resources = self.policy.resource_manager.resources()
  File "/usr/local/lib/python3.7/site-packages/c7n/query.py", line 466, in resources
    resources = self.filter_resources(resources)
  File "/usr/local/lib/python3.7/site-packages/c7n/manager.py", line 109, in filter_resources
    resources = f.process(resources, event)
  File "/usr/local/lib/python3.7/site-packages/c7n/resources/cloudtrail.py", line 122, in process
    return super(Status, self).process(resources)
  File "/usr/local/lib/python3.7/site-packages/c7n/filters/core.py", line 499, in process
    return super(ValueFilter, self).process(resources, event)
  File "/usr/local/lib/python3.7/site-packages/c7n/filters/core.py", line 197, in process
    return list(filter(self, resources))
  File "/usr/local/lib/python3.7/site-packages/c7n/resources/cloudtrail.py", line 125, in __call__
    return self.match(r['c7n:TrailStatus'])
KeyError: 'c7n:TrailStatus'
```

**Expected behavior**
Only CloudTrails that are enabled are returned, no error.


**Background (please complete the following information):**
 - OS: OSX 10.14.6
 - Python Version: Python 3.7.4
 - Custodian Version: 0.9.1
 - Cloud Provider: aws
 - Policy:
```yaml
policies: 
  - name: awslogs-cloudtrail
    resource: cloudtrail
    filters:
      - type: status
        key: IsLogging
        value: True
```
 - Traceback: [if applicable, please exclude sensitive/account information]
 ```
Custodian:   0.9.1
Python:      3.7.4 (default, Sep  7 2019, 18:27:02)
             [Clang 10.0.1 (clang-1001.0.46.4)]
Platform:    posix.uname_result(sysname='Darwin', nodename='xxx', release='18.7.0', version='Darwin Kernel Version 18.7.0: Tue Aug 20 16:57:14 PDT 2019; root:xnu-4903.271.2~2/RELEASE_X86_64', machine='x86_64')
Using venv:  False
Docker: False
Installed:

argcomplete==1.11.1
attrs==19.3.0
boto3==1.12.47
botocore==1.15.47
docutils==0.15.2
importlib-metadata==1.6.0
jmespath==0.9.5
jsonschema==3.2.0
pyrsistent==0.16.0
python-dateutil==2.8.1
pyyaml==5.3.1
s3transfer==0.3.3
setuptools==41.0.1
six==1.14.0
tabulate==0.8.7
urllib3==1.25.9
zipp==3.1.0
```

Under --debug, self has:
```
(Pdb) p dir(self)
['__call__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_validate_resource_count', '_validate_value_regex', 'annotate', 'annotation_key', 'data', 'executor_factory', 'expr', 'get_block_operator', 'get_permissions', 'get_resource_value', 'log', 'manager', 'match', 'merge_annotation', 'metrics', 'op', 'permissions', 'process', 'process_value_type', 'required_keys', 'schema', 'schema_alias', 'type', 'type_aliases', 'v', 'validate', 'vtype']
```

Adding this filter _before_ the status filter works around the issue:
```yaml
      - type: is-shadow
        state: False
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `c7n/resources/cloudtrail.py`
Content:
```
1 # Copyright 2017-2019 Capital One Services, LLC
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 import logging
15 
16 from c7n.actions import Action, BaseAction
17 from c7n.exceptions import PolicyValidationError
18 from c7n.filters import ValueFilter, Filter
19 from c7n.manager import resources
20 from c7n.tags import universal_augment
21 from c7n.query import ConfigSource, DescribeSource, QueryResourceManager, TypeInfo
22 from c7n.utils import local_session, type_schema
23 
24 from .aws import shape_validate, Arn
25 
26 log = logging.getLogger('c7n.resources.cloudtrail')
27 
28 
29 class DescribeTrail(DescribeSource):
30 
31     def augment(self, resources):
32         return universal_augment(self.manager, resources)
33 
34 
35 @resources.register('cloudtrail')
36 class CloudTrail(QueryResourceManager):
37 
38     class resource_type(TypeInfo):
39         service = 'cloudtrail'
40         enum_spec = ('describe_trails', 'trailList', None)
41         filter_name = 'trailNameList'
42         filter_type = 'list'
43         arn = id = 'TrailARN'
44         name = 'Name'
45         cfn_type = config_type = "AWS::CloudTrail::Trail"
46         universal_taggable = object()
47 
48     source_mapping = {
49         'describe': DescribeTrail,
50         'config': ConfigSource
51     }
52 
53 
54 @CloudTrail.filter_registry.register('is-shadow')
55 class IsShadow(Filter):
56     """Identify shadow trails (secondary copies), shadow trails
57     can't be modified directly, the origin trail needs to be modified.
58 
59     Shadow trails are created for multi-region trails as well for
60     organizational trails.
61     """
62     schema = type_schema('is-shadow', state={'type': 'boolean'})
63     permissions = ('cloudtrail:DescribeTrails',)
64     embedded = False
65 
66     def process(self, resources, event=None):
67         rcount = len(resources)
68         trails = [t for t in resources if (self.is_shadow(t) == self.data.get('state', True))]
69         if len(trails) != rcount and self.embedded:
70             self.log.info("implicitly filtering shadow trails %d -> %d",
71                      rcount, len(trails))
72         return trails
73 
74     def is_shadow(self, t):
75         if t.get('IsOrganizationTrail') and self.manager.config.account_id not in t['TrailARN']:
76             return True
77         if t.get('IsMultiRegionTrail') and t['HomeRegion'] != self.manager.config.region:
78             return True
79         return False
80 
81 
82 @CloudTrail.filter_registry.register('status')
83 class Status(ValueFilter):
84     """Filter a cloudtrail by its status.
85 
86     :Example:
87 
88     .. code-block:: yaml
89 
90         policies:
91           - name: cloudtrail-check-status
92             resource: aws.cloudtrail
93             filters:
94             - type: status
95               key: IsLogging
96               value: False
97     """
98 
99     schema = type_schema('status', rinherit=ValueFilter.schema)
100     schema_alias = False
101     permissions = ('cloudtrail:GetTrailStatus',)
102     annotation_key = 'c7n:TrailStatus'
103 
104     def process(self, resources, event=None):
105         for r in resources:
106             region = self.manager.config.region
107             trail_arn = Arn.parse(r['TrailARN'])
108 
109             if (r.get('IsOrganizationTrail') and
110                     self.manager.config.account_id != trail_arn.account_id):
111                 continue
112             if r.get('HomeRegion') and r['HomeRegion'] != region:
113                 region = trail_arn.region
114             if self.annotation_key in r:
115                 continue
116             client = local_session(self.manager.session_factory).client(
117                 'cloudtrail', region_name=region)
118             status = client.get_trail_status(Name=r['Name'])
119             status.pop('ResponseMetadata')
120             r[self.annotation_key] = status
121 
122         return super(Status, self).process(resources)
123 
124     def __call__(self, r):
125         return self.match(r['c7n:TrailStatus'])
126 
127 
128 @CloudTrail.action_registry.register('update-trail')
129 class UpdateTrail(Action):
130     """Update trail attributes.
131 
132     :Example:
133 
134     .. code-block:: yaml
135 
136        policies:
137          - name: cloudtrail-set-log
138            resource: aws.cloudtrail
139            filters:
140             - or:
141               - KmsKeyId: empty
142               - LogFileValidationEnabled: false
143            actions:
144             - type: update-trail
145               attributes:
146                 KmsKeyId: arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef
147                 EnableLogFileValidation: true
148     """
149     schema = type_schema(
150         'update-trail',
151         attributes={'type': 'object'},
152         required=('attributes',))
153     shape = 'UpdateTrailRequest'
154     permissions = ('cloudtrail:UpdateTrail',)
155 
156     def validate(self):
157         attrs = dict(self.data['attributes'])
158         if 'Name' in attrs:
159             raise PolicyValidationError(
160                 "Can't include Name in update-trail action")
161         attrs['Name'] = 'PolicyValidation'
162         return shape_validate(
163             attrs,
164             self.shape,
165             self.manager.resource_type.service)
166 
167     def process(self, resources):
168         client = local_session(self.manager.session_factory).client('cloudtrail')
169         shadow_check = IsShadow({'state': False}, self.manager)
170         shadow_check.embedded = True
171         resources = shadow_check.process(resources)
172 
173         for r in resources:
174             client.update_trail(
175                 Name=r['Name'],
176                 **self.data['attributes'])
177 
178 
179 @CloudTrail.action_registry.register('set-logging')
180 class SetLogging(Action):
181     """Set the logging state of a trail
182 
183     :Example:
184 
185     .. code-block:: yaml
186 
187       policies:
188         - name: cloudtrail-set-active
189           resource: aws.cloudtrail
190           filters:
191            - type: status
192              key: IsLogging
193              value: False
194           actions:
195            - type: set-logging
196              enabled: True
197     """
198     schema = type_schema(
199         'set-logging', enabled={'type': 'boolean'})
200 
201     def get_permissions(self):
202         enable = self.data.get('enabled', True)
203         if enable is True:
204             return ('cloudtrail:StartLogging',)
205         else:
206             return ('cloudtrail:StopLogging',)
207 
208     def process(self, resources):
209         client = local_session(self.manager.session_factory).client('cloudtrail')
210         shadow_check = IsShadow({'state': False}, self.manager)
211         shadow_check.embedded = True
212         resources = shadow_check.process(resources)
213         enable = self.data.get('enabled', True)
214 
215         for r in resources:
216             if enable:
217                 client.start_logging(Name=r['Name'])
218             else:
219                 client.stop_logging(Name=r['Name'])
220 
221 
222 @CloudTrail.action_registry.register('delete')
223 class DeleteTrail(BaseAction):
224     """ Delete a cloud trail
225 
226     :example:
227 
228     .. code-block:: yaml
229 
230       policies:
231         - name: delete-cloudtrail
232           resource: aws.cloudtrail
233           filters:
234            - type: value
235              key: Name
236              value: delete-me
237              op: eq
238           actions:
239            - type: delete
240     """
241 
242     schema = type_schema('delete')
243     permissions = ('cloudtrail:DeleteTrail',)
244 
245     def process(self, resources):
246         client = local_session(self.manager.session_factory).client('cloudtrail')
247         shadow_check = IsShadow({'state': False}, self.manager)
248         shadow_check.embedded = True
249         resources = shadow_check.process(resources)
250         for r in resources:
251             try:
252                 client.delete_trail(Name=r['Name'])
253             except client.exceptions.TrailNotFoundException:
254                 continue
255
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/c7n/resources/cloudtrail.py b/c7n/resources/cloudtrail.py
--- a/c7n/resources/cloudtrail.py
+++ b/c7n/resources/cloudtrail.py
@@ -102,12 +102,16 @@
     annotation_key = 'c7n:TrailStatus'
 
     def process(self, resources, event=None):
+
+        non_account_trails = set()
+
         for r in resources:
             region = self.manager.config.region
             trail_arn = Arn.parse(r['TrailARN'])
 
             if (r.get('IsOrganizationTrail') and
                     self.manager.config.account_id != trail_arn.account_id):
+                non_account_trails.add(r['TrailARN'])
                 continue
             if r.get('HomeRegion') and r['HomeRegion'] != region:
                 region = trail_arn.region
@@ -119,7 +123,12 @@
             status.pop('ResponseMetadata')
             r[self.annotation_key] = status
 
-        return super(Status, self).process(resources)
+        if non_account_trails:
+            self.log.warning(
+                'found %d org cloud trail from different account that cant be processed',
+                len(non_account_trails))
+        return super(Status, self).process([
+            r for r in resources if r['TrailARN'] not in non_account_trails])
 
     def __call__(self, r):
         return self.match(r['c7n:TrailStatus'])

{"golden_diff": "diff --git a/c7n/resources/cloudtrail.py b/c7n/resources/cloudtrail.py\n--- a/c7n/resources/cloudtrail.py\n+++ b/c7n/resources/cloudtrail.py\n@@ -102,12 +102,16 @@\n     annotation_key = 'c7n:TrailStatus'\n \n     def process(self, resources, event=None):\n+\n+        non_account_trails = set()\n+\n         for r in resources:\n             region = self.manager.config.region\n             trail_arn = Arn.parse(r['TrailARN'])\n \n             if (r.get('IsOrganizationTrail') and\n                     self.manager.config.account_id != trail_arn.account_id):\n+                non_account_trails.add(r['TrailARN'])\n                 continue\n             if r.get('HomeRegion') and r['HomeRegion'] != region:\n                 region = trail_arn.region\n@@ -119,7 +123,12 @@\n             status.pop('ResponseMetadata')\n             r[self.annotation_key] = status\n \n-        return super(Status, self).process(resources)\n+        if non_account_trails:\n+            self.log.warning(\n+                'found %d org cloud trail from different account that cant be processed',\n+                len(non_account_trails))\n+        return super(Status, self).process([\n+            r for r in resources if r['TrailARN'] not in non_account_trails])\n \n     def __call__(self, r):\n         return self.match(r['c7n:TrailStatus'])\n", "issue": "aws.cloudtrail status IsLogging fails with KeyError: 'c7n:TrailStatus'\n**Describe the bug**\r\ncloudtrail status / IsLogging returns key error KeyError: 'c7n:TrailStatus'\r\n\r\nhttps://cloudcustodian.io/docs/aws/resources/cloudtrail.html#status indicates this should work.\r\n\r\n**To Reproduce**\r\nAuthenticate to an account that has both an Organizational trail and local trail.\r\n\r\nPolicy file:\r\n```yaml\r\n  - name: awslogs-cloudtrail\r\n    resource: aws.cloudtrail\r\n    filters:\r\n      - type: status\r\n        key: IsLogging\r\n        value: True\r\n```\r\n\r\nOutput is:\r\n```\r\n2020-05-05 09:03:16,332: custodian.commands:ERROR Error while executing policy awslogs-cloudtrail, continuing\r\nTraceback (most recent call last):\r\n  File \"/usr/local/lib/python3.7/site-packages/c7n/commands.py\", line 281, in run\r\n    policy()\r\n  File \"/usr/local/lib/python3.7/site-packages/c7n/policy.py\", line 1062, in __call__\r\n    resources = mode.run()\r\n  File \"/usr/local/lib/python3.7/site-packages/c7n/policy.py\", line 291, in run\r\n    resources = self.policy.resource_manager.resources()\r\n  File \"/usr/local/lib/python3.7/site-packages/c7n/query.py\", line 466, in resources\r\n    resources = self.filter_resources(resources)\r\n  File \"/usr/local/lib/python3.7/site-packages/c7n/manager.py\", line 109, in filter_resources\r\n    resources = f.process(resources, event)\r\n  File \"/usr/local/lib/python3.7/site-packages/c7n/resources/cloudtrail.py\", line 122, in process\r\n    return super(Status, self).process(resources)\r\n  File \"/usr/local/lib/python3.7/site-packages/c7n/filters/core.py\", line 499, in process\r\n    return super(ValueFilter, self).process(resources, event)\r\n  File \"/usr/local/lib/python3.7/site-packages/c7n/filters/core.py\", line 197, in process\r\n    return list(filter(self, resources))\r\n  File \"/usr/local/lib/python3.7/site-packages/c7n/resources/cloudtrail.py\", line 125, in __call__\r\n    return self.match(r['c7n:TrailStatus'])\r\nKeyError: 'c7n:TrailStatus'\r\n```\r\n\r\n**Expected behavior**\r\nOnly CloudTrails that are enabled are returned, no error.\r\n\r\n\r\n**Background (please complete the following information):**\r\n - OS: OSX 10.14.6\r\n - Python Version: Python 3.7.4\r\n - Custodian Version: 0.9.1\r\n - Cloud Provider: aws\r\n - Policy:\r\n```yaml\r\npolicies: \r\n  - name: awslogs-cloudtrail\r\n    resource: cloudtrail\r\n    filters:\r\n      - type: status\r\n        key: IsLogging\r\n        value: True\r\n```\r\n - Traceback: [if applicable, please exclude sensitive/account information]\r\n ```\r\nCustodian:   0.9.1\r\nPython:      3.7.4 (default, Sep  7 2019, 18:27:02)\r\n             [Clang 10.0.1 (clang-1001.0.46.4)]\r\nPlatform:    posix.uname_result(sysname='Darwin', nodename='xxx', release='18.7.0', version='Darwin Kernel Version 18.7.0: Tue Aug 20 16:57:14 PDT 2019; root:xnu-4903.271.2~2/RELEASE_X86_64', machine='x86_64')\r\nUsing venv:  False\r\nDocker: False\r\nInstalled:\r\n\r\nargcomplete==1.11.1\r\nattrs==19.3.0\r\nboto3==1.12.47\r\nbotocore==1.15.47\r\ndocutils==0.15.2\r\nimportlib-metadata==1.6.0\r\njmespath==0.9.5\r\njsonschema==3.2.0\r\npyrsistent==0.16.0\r\npython-dateutil==2.8.1\r\npyyaml==5.3.1\r\ns3transfer==0.3.3\r\nsetuptools==41.0.1\r\nsix==1.14.0\r\ntabulate==0.8.7\r\nurllib3==1.25.9\r\nzipp==3.1.0\r\n```\r\n\r\nUnder --debug, self has:\r\n```\r\n(Pdb) p dir(self)\r\n['__call__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_validate_resource_count', '_validate_value_regex', 'annotate', 'annotation_key', 'data', 'executor_factory', 'expr', 'get_block_operator', 'get_permissions', 'get_resource_value', 'log', 'manager', 'match', 'merge_annotation', 'metrics', 'op', 'permissions', 'process', 'process_value_type', 'required_keys', 'schema', 'schema_alias', 'type', 'type_aliases', 'v', 'validate', 'vtype']\r\n```\r\n\r\nAdding this filter _before_ the status filter works around the issue:\r\n```yaml\r\n      - type: is-shadow\r\n        state: False\r\n```\n", "before_files": [{"content": "# Copyright 2017-2019 Capital One Services, LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\n\nfrom c7n.actions import Action, BaseAction\nfrom c7n.exceptions import PolicyValidationError\nfrom c7n.filters import ValueFilter, Filter\nfrom c7n.manager import resources\nfrom c7n.tags import universal_augment\nfrom c7n.query import ConfigSource, DescribeSource, QueryResourceManager, TypeInfo\nfrom c7n.utils import local_session, type_schema\n\nfrom .aws import shape_validate, Arn\n\nlog = logging.getLogger('c7n.resources.cloudtrail')\n\n\nclass DescribeTrail(DescribeSource):\n\n    def augment(self, resources):\n        return universal_augment(self.manager, resources)\n\n\n@resources.register('cloudtrail')\nclass CloudTrail(QueryResourceManager):\n\n    class resource_type(TypeInfo):\n        service = 'cloudtrail'\n        enum_spec = ('describe_trails', 'trailList', None)\n        filter_name = 'trailNameList'\n        filter_type = 'list'\n        arn = id = 'TrailARN'\n        name = 'Name'\n        cfn_type = config_type = \"AWS::CloudTrail::Trail\"\n        universal_taggable = object()\n\n    source_mapping = {\n        'describe': DescribeTrail,\n        'config': ConfigSource\n    }\n\n\n@CloudTrail.filter_registry.register('is-shadow')\nclass IsShadow(Filter):\n    \"\"\"Identify shadow trails (secondary copies), shadow trails\n    can't be modified directly, the origin trail needs to be modified.\n\n    Shadow trails are created for multi-region trails as well for\n    organizational trails.\n    \"\"\"\n    schema = type_schema('is-shadow', state={'type': 'boolean'})\n    permissions = ('cloudtrail:DescribeTrails',)\n    embedded = False\n\n    def process(self, resources, event=None):\n        rcount = len(resources)\n        trails = [t for t in resources if (self.is_shadow(t) == self.data.get('state', True))]\n        if len(trails) != rcount and self.embedded:\n            self.log.info(\"implicitly filtering shadow trails %d -> %d\",\n                     rcount, len(trails))\n        return trails\n\n    def is_shadow(self, t):\n        if t.get('IsOrganizationTrail') and self.manager.config.account_id not in t['TrailARN']:\n            return True\n        if t.get('IsMultiRegionTrail') and t['HomeRegion'] != self.manager.config.region:\n            return True\n        return False\n\n\n@CloudTrail.filter_registry.register('status')\nclass Status(ValueFilter):\n    \"\"\"Filter a cloudtrail by its status.\n\n    :Example:\n\n    .. code-block:: yaml\n\n        policies:\n          - name: cloudtrail-check-status\n            resource: aws.cloudtrail\n            filters:\n            - type: status\n              key: IsLogging\n              value: False\n    \"\"\"\n\n    schema = type_schema('status', rinherit=ValueFilter.schema)\n    schema_alias = False\n    permissions = ('cloudtrail:GetTrailStatus',)\n    annotation_key = 'c7n:TrailStatus'\n\n    def process(self, resources, event=None):\n        for r in resources:\n            region = self.manager.config.region\n            trail_arn = Arn.parse(r['TrailARN'])\n\n            if (r.get('IsOrganizationTrail') and\n                    self.manager.config.account_id != trail_arn.account_id):\n                continue\n            if r.get('HomeRegion') and r['HomeRegion'] != region:\n                region = trail_arn.region\n            if self.annotation_key in r:\n                continue\n            client = local_session(self.manager.session_factory).client(\n                'cloudtrail', region_name=region)\n            status = client.get_trail_status(Name=r['Name'])\n            status.pop('ResponseMetadata')\n            r[self.annotation_key] = status\n\n        return super(Status, self).process(resources)\n\n    def __call__(self, r):\n        return self.match(r['c7n:TrailStatus'])\n\n\n@CloudTrail.action_registry.register('update-trail')\nclass UpdateTrail(Action):\n    \"\"\"Update trail attributes.\n\n    :Example:\n\n    .. code-block:: yaml\n\n       policies:\n         - name: cloudtrail-set-log\n           resource: aws.cloudtrail\n           filters:\n            - or:\n              - KmsKeyId: empty\n              - LogFileValidationEnabled: false\n           actions:\n            - type: update-trail\n              attributes:\n                KmsKeyId: arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef\n                EnableLogFileValidation: true\n    \"\"\"\n    schema = type_schema(\n        'update-trail',\n        attributes={'type': 'object'},\n        required=('attributes',))\n    shape = 'UpdateTrailRequest'\n    permissions = ('cloudtrail:UpdateTrail',)\n\n    def validate(self):\n        attrs = dict(self.data['attributes'])\n        if 'Name' in attrs:\n            raise PolicyValidationError(\n                \"Can't include Name in update-trail action\")\n        attrs['Name'] = 'PolicyValidation'\n        return shape_validate(\n            attrs,\n            self.shape,\n            self.manager.resource_type.service)\n\n    def process(self, resources):\n        client = local_session(self.manager.session_factory).client('cloudtrail')\n        shadow_check = IsShadow({'state': False}, self.manager)\n        shadow_check.embedded = True\n        resources = shadow_check.process(resources)\n\n        for r in resources:\n            client.update_trail(\n                Name=r['Name'],\n                **self.data['attributes'])\n\n\n@CloudTrail.action_registry.register('set-logging')\nclass SetLogging(Action):\n    \"\"\"Set the logging state of a trail\n\n    :Example:\n\n    .. code-block:: yaml\n\n      policies:\n        - name: cloudtrail-set-active\n          resource: aws.cloudtrail\n          filters:\n           - type: status\n             key: IsLogging\n             value: False\n          actions:\n           - type: set-logging\n             enabled: True\n    \"\"\"\n    schema = type_schema(\n        'set-logging', enabled={'type': 'boolean'})\n\n    def get_permissions(self):\n        enable = self.data.get('enabled', True)\n        if enable is True:\n            return ('cloudtrail:StartLogging',)\n        else:\n            return ('cloudtrail:StopLogging',)\n\n    def process(self, resources):\n        client = local_session(self.manager.session_factory).client('cloudtrail')\n        shadow_check = IsShadow({'state': False}, self.manager)\n        shadow_check.embedded = True\n        resources = shadow_check.process(resources)\n        enable = self.data.get('enabled', True)\n\n        for r in resources:\n            if enable:\n                client.start_logging(Name=r['Name'])\n            else:\n                client.stop_logging(Name=r['Name'])\n\n\n@CloudTrail.action_registry.register('delete')\nclass DeleteTrail(BaseAction):\n    \"\"\" Delete a cloud trail\n\n    :example:\n\n    .. code-block:: yaml\n\n      policies:\n        - name: delete-cloudtrail\n          resource: aws.cloudtrail\n          filters:\n           - type: value\n             key: Name\n             value: delete-me\n             op: eq\n          actions:\n           - type: delete\n    \"\"\"\n\n    schema = type_schema('delete')\n    permissions = ('cloudtrail:DeleteTrail',)\n\n    def process(self, resources):\n        client = local_session(self.manager.session_factory).client('cloudtrail')\n        shadow_check = IsShadow({'state': False}, self.manager)\n        shadow_check.embedded = True\n        resources = shadow_check.process(resources)\n        for r in resources:\n            try:\n                client.delete_trail(Name=r['Name'])\n            except client.exceptions.TrailNotFoundException:\n                continue\n", "path": "c7n/resources/cloudtrail.py"}], "after_files": [{"content": "# Copyright 2017-2019 Capital One Services, LLC\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport logging\n\nfrom c7n.actions import Action, BaseAction\nfrom c7n.exceptions import PolicyValidationError\nfrom c7n.filters import ValueFilter, Filter\nfrom c7n.manager import resources\nfrom c7n.tags import universal_augment\nfrom c7n.query import ConfigSource, DescribeSource, QueryResourceManager, TypeInfo\nfrom c7n.utils import local_session, type_schema\n\nfrom .aws import shape_validate, Arn\n\nlog = logging.getLogger('c7n.resources.cloudtrail')\n\n\nclass DescribeTrail(DescribeSource):\n\n    def augment(self, resources):\n        return universal_augment(self.manager, resources)\n\n\n@resources.register('cloudtrail')\nclass CloudTrail(QueryResourceManager):\n\n    class resource_type(TypeInfo):\n        service = 'cloudtrail'\n        enum_spec = ('describe_trails', 'trailList', None)\n        filter_name = 'trailNameList'\n        filter_type = 'list'\n        arn = id = 'TrailARN'\n        name = 'Name'\n        cfn_type = config_type = \"AWS::CloudTrail::Trail\"\n        universal_taggable = object()\n\n    source_mapping = {\n        'describe': DescribeTrail,\n        'config': ConfigSource\n    }\n\n\n@CloudTrail.filter_registry.register('is-shadow')\nclass IsShadow(Filter):\n    \"\"\"Identify shadow trails (secondary copies), shadow trails\n    can't be modified directly, the origin trail needs to be modified.\n\n    Shadow trails are created for multi-region trails as well for\n    organizational trails.\n    \"\"\"\n    schema = type_schema('is-shadow', state={'type': 'boolean'})\n    permissions = ('cloudtrail:DescribeTrails',)\n    embedded = False\n\n    def process(self, resources, event=None):\n        rcount = len(resources)\n        trails = [t for t in resources if (self.is_shadow(t) == self.data.get('state', True))]\n        if len(trails) != rcount and self.embedded:\n            self.log.info(\"implicitly filtering shadow trails %d -> %d\",\n                     rcount, len(trails))\n        return trails\n\n    def is_shadow(self, t):\n        if t.get('IsOrganizationTrail') and self.manager.config.account_id not in t['TrailARN']:\n            return True\n        if t.get('IsMultiRegionTrail') and t['HomeRegion'] != self.manager.config.region:\n            return True\n        return False\n\n\n@CloudTrail.filter_registry.register('status')\nclass Status(ValueFilter):\n    \"\"\"Filter a cloudtrail by its status.\n\n    :Example:\n\n    .. code-block:: yaml\n\n        policies:\n          - name: cloudtrail-check-status\n            resource: aws.cloudtrail\n            filters:\n            - type: status\n              key: IsLogging\n              value: False\n    \"\"\"\n\n    schema = type_schema('status', rinherit=ValueFilter.schema)\n    schema_alias = False\n    permissions = ('cloudtrail:GetTrailStatus',)\n    annotation_key = 'c7n:TrailStatus'\n\n    def process(self, resources, event=None):\n\n        non_account_trails = set()\n\n        for r in resources:\n            region = self.manager.config.region\n            trail_arn = Arn.parse(r['TrailARN'])\n\n            if (r.get('IsOrganizationTrail') and\n                    self.manager.config.account_id != trail_arn.account_id):\n                non_account_trails.add(r['TrailARN'])\n                continue\n            if r.get('HomeRegion') and r['HomeRegion'] != region:\n                region = trail_arn.region\n            if self.annotation_key in r:\n                continue\n            client = local_session(self.manager.session_factory).client(\n                'cloudtrail', region_name=region)\n            status = client.get_trail_status(Name=r['Name'])\n            status.pop('ResponseMetadata')\n            r[self.annotation_key] = status\n\n        if non_account_trails:\n            self.log.warning(\n                'found %d org cloud trail from different account that cant be processed',\n                len(non_account_trails))\n        return super(Status, self).process([\n            r for r in resources if r['TrailARN'] not in non_account_trails])\n\n    def __call__(self, r):\n        return self.match(r['c7n:TrailStatus'])\n\n\n@CloudTrail.action_registry.register('update-trail')\nclass UpdateTrail(Action):\n    \"\"\"Update trail attributes.\n\n    :Example:\n\n    .. code-block:: yaml\n\n       policies:\n         - name: cloudtrail-set-log\n           resource: aws.cloudtrail\n           filters:\n            - or:\n              - KmsKeyId: empty\n              - LogFileValidationEnabled: false\n           actions:\n            - type: update-trail\n              attributes:\n                KmsKeyId: arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef\n                EnableLogFileValidation: true\n    \"\"\"\n    schema = type_schema(\n        'update-trail',\n        attributes={'type': 'object'},\n        required=('attributes',))\n    shape = 'UpdateTrailRequest'\n    permissions = ('cloudtrail:UpdateTrail',)\n\n    def validate(self):\n        attrs = dict(self.data['attributes'])\n        if 'Name' in attrs:\n            raise PolicyValidationError(\n                \"Can't include Name in update-trail action\")\n        attrs['Name'] = 'PolicyValidation'\n        return shape_validate(\n            attrs,\n            self.shape,\n            self.manager.resource_type.service)\n\n    def process(self, resources):\n        client = local_session(self.manager.session_factory).client('cloudtrail')\n        shadow_check = IsShadow({'state': False}, self.manager)\n        shadow_check.embedded = True\n        resources = shadow_check.process(resources)\n\n        for r in resources:\n            client.update_trail(\n                Name=r['Name'],\n                **self.data['attributes'])\n\n\n@CloudTrail.action_registry.register('set-logging')\nclass SetLogging(Action):\n    \"\"\"Set the logging state of a trail\n\n    :Example:\n\n    .. code-block:: yaml\n\n      policies:\n        - name: cloudtrail-set-active\n          resource: aws.cloudtrail\n          filters:\n           - type: status\n             key: IsLogging\n             value: False\n          actions:\n           - type: set-logging\n             enabled: True\n    \"\"\"\n    schema = type_schema(\n        'set-logging', enabled={'type': 'boolean'})\n\n    def get_permissions(self):\n        enable = self.data.get('enabled', True)\n        if enable is True:\n            return ('cloudtrail:StartLogging',)\n        else:\n            return ('cloudtrail:StopLogging',)\n\n    def process(self, resources):\n        client = local_session(self.manager.session_factory).client('cloudtrail')\n        shadow_check = IsShadow({'state': False}, self.manager)\n        shadow_check.embedded = True\n        resources = shadow_check.process(resources)\n        enable = self.data.get('enabled', True)\n\n        for r in resources:\n            if enable:\n                client.start_logging(Name=r['Name'])\n            else:\n                client.stop_logging(Name=r['Name'])\n\n\n@CloudTrail.action_registry.register('delete')\nclass DeleteTrail(BaseAction):\n    \"\"\" Delete a cloud trail\n\n    :example:\n\n    .. code-block:: yaml\n\n      policies:\n        - name: delete-cloudtrail\n          resource: aws.cloudtrail\n          filters:\n           - type: value\n             key: Name\n             value: delete-me\n             op: eq\n          actions:\n           - type: delete\n    \"\"\"\n\n    schema = type_schema('delete')\n    permissions = ('cloudtrail:DeleteTrail',)\n\n    def process(self, resources):\n        client = local_session(self.manager.session_factory).client('cloudtrail')\n        shadow_check = IsShadow({'state': False}, self.manager)\n        shadow_check.embedded = True\n        resources = shadow_check.process(resources)\n        for r in resources:\n            try:\n                client.delete_trail(Name=r['Name'])\n            except client.exceptions.TrailNotFoundException:\n                continue\n", "path": "c7n/resources/cloudtrail.py"}]}