Repository: cloud-custodian/cloud-custodian

Issue:
iam-policy no longer works with mode: cloudtrail
Unable to get mode: cloudtrail to trigger action with iam-policy.  From my understanding, iam-policy utilizes list_polices (https://docs.aws.amazon.com/IAM/latest/APIReference/API_ListPolicies.html, https://github.com/capitalone/cloud-custodian/blob/master/c7n/resources/iam.py#L84)
Attempted to use the example within the code itself and run from command line (https://github.com/capitalone/cloud-custodian/blob/master/c7n/resources/iam.py#L295-L299) which results in the following error:
https://gist.github.com/zachzeid/8a9d7b0345415a8329f91551495dfbe8

With using `mode: cloudtrail`, Custodian function does trigger, but does not invoke action:
policy: https://gist.github.com/zachzeid/44560d1cd66b0b0ceab25dd5c0d31c9c

The custodian function logs this to Cloudwatch Logs (https://gist.github.com/zachzeid/ca6a007a1f8cbd49f28743d5cb084219).  I suspect because the `responseElements` is null, it won't return any resource id to trigger the function.  I'm not understanding what filters need to be in place to trigger an action in this case. 




Discussion:
That first trace back, implies the custodian version in the lambda doesn't have the action, which is odd since it had to validate to deploy
the issue i'm seeing is translating the event's policy arn back to a path for the resource id resolution when fetching the iam policies for c7n policy evaluation.

Resolving patch:
diff --git a/c7n/resources/iam.py b/c7n/resources/iam.py
--- a/c7n/resources/iam.py
+++ b/c7n/resources/iam.py
@@ -83,12 +83,24 @@ class resource_type(object):
         type = 'policy'
         enum_spec = ('list_policies', 'Policies', None)
         id = 'PolicyId'
-        filter_name = None
         name = 'PolicyName'
         date = 'CreateDate'
         dimension = None
         config_type = "AWS::IAM::Policy"
 
+    arn_path_prefix = "aws:policy/"
+
+    def get_resources(self, resource_ids):
+        client = local_session(self.session_factory).client('iam')
+        results = []
+        try:
+            for r in resource_ids:
+                results.append(client.get_policy(PolicyArn=r)['Policy'])
+        except Exception as e:
+            self.log.warning("unable to resolve ids %s, err: %s",
+                             resource_ids, e)
+        return results
+
 
 @resources.register('iam-profile')
 class InstanceProfile(QueryResourceManager):
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -21,6 +21,6 @@ def read(fname):
     entry_points={
         'console_scripts': [
             'custodian = c7n.cli:main']},
-    install_requires=["boto3", "pyyaml", "jsonschema", "ipaddress"],
+    install_requires=["boto3", "pyyaml", "jsonschema", "ipaddress", "argcomplete"],
 )
 


Test patch:
diff --git a/tests/data/placebo/test_iam_policy_get_resource/iam.GetPolicy_1.json b/tests/data/placebo/test_iam_policy_get_resource/iam.GetPolicy_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_iam_policy_get_resource/iam.GetPolicy_1.json
@@ -0,0 +1,46 @@
+{
+    "status_code": 200, 
+    "data": {
+        "Policy": {
+            "PolicyName": "AWSHealthFullAccess", 
+            "Description": "Allows full access to the AWS Health Apis and Notifications and the Personal Health Dashboard", 
+            "CreateDate": {
+                "hour": 12, 
+                "__class__": "datetime", 
+                "month": 12, 
+                "second": 31, 
+                "microsecond": 0, 
+                "year": 2016, 
+                "day": 6, 
+                "minute": 30
+            }, 
+            "AttachmentCount": 1, 
+            "IsAttachable": true, 
+            "PolicyId": "ANPAI3CUMPCPEUPCSXC4Y", 
+            "DefaultVersionId": "v1", 
+            "Path": "/", 
+            "Arn": "arn:aws:iam::aws:policy/AWSHealthFullAccess", 
+            "UpdateDate": {
+                "hour": 12, 
+                "__class__": "datetime", 
+                "month": 12, 
+                "second": 31, 
+                "microsecond": 0, 
+                "year": 2016, 
+                "day": 6, 
+                "minute": 30
+            }
+        }, 
+        "ResponseMetadata": {
+            "RetryAttempts": 0, 
+            "HTTPStatusCode": 200, 
+            "RequestId": "14a8da87-e865-11e6-a572-dddd468753c8", 
+            "HTTPHeaders": {
+                "x-amzn-requestid": "14a8da87-e865-11e6-a572-dddd468753c8", 
+                "date": "Wed, 01 Feb 2017 09:59:10 GMT", 
+                "content-length": "808", 
+                "content-type": "text/xml"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/test_iam.py b/tests/test_iam.py
--- a/tests/test_iam.py
+++ b/tests/test_iam.py
@@ -25,15 +25,18 @@
 from c7n.filters.iamaccess import check_cross_account, CrossAccountAccessFilter
 from c7n.mu import LambdaManager, LambdaFunction, PythonPackageArchive
 from c7n.resources.sns import SNS
-from c7n.resources.iam import (UserMfaDevice,
-                               UsedIamPolicies, UnusedIamPolicies,
-                               AllowAllIamPolicies,
-                               UsedInstanceProfiles,
-                               UnusedInstanceProfiles,
-                               UsedIamRole, UnusedIamRole,
-                               IamGroupUsers,
-                               UserCredentialReport,
-                               IamRoleInlinePolicy, IamGroupInlinePolicy)
+from c7n.resources.iam import (
+    UserMfaDevice,
+    UsedIamPolicies, UnusedIamPolicies,
+    AllowAllIamPolicies,
+    UsedInstanceProfiles,
+    UnusedInstanceProfiles,
+    UsedIamRole, UnusedIamRole,
+    IamGroupUsers,
+    UserCredentialReport,
+    IamRoleInlinePolicy, IamGroupInlinePolicy)
+
+
 from c7n.executor import MainThreadExecutor
 
 
@@ -212,6 +215,16 @@ def test_iam_instance_profile_unused(self):
 
 class IamPolicyFilterUsage(BaseTest):
 
+    def test_iam_policy_get_resources(self):
+        session_factory = self.replay_flight_data('test_iam_policy_get_resource')
+        p = self.load_policy({
+            'name': 'iam-attached-profiles',
+            'resource': 'iam-policy'}, session_factory=session_factory)
+        resources = p.resource_manager.get_resources(
+            ['arn:aws:iam::aws:policy/AWSHealthFullAccess'])
+        self.assertEqual(len(resources), 1)
+        self.assertEqual(resources[0]['PolicyName'], 'AWSHealthFullAccess')
+
     def test_iam_attached_policies(self):
         session_factory = self.replay_flight_data('test_iam_policy_attached')
         self.patch(
@@ -234,6 +247,7 @@ def test_iam_unattached_policies(self):
         resources = p.run()
         self.assertEqual(len(resources), 203)
 
+
 class IamPolicyHasAllowAll(BaseTest):
 
     def test_iam_has_allow_all_policies(self):
@@ -252,6 +266,7 @@ def test_iam_has_allow_all_policies(self):
         resources = p.run()
         self.assertEqual(len(resources), 1)
 
+
 class IamGroupFilterUsage(BaseTest):
 
     def test_iam_group_used_users(self):