Repository: cloud-custodian/cloud-custodian

Issue:
aws account - Add filter for checking Macie2 status
**Is your feature request related to a problem? Please describe.**
As a means of checking to see if Macie is enabled for a given account we would need to add a filter under the account resource (or make separate macie resource)

**Describe the solution you'd like**
Either a aws.account.filter.macie filter addition or an addition of a aws.macie resource which would display the status of Macie in an account.
Boto3 call - https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/macie2.html#Macie2.Client.get_macie_session

**Describe alternatives you've considered**
No other way to pull this information via Custodian at this time

**Additional context**
I want to ensure Macie is enabled in my AWS accounts and this filter or resource addition would allow that.



Discussion:

Resolving patch:
diff --git a/c7n/resources/account.py b/c7n/resources/account.py
--- a/c7n/resources/account.py
+++ b/c7n/resources/account.py
@@ -95,6 +95,49 @@ def process(self, resources, event=None):
         return results
 
 
+@filters.register('check-macie')
+class MacieEnabled(ValueFilter):
+    """Check status of macie v2 in the account.
+
+    Gets the macie session info for the account, and
+    the macie master account for the current account if
+    configured.
+    """
+
+    schema = type_schema('check-macie', rinherit=ValueFilter.schema)
+    schema_alias = False
+    annotation_key = 'c7n:macie'
+    annotate = False
+    permissions = ('macie2:GetMacieSession', 'macie2:GetMasterAccount',)
+
+    def process(self, resources, event=None):
+
+        if self.annotation_key not in resources[0]:
+            self.get_macie_info(resources[0])
+
+        if super().process([resources[0][self.annotation_key]]):
+            return resources
+
+    def get_macie_info(self, account):
+        client = local_session(
+            self.manager.session_factory).client('macie2')
+
+        try:
+            info = client.get_macie_session()
+            info.pop('ResponseMetadata')
+        except client.exceptions.AccessDeniedException:
+            info = {}
+
+        try:
+            minfo = client.get_master_account().get('master')
+        except (client.exceptions.AccessDeniedException,
+                client.exceptions.ResourceNotFoundException):
+            info['master'] = {}
+        else:
+            info['master'] = minfo
+        account[self.annotation_key] = info
+
+
 @filters.register('check-cloudtrail')
 class CloudTrailEnabled(Filter):
     """Verify cloud trail enabled for this account per specifications.


Test patch:
diff --git a/tests/data/placebo/test_account_check_macie/iam.ListAccountAliases_1.json b/tests/data/placebo/test_account_check_macie/iam.ListAccountAliases_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_account_check_macie/iam.ListAccountAliases_1.json
@@ -0,0 +1,8 @@
+{
+    "status_code": 200,
+    "data": {
+        "AccountAliases": [],
+        "IsTruncated": false,
+        "ResponseMetadata": {}
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_account_check_macie/macie2.GetMacieSession_1.json b/tests/data/placebo/test_account_check_macie/macie2.GetMacieSession_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_account_check_macie/macie2.GetMacieSession_1.json
@@ -0,0 +1,29 @@
+{
+    "status_code": 200,
+    "data": {
+        "ResponseMetadata": {},
+        "createdAt": {
+            "__class__": "datetime",
+            "year": 2020,
+            "month": 12,
+            "day": 3,
+            "hour": 16,
+            "minute": 22,
+            "second": 14,
+            "microsecond": 821000
+        },
+        "findingPublishingFrequency": "FIFTEEN_MINUTES",
+        "serviceRole": "arn:aws:iam::644160558196:role/aws-service-role/macie.amazonaws.com/AWSServiceRoleForAmazonMacie",
+        "status": "ENABLED",
+        "updatedAt": {
+            "__class__": "datetime",
+            "year": 2020,
+            "month": 12,
+            "day": 3,
+            "hour": 16,
+            "minute": 22,
+            "second": 14,
+            "microsecond": 821000
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/data/placebo/test_account_check_macie/macie2.GetMasterAccount_1.json b/tests/data/placebo/test_account_check_macie/macie2.GetMasterAccount_1.json
new file mode 100644
--- /dev/null
+++ b/tests/data/placebo/test_account_check_macie/macie2.GetMasterAccount_1.json
@@ -0,0 +1,11 @@
+{
+    "status_code": 404,
+    "data": {
+        "Error": {
+            "Message": "The request failed because this account does not have a master",
+            "Code": "ResourceNotFoundException"
+        },
+        "ResponseMetadata": {},
+        "message": "The request failed because this account does not have a master"
+    }
+}
\ No newline at end of file
diff --git a/tests/test_account.py b/tests/test_account.py
--- a/tests/test_account.py
+++ b/tests/test_account.py
@@ -9,7 +9,7 @@
 from c7n.testing import mock_datetime_now
 
 import datetime
-from dateutil import parser
+from dateutil import parser, tz
 import json
 import mock
 import time
@@ -21,6 +21,37 @@
 
 class AccountTests(BaseTest):
 
+    def test_macie(self):
+        factory = self.replay_flight_data(
+            'test_account_check_macie')
+        p = self.load_policy({
+            'name': 'macie-check',
+            'resource': 'aws.account',
+            'filters': [{
+                'or': [
+                    {'type': 'check-macie',
+                     'value': 'absent',
+                     'key': 'master.accountId'},
+                    {'type': 'check-macie',
+                     'key': 'status',
+                     'value': 'ENABLED'}]}]
+        }, session_factory=factory)
+        resources = p.run()
+        self.assertEqual(len(resources), 1)
+        assert resources[0]['c7n:macie'] == {
+            'createdAt': datetime.datetime(
+                2020, 12, 3, 16, 22, 14, 821000, tzinfo=tz.tzutc()),
+            'findingPublishingFrequency': 'FIFTEEN_MINUTES',
+            'master': {},
+            'serviceRole': ('arn:aws:iam::{}:role/aws-service-role/'
+                            'macie.amazonaws.com/'
+                            'AWSServiceRoleForAmazonMacie').format(
+                                p.options.account_id),
+            'status': 'ENABLED',
+            'updatedAt': datetime.datetime(
+                2020, 12, 3, 16, 22, 14, 821000, tzinfo=tz.tzutc()),
+        }
+
     def test_missing(self):
         session_factory = self.replay_flight_data(
             'test_account_missing_resource_ec2')