We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
GCP - new serviceAccountsKeys resource
support for service account keys by adding a new resource under iam. 

https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `tools/c7n_gcp/c7n_gcp/resources/resource_map.py`
Content:
```
1 # Copyright The Cloud Custodian Authors.
2 # SPDX-License-Identifier: Apache-2.0
3 ResourceMap = {
4     "gcp.app-engine": "c7n_gcp.resources.appengine.AppEngineApp",
5     "gcp.app-engine-certificate": "c7n_gcp.resources.appengine.AppEngineCertificate",
6     "gcp.app-engine-domain": "c7n_gcp.resources.appengine.AppEngineDomain",
7     "gcp.app-engine-domain-mapping": "c7n_gcp.resources.appengine.AppEngineDomainMapping",
8     "gcp.app-engine-firewall-ingress-rule": (
9         "c7n_gcp.resources.appengine.AppEngineFirewallIngressRule"),
10     "gcp.autoscaler": "c7n_gcp.resources.compute.Autoscaler",
11     "gcp.bq-dataset": "c7n_gcp.resources.bigquery.DataSet",
12     "gcp.bq-job": "c7n_gcp.resources.bigquery.BigQueryJob",
13     "gcp.bq-project": "c7n_gcp.resources.bigquery.BigQueryProject",
14     "gcp.bq-table": "c7n_gcp.resources.bigquery.BigQueryTable",
15     "gcp.bucket": "c7n_gcp.resources.storage.Bucket",
16     "gcp.build": "c7n_gcp.resources.build.CloudBuild",
17     "gcp.cloudbilling-account": "c7n_gcp.resources.cloudbilling.CloudBillingAccount",
18     "gcp.dataflow-job": "c7n_gcp.resources.dataflow.DataflowJob",
19     "gcp.disk": "c7n_gcp.resources.compute.Disk",
20     "gcp.dm-deployment": "c7n_gcp.resources.deploymentmanager.DMDeployment",
21     "gcp.dns-managed-zone": "c7n_gcp.resources.dns.DnsManagedZone",
22     "gcp.dns-policy": "c7n_gcp.resources.dns.DnsPolicy",
23     "gcp.firewall": "c7n_gcp.resources.network.Firewall",
24     "gcp.folder": "c7n_gcp.resources.resourcemanager.Folder",
25     "gcp.function": "c7n_gcp.resources.function.Function",
26     "gcp.gke-cluster": "c7n_gcp.resources.gke.KubernetesCluster",
27     "gcp.gke-nodepool": "c7n_gcp.resources.gke.KubernetesClusterNodePool",
28     "gcp.iam-role": "c7n_gcp.resources.iam.Role",
29     "gcp.image": "c7n_gcp.resources.compute.Image",
30     "gcp.instance": "c7n_gcp.resources.compute.Instance",
31     "gcp.instance-template": "c7n_gcp.resources.compute.InstanceTemplate",
32     "gcp.interconnect": "c7n_gcp.resources.network.Interconnect",
33     "gcp.interconnect-attachment": "c7n_gcp.resources.network.InterconnectAttachment",
34     "gcp.kms-cryptokey": "c7n_gcp.resources.kms.KmsCryptoKey",
35     "gcp.kms-cryptokey-version": "c7n_gcp.resources.kms.KmsCryptoKeyVersion",
36     "gcp.kms-keyring": "c7n_gcp.resources.kms.KmsKeyRing",
37     "gcp.loadbalancer-address": "c7n_gcp.resources.loadbalancer.LoadBalancingAddress",
38     "gcp.loadbalancer-backend-bucket": "c7n_gcp.resources.loadbalancer.LoadBalancingBackendBucket",
39     "gcp.loadbalancer-backend-service": (
40         "c7n_gcp.resources.loadbalancer.LoadBalancingBackendService"),
41     "gcp.loadbalancer-forwarding-rule": (
42         "c7n_gcp.resources.loadbalancer.LoadBalancingForwardingRule"),
43     "gcp.loadbalancer-global-address": "c7n_gcp.resources.loadbalancer.LoadBalancingGlobalAddress",
44     "gcp.loadbalancer-global-forwarding-rule": (
45         "c7n_gcp.resources.loadbalancer.LoadBalancingGlobalForwardingRule"),
46     "gcp.loadbalancer-health-check": "c7n_gcp.resources.loadbalancer.LoadBalancingHealthCheck",
47     "gcp.loadbalancer-http-health-check": (
48         "c7n_gcp.resources.loadbalancer.LoadBalancingHttpHealthCheck"),
49     "gcp.loadbalancer-https-health-check": (
50         "c7n_gcp.resources.loadbalancer.LoadBalancingHttpsHealthCheck"),
51     "gcp.loadbalancer-ssl-certificate": (
52         "c7n_gcp.resources.loadbalancer.LoadBalancingSslCertificate"),
53     "gcp.loadbalancer-ssl-policy": "c7n_gcp.resources.loadbalancer.LoadBalancingSslPolicy",
54     "gcp.loadbalancer-target-http-proxy": (
55         "c7n_gcp.resources.loadbalancer.LoadBalancingTargetHttpProxy"),
56     "gcp.loadbalancer-target-https-proxy": (
57         "c7n_gcp.resources.loadbalancer.LoadBalancingTargetHttpsProxy"),
58     "gcp.loadbalancer-target-instance": (
59         "c7n_gcp.resources.loadbalancer.LoadBalancingTargetInstance"),
60     "gcp.loadbalancer-target-pool": "c7n_gcp.resources.loadbalancer.LoadBalancingTargetPool",
61     "gcp.loadbalancer-target-ssl-proxy": (
62         "c7n_gcp.resources.loadbalancer.LoadBalancingTargetSslProxy"),
63     "gcp.loadbalancer-target-tcp-proxy": (
64         "c7n_gcp.resources.loadbalancer.LoadBalancingTargetTcpProxy"),
65     "gcp.loadbalancer-url-map": "c7n_gcp.resources.loadbalancer.LoadBalancingUrlMap",
66     "gcp.log-exclusion": "c7n_gcp.resources.logging.LogExclusion",
67     "gcp.log-project-metric": "c7n_gcp.resources.logging.LogProjectMetric",
68     "gcp.log-project-sink": "c7n_gcp.resources.logging.LogProjectSink",
69     "gcp.ml-job": "c7n_gcp.resources.mlengine.MLJob",
70     "gcp.ml-model": "c7n_gcp.resources.mlengine.MLModel",
71     "gcp.organization": "c7n_gcp.resources.resourcemanager.Organization",
72     "gcp.project": "c7n_gcp.resources.resourcemanager.Project",
73     "gcp.project-role": "c7n_gcp.resources.iam.ProjectRole",
74     "gcp.pubsub-snapshot": "c7n_gcp.resources.pubsub.PubSubSnapshot",
75     "gcp.pubsub-subscription": "c7n_gcp.resources.pubsub.PubSubSubscription",
76     "gcp.pubsub-topic": "c7n_gcp.resources.pubsub.PubSubTopic",
77     "gcp.route": "c7n_gcp.resources.network.Route",
78     "gcp.router": "c7n_gcp.resources.network.Router",
79     "gcp.service": "c7n_gcp.resources.service.Service",
80     "gcp.service-account": "c7n_gcp.resources.iam.ServiceAccount",
81     "gcp.snapshot": "c7n_gcp.resources.compute.Snapshot",
82     "gcp.sourcerepo": "c7n_gcp.resources.source.SourceRepository",
83     "gcp.spanner-database-instance": "c7n_gcp.resources.spanner.SpannerDatabaseInstance",
84     "gcp.spanner-instance": "c7n_gcp.resources.spanner.SpannerInstance",
85     "gcp.sql-backup-run": "c7n_gcp.resources.sql.SqlBackupRun",
86     "gcp.sql-instance": "c7n_gcp.resources.sql.SqlInstance",
87     "gcp.sql-ssl-cert": "c7n_gcp.resources.sql.SqlSslCert",
88     "gcp.sql-user": "c7n_gcp.resources.sql.SqlUser",
89     "gcp.subnet": "c7n_gcp.resources.network.Subnet",
90     "gcp.vpc": "c7n_gcp.resources.network.Network"
91 }
92
```

Path: `tools/c7n_gcp/c7n_gcp/resources/iam.py`
Content:
```
1 # Copyright The Cloud Custodian Authors.
2 # SPDX-License-Identifier: Apache-2.0
3 
4 from c7n_gcp.provider import resources
5 from c7n_gcp.query import QueryResourceManager, TypeInfo
6 
7 
8 @resources.register('project-role')
9 class ProjectRole(QueryResourceManager):
10     """GCP Project Role
11     https://cloud.google.com/iam/docs/reference/rest/v1/organizations.roles#Role
12     """
13     class resource_type(TypeInfo):
14         service = 'iam'
15         version = 'v1'
16         component = 'projects.roles'
17         enum_spec = ('list', 'roles[]', None)
18         scope = 'project'
19         scope_key = 'parent'
20         scope_template = 'projects/{}'
21         name = id = "name"
22         default_report_fields = ['name', 'title', 'description', 'stage', 'deleted']
23         asset_type = "iam.googleapis.com/Role"
24 
25         @staticmethod
26         def get(client, resource_info):
27             return client.execute_query(
28                 'get', verb_arguments={
29                     'name': 'projects/{}/roles/{}'.format(
30                         resource_info['project_id'],
31                         resource_info['role_name'].rsplit('/', 1)[-1])})
32 
33 
34 @resources.register('service-account')
35 class ServiceAccount(QueryResourceManager):
36 
37     class resource_type(TypeInfo):
38         service = 'iam'
39         version = 'v1'
40         component = 'projects.serviceAccounts'
41         enum_spec = ('list', 'accounts[]', [])
42         scope = 'project'
43         scope_key = 'name'
44         scope_template = 'projects/{}'
45         id = "name"
46         name = 'email'
47         default_report_fields = ['name', 'displayName', 'email', 'description', 'disabled']
48         asset_type = "iam.googleapis.com/ServiceAccount"
49 
50         @staticmethod
51         def get(client, resource_info):
52             return client.execute_query(
53                 'get', verb_arguments={
54                     'name': 'projects/{}/serviceAccounts/{}'.format(
55                         resource_info['project_id'],
56                         resource_info['email_id'])})
57 
58 
59 @resources.register('iam-role')
60 class Role(QueryResourceManager):
61     """GCP Organization Role
62     https://cloud.google.com/iam/docs/reference/rest/v1/organizations.roles#Role
63     """
64     class resource_type(TypeInfo):
65         service = 'iam'
66         version = 'v1'
67         component = 'roles'
68         enum_spec = ('list', 'roles[]', None)
69         scope = "global"
70         name = id = "name"
71         default_report_fields = ['name', 'title', 'description', 'stage', 'deleted']
72         asset_type = "iam.googleapis.com/Role"
73 
74         @staticmethod
75         def get(client, resource_info):
76             return client.execute_command(
77                 'get', {
78                     'name': 'roles/{}'.format(
79                         resource_info['name'])})
80
```
--- 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/tools/c7n_gcp/c7n_gcp/resources/iam.py b/tools/c7n_gcp/c7n_gcp/resources/iam.py
--- a/tools/c7n_gcp/c7n_gcp/resources/iam.py
+++ b/tools/c7n_gcp/c7n_gcp/resources/iam.py
@@ -1,8 +1,12 @@
 # Copyright The Cloud Custodian Authors.
 # SPDX-License-Identifier: Apache-2.0
+import re
+
+from c7n.utils import type_schema
 
 from c7n_gcp.provider import resources
-from c7n_gcp.query import QueryResourceManager, TypeInfo
+from c7n_gcp.query import QueryResourceManager, TypeInfo, ChildResourceManager, ChildTypeInfo
+from c7n_gcp.actions import MethodAction
 
 
 @resources.register('project-role')
@@ -56,6 +60,66 @@
                         resource_info['email_id'])})
 
 
+@resources.register('service-account-key')
+class ServiceAccountKey(ChildResourceManager):
+    """GCP Resource
+    https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys
+    """
+    def _get_parent_resource_info(self, child_instance):
+        project_id, sa = re.match(
+            'projects/(.*?)/serviceAccounts/(.*?)/keys/.*',
+            child_instance['name']).groups()
+        return {'project_id': project_id,
+                'email_id': sa}
+
+    def get_resource_query(self):
+        """Does nothing as self does not need query values unlike its parent
+        which receives them with the use_child_query flag."""
+        pass
+
+    class resource_type(ChildTypeInfo):
+        service = 'iam'
+        version = 'v1'
+        component = 'projects.serviceAccounts.keys'
+        enum_spec = ('list', 'keys[]', [])
+        scope = None
+        scope_key = 'name'
+        name = id = 'name'
+        default_report_fields = ['name', 'privateKeyType', 'keyAlgorithm',
+          'validAfterTime', 'validBeforeTime', 'keyOrigin', 'keyType']
+        parent_spec = {
+            'resource': 'service-account',
+            'child_enum_params': [
+                ('name', 'name')
+            ],
+            'use_child_query': True
+        }
+        asset_type = "iam.googleapis.com/ServiceAccountKey"
+        scc_type = "google.iam.ServiceAccountKey"
+        permissions = ("iam.serviceAccounts.list",)
+
+        @staticmethod
+        def get(client, resource_info):
+            project, sa, key = re.match(
+                '.*?/projects/(.*?)/serviceAccounts/(.*?)/keys/(.*)',
+                resource_info['resourceName']).groups()
+            return client.execute_query(
+                'get', {
+                    'name': 'projects/{}/serviceAccounts/{}/keys/{}'.format(
+                        project, sa, key)})
+
+
+@ServiceAccountKey.action_registry.register('delete')
+class DeleteServiceAccountKey(MethodAction):
+
+    schema = type_schema('delete')
+    method_spec = {'op': 'delete'}
+    permissions = ("iam.serviceAccountKeys.delete",)
+
+    def get_resource_params(self, m, r):
+        return {'name': r['name']}
+
+
 @resources.register('iam-role')
 class Role(QueryResourceManager):
     """GCP Organization Role
diff --git a/tools/c7n_gcp/c7n_gcp/resources/resource_map.py b/tools/c7n_gcp/c7n_gcp/resources/resource_map.py
--- a/tools/c7n_gcp/c7n_gcp/resources/resource_map.py
+++ b/tools/c7n_gcp/c7n_gcp/resources/resource_map.py
@@ -78,6 +78,7 @@
     "gcp.router": "c7n_gcp.resources.network.Router",
     "gcp.service": "c7n_gcp.resources.service.Service",
     "gcp.service-account": "c7n_gcp.resources.iam.ServiceAccount",
+    "gcp.service-account-key": "c7n_gcp.resources.iam.ServiceAccountKey",
     "gcp.snapshot": "c7n_gcp.resources.compute.Snapshot",
     "gcp.sourcerepo": "c7n_gcp.resources.source.SourceRepository",
     "gcp.spanner-database-instance": "c7n_gcp.resources.spanner.SpannerDatabaseInstance",

{"golden_diff": "diff --git a/tools/c7n_gcp/c7n_gcp/resources/iam.py b/tools/c7n_gcp/c7n_gcp/resources/iam.py\n--- a/tools/c7n_gcp/c7n_gcp/resources/iam.py\n+++ b/tools/c7n_gcp/c7n_gcp/resources/iam.py\n@@ -1,8 +1,12 @@\n # Copyright The Cloud Custodian Authors.\n # SPDX-License-Identifier: Apache-2.0\n+import re\n+\n+from c7n.utils import type_schema\n \n from c7n_gcp.provider import resources\n-from c7n_gcp.query import QueryResourceManager, TypeInfo\n+from c7n_gcp.query import QueryResourceManager, TypeInfo, ChildResourceManager, ChildTypeInfo\n+from c7n_gcp.actions import MethodAction\n \n \n @resources.register('project-role')\n@@ -56,6 +60,66 @@\n                         resource_info['email_id'])})\n \n \n+@resources.register('service-account-key')\n+class ServiceAccountKey(ChildResourceManager):\n+    \"\"\"GCP Resource\n+    https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys\n+    \"\"\"\n+    def _get_parent_resource_info(self, child_instance):\n+        project_id, sa = re.match(\n+            'projects/(.*?)/serviceAccounts/(.*?)/keys/.*',\n+            child_instance['name']).groups()\n+        return {'project_id': project_id,\n+                'email_id': sa}\n+\n+    def get_resource_query(self):\n+        \"\"\"Does nothing as self does not need query values unlike its parent\n+        which receives them with the use_child_query flag.\"\"\"\n+        pass\n+\n+    class resource_type(ChildTypeInfo):\n+        service = 'iam'\n+        version = 'v1'\n+        component = 'projects.serviceAccounts.keys'\n+        enum_spec = ('list', 'keys[]', [])\n+        scope = None\n+        scope_key = 'name'\n+        name = id = 'name'\n+        default_report_fields = ['name', 'privateKeyType', 'keyAlgorithm',\n+          'validAfterTime', 'validBeforeTime', 'keyOrigin', 'keyType']\n+        parent_spec = {\n+            'resource': 'service-account',\n+            'child_enum_params': [\n+                ('name', 'name')\n+            ],\n+            'use_child_query': True\n+        }\n+        asset_type = \"iam.googleapis.com/ServiceAccountKey\"\n+        scc_type = \"google.iam.ServiceAccountKey\"\n+        permissions = (\"iam.serviceAccounts.list\",)\n+\n+        @staticmethod\n+        def get(client, resource_info):\n+            project, sa, key = re.match(\n+                '.*?/projects/(.*?)/serviceAccounts/(.*?)/keys/(.*)',\n+                resource_info['resourceName']).groups()\n+            return client.execute_query(\n+                'get', {\n+                    'name': 'projects/{}/serviceAccounts/{}/keys/{}'.format(\n+                        project, sa, key)})\n+\n+\n+@ServiceAccountKey.action_registry.register('delete')\n+class DeleteServiceAccountKey(MethodAction):\n+\n+    schema = type_schema('delete')\n+    method_spec = {'op': 'delete'}\n+    permissions = (\"iam.serviceAccountKeys.delete\",)\n+\n+    def get_resource_params(self, m, r):\n+        return {'name': r['name']}\n+\n+\n @resources.register('iam-role')\n class Role(QueryResourceManager):\n     \"\"\"GCP Organization Role\ndiff --git a/tools/c7n_gcp/c7n_gcp/resources/resource_map.py b/tools/c7n_gcp/c7n_gcp/resources/resource_map.py\n--- a/tools/c7n_gcp/c7n_gcp/resources/resource_map.py\n+++ b/tools/c7n_gcp/c7n_gcp/resources/resource_map.py\n@@ -78,6 +78,7 @@\n     \"gcp.router\": \"c7n_gcp.resources.network.Router\",\n     \"gcp.service\": \"c7n_gcp.resources.service.Service\",\n     \"gcp.service-account\": \"c7n_gcp.resources.iam.ServiceAccount\",\n+    \"gcp.service-account-key\": \"c7n_gcp.resources.iam.ServiceAccountKey\",\n     \"gcp.snapshot\": \"c7n_gcp.resources.compute.Snapshot\",\n     \"gcp.sourcerepo\": \"c7n_gcp.resources.source.SourceRepository\",\n     \"gcp.spanner-database-instance\": \"c7n_gcp.resources.spanner.SpannerDatabaseInstance\",\n", "issue": "GCP - new serviceAccountsKeys resource\nsupport for service account keys by adding a new resource under iam. \r\n\r\nhttps://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys\n", "before_files": [{"content": "# Copyright The Cloud Custodian Authors.\n# SPDX-License-Identifier: Apache-2.0\nResourceMap = {\n    \"gcp.app-engine\": \"c7n_gcp.resources.appengine.AppEngineApp\",\n    \"gcp.app-engine-certificate\": \"c7n_gcp.resources.appengine.AppEngineCertificate\",\n    \"gcp.app-engine-domain\": \"c7n_gcp.resources.appengine.AppEngineDomain\",\n    \"gcp.app-engine-domain-mapping\": \"c7n_gcp.resources.appengine.AppEngineDomainMapping\",\n    \"gcp.app-engine-firewall-ingress-rule\": (\n        \"c7n_gcp.resources.appengine.AppEngineFirewallIngressRule\"),\n    \"gcp.autoscaler\": \"c7n_gcp.resources.compute.Autoscaler\",\n    \"gcp.bq-dataset\": \"c7n_gcp.resources.bigquery.DataSet\",\n    \"gcp.bq-job\": \"c7n_gcp.resources.bigquery.BigQueryJob\",\n    \"gcp.bq-project\": \"c7n_gcp.resources.bigquery.BigQueryProject\",\n    \"gcp.bq-table\": \"c7n_gcp.resources.bigquery.BigQueryTable\",\n    \"gcp.bucket\": \"c7n_gcp.resources.storage.Bucket\",\n    \"gcp.build\": \"c7n_gcp.resources.build.CloudBuild\",\n    \"gcp.cloudbilling-account\": \"c7n_gcp.resources.cloudbilling.CloudBillingAccount\",\n    \"gcp.dataflow-job\": \"c7n_gcp.resources.dataflow.DataflowJob\",\n    \"gcp.disk\": \"c7n_gcp.resources.compute.Disk\",\n    \"gcp.dm-deployment\": \"c7n_gcp.resources.deploymentmanager.DMDeployment\",\n    \"gcp.dns-managed-zone\": \"c7n_gcp.resources.dns.DnsManagedZone\",\n    \"gcp.dns-policy\": \"c7n_gcp.resources.dns.DnsPolicy\",\n    \"gcp.firewall\": \"c7n_gcp.resources.network.Firewall\",\n    \"gcp.folder\": \"c7n_gcp.resources.resourcemanager.Folder\",\n    \"gcp.function\": \"c7n_gcp.resources.function.Function\",\n    \"gcp.gke-cluster\": \"c7n_gcp.resources.gke.KubernetesCluster\",\n    \"gcp.gke-nodepool\": \"c7n_gcp.resources.gke.KubernetesClusterNodePool\",\n    \"gcp.iam-role\": \"c7n_gcp.resources.iam.Role\",\n    \"gcp.image\": \"c7n_gcp.resources.compute.Image\",\n    \"gcp.instance\": \"c7n_gcp.resources.compute.Instance\",\n    \"gcp.instance-template\": \"c7n_gcp.resources.compute.InstanceTemplate\",\n    \"gcp.interconnect\": \"c7n_gcp.resources.network.Interconnect\",\n    \"gcp.interconnect-attachment\": \"c7n_gcp.resources.network.InterconnectAttachment\",\n    \"gcp.kms-cryptokey\": \"c7n_gcp.resources.kms.KmsCryptoKey\",\n    \"gcp.kms-cryptokey-version\": \"c7n_gcp.resources.kms.KmsCryptoKeyVersion\",\n    \"gcp.kms-keyring\": \"c7n_gcp.resources.kms.KmsKeyRing\",\n    \"gcp.loadbalancer-address\": \"c7n_gcp.resources.loadbalancer.LoadBalancingAddress\",\n    \"gcp.loadbalancer-backend-bucket\": \"c7n_gcp.resources.loadbalancer.LoadBalancingBackendBucket\",\n    \"gcp.loadbalancer-backend-service\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingBackendService\"),\n    \"gcp.loadbalancer-forwarding-rule\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingForwardingRule\"),\n    \"gcp.loadbalancer-global-address\": \"c7n_gcp.resources.loadbalancer.LoadBalancingGlobalAddress\",\n    \"gcp.loadbalancer-global-forwarding-rule\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingGlobalForwardingRule\"),\n    \"gcp.loadbalancer-health-check\": \"c7n_gcp.resources.loadbalancer.LoadBalancingHealthCheck\",\n    \"gcp.loadbalancer-http-health-check\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingHttpHealthCheck\"),\n    \"gcp.loadbalancer-https-health-check\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingHttpsHealthCheck\"),\n    \"gcp.loadbalancer-ssl-certificate\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingSslCertificate\"),\n    \"gcp.loadbalancer-ssl-policy\": \"c7n_gcp.resources.loadbalancer.LoadBalancingSslPolicy\",\n    \"gcp.loadbalancer-target-http-proxy\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingTargetHttpProxy\"),\n    \"gcp.loadbalancer-target-https-proxy\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingTargetHttpsProxy\"),\n    \"gcp.loadbalancer-target-instance\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingTargetInstance\"),\n    \"gcp.loadbalancer-target-pool\": \"c7n_gcp.resources.loadbalancer.LoadBalancingTargetPool\",\n    \"gcp.loadbalancer-target-ssl-proxy\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingTargetSslProxy\"),\n    \"gcp.loadbalancer-target-tcp-proxy\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingTargetTcpProxy\"),\n    \"gcp.loadbalancer-url-map\": \"c7n_gcp.resources.loadbalancer.LoadBalancingUrlMap\",\n    \"gcp.log-exclusion\": \"c7n_gcp.resources.logging.LogExclusion\",\n    \"gcp.log-project-metric\": \"c7n_gcp.resources.logging.LogProjectMetric\",\n    \"gcp.log-project-sink\": \"c7n_gcp.resources.logging.LogProjectSink\",\n    \"gcp.ml-job\": \"c7n_gcp.resources.mlengine.MLJob\",\n    \"gcp.ml-model\": \"c7n_gcp.resources.mlengine.MLModel\",\n    \"gcp.organization\": \"c7n_gcp.resources.resourcemanager.Organization\",\n    \"gcp.project\": \"c7n_gcp.resources.resourcemanager.Project\",\n    \"gcp.project-role\": \"c7n_gcp.resources.iam.ProjectRole\",\n    \"gcp.pubsub-snapshot\": \"c7n_gcp.resources.pubsub.PubSubSnapshot\",\n    \"gcp.pubsub-subscription\": \"c7n_gcp.resources.pubsub.PubSubSubscription\",\n    \"gcp.pubsub-topic\": \"c7n_gcp.resources.pubsub.PubSubTopic\",\n    \"gcp.route\": \"c7n_gcp.resources.network.Route\",\n    \"gcp.router\": \"c7n_gcp.resources.network.Router\",\n    \"gcp.service\": \"c7n_gcp.resources.service.Service\",\n    \"gcp.service-account\": \"c7n_gcp.resources.iam.ServiceAccount\",\n    \"gcp.snapshot\": \"c7n_gcp.resources.compute.Snapshot\",\n    \"gcp.sourcerepo\": \"c7n_gcp.resources.source.SourceRepository\",\n    \"gcp.spanner-database-instance\": \"c7n_gcp.resources.spanner.SpannerDatabaseInstance\",\n    \"gcp.spanner-instance\": \"c7n_gcp.resources.spanner.SpannerInstance\",\n    \"gcp.sql-backup-run\": \"c7n_gcp.resources.sql.SqlBackupRun\",\n    \"gcp.sql-instance\": \"c7n_gcp.resources.sql.SqlInstance\",\n    \"gcp.sql-ssl-cert\": \"c7n_gcp.resources.sql.SqlSslCert\",\n    \"gcp.sql-user\": \"c7n_gcp.resources.sql.SqlUser\",\n    \"gcp.subnet\": \"c7n_gcp.resources.network.Subnet\",\n    \"gcp.vpc\": \"c7n_gcp.resources.network.Network\"\n}\n", "path": "tools/c7n_gcp/c7n_gcp/resources/resource_map.py"}, {"content": "# Copyright The Cloud Custodian Authors.\n# SPDX-License-Identifier: Apache-2.0\n\nfrom c7n_gcp.provider import resources\nfrom c7n_gcp.query import QueryResourceManager, TypeInfo\n\n\n@resources.register('project-role')\nclass ProjectRole(QueryResourceManager):\n    \"\"\"GCP Project Role\n    https://cloud.google.com/iam/docs/reference/rest/v1/organizations.roles#Role\n    \"\"\"\n    class resource_type(TypeInfo):\n        service = 'iam'\n        version = 'v1'\n        component = 'projects.roles'\n        enum_spec = ('list', 'roles[]', None)\n        scope = 'project'\n        scope_key = 'parent'\n        scope_template = 'projects/{}'\n        name = id = \"name\"\n        default_report_fields = ['name', 'title', 'description', 'stage', 'deleted']\n        asset_type = \"iam.googleapis.com/Role\"\n\n        @staticmethod\n        def get(client, resource_info):\n            return client.execute_query(\n                'get', verb_arguments={\n                    'name': 'projects/{}/roles/{}'.format(\n                        resource_info['project_id'],\n                        resource_info['role_name'].rsplit('/', 1)[-1])})\n\n\n@resources.register('service-account')\nclass ServiceAccount(QueryResourceManager):\n\n    class resource_type(TypeInfo):\n        service = 'iam'\n        version = 'v1'\n        component = 'projects.serviceAccounts'\n        enum_spec = ('list', 'accounts[]', [])\n        scope = 'project'\n        scope_key = 'name'\n        scope_template = 'projects/{}'\n        id = \"name\"\n        name = 'email'\n        default_report_fields = ['name', 'displayName', 'email', 'description', 'disabled']\n        asset_type = \"iam.googleapis.com/ServiceAccount\"\n\n        @staticmethod\n        def get(client, resource_info):\n            return client.execute_query(\n                'get', verb_arguments={\n                    'name': 'projects/{}/serviceAccounts/{}'.format(\n                        resource_info['project_id'],\n                        resource_info['email_id'])})\n\n\n@resources.register('iam-role')\nclass Role(QueryResourceManager):\n    \"\"\"GCP Organization Role\n    https://cloud.google.com/iam/docs/reference/rest/v1/organizations.roles#Role\n    \"\"\"\n    class resource_type(TypeInfo):\n        service = 'iam'\n        version = 'v1'\n        component = 'roles'\n        enum_spec = ('list', 'roles[]', None)\n        scope = \"global\"\n        name = id = \"name\"\n        default_report_fields = ['name', 'title', 'description', 'stage', 'deleted']\n        asset_type = \"iam.googleapis.com/Role\"\n\n        @staticmethod\n        def get(client, resource_info):\n            return client.execute_command(\n                'get', {\n                    'name': 'roles/{}'.format(\n                        resource_info['name'])})\n", "path": "tools/c7n_gcp/c7n_gcp/resources/iam.py"}], "after_files": [{"content": "# Copyright The Cloud Custodian Authors.\n# SPDX-License-Identifier: Apache-2.0\nResourceMap = {\n    \"gcp.app-engine\": \"c7n_gcp.resources.appengine.AppEngineApp\",\n    \"gcp.app-engine-certificate\": \"c7n_gcp.resources.appengine.AppEngineCertificate\",\n    \"gcp.app-engine-domain\": \"c7n_gcp.resources.appengine.AppEngineDomain\",\n    \"gcp.app-engine-domain-mapping\": \"c7n_gcp.resources.appengine.AppEngineDomainMapping\",\n    \"gcp.app-engine-firewall-ingress-rule\": (\n        \"c7n_gcp.resources.appengine.AppEngineFirewallIngressRule\"),\n    \"gcp.autoscaler\": \"c7n_gcp.resources.compute.Autoscaler\",\n    \"gcp.bq-dataset\": \"c7n_gcp.resources.bigquery.DataSet\",\n    \"gcp.bq-job\": \"c7n_gcp.resources.bigquery.BigQueryJob\",\n    \"gcp.bq-project\": \"c7n_gcp.resources.bigquery.BigQueryProject\",\n    \"gcp.bq-table\": \"c7n_gcp.resources.bigquery.BigQueryTable\",\n    \"gcp.bucket\": \"c7n_gcp.resources.storage.Bucket\",\n    \"gcp.build\": \"c7n_gcp.resources.build.CloudBuild\",\n    \"gcp.cloudbilling-account\": \"c7n_gcp.resources.cloudbilling.CloudBillingAccount\",\n    \"gcp.dataflow-job\": \"c7n_gcp.resources.dataflow.DataflowJob\",\n    \"gcp.disk\": \"c7n_gcp.resources.compute.Disk\",\n    \"gcp.dm-deployment\": \"c7n_gcp.resources.deploymentmanager.DMDeployment\",\n    \"gcp.dns-managed-zone\": \"c7n_gcp.resources.dns.DnsManagedZone\",\n    \"gcp.dns-policy\": \"c7n_gcp.resources.dns.DnsPolicy\",\n    \"gcp.firewall\": \"c7n_gcp.resources.network.Firewall\",\n    \"gcp.folder\": \"c7n_gcp.resources.resourcemanager.Folder\",\n    \"gcp.function\": \"c7n_gcp.resources.function.Function\",\n    \"gcp.gke-cluster\": \"c7n_gcp.resources.gke.KubernetesCluster\",\n    \"gcp.gke-nodepool\": \"c7n_gcp.resources.gke.KubernetesClusterNodePool\",\n    \"gcp.iam-role\": \"c7n_gcp.resources.iam.Role\",\n    \"gcp.image\": \"c7n_gcp.resources.compute.Image\",\n    \"gcp.instance\": \"c7n_gcp.resources.compute.Instance\",\n    \"gcp.instance-template\": \"c7n_gcp.resources.compute.InstanceTemplate\",\n    \"gcp.interconnect\": \"c7n_gcp.resources.network.Interconnect\",\n    \"gcp.interconnect-attachment\": \"c7n_gcp.resources.network.InterconnectAttachment\",\n    \"gcp.kms-cryptokey\": \"c7n_gcp.resources.kms.KmsCryptoKey\",\n    \"gcp.kms-cryptokey-version\": \"c7n_gcp.resources.kms.KmsCryptoKeyVersion\",\n    \"gcp.kms-keyring\": \"c7n_gcp.resources.kms.KmsKeyRing\",\n    \"gcp.loadbalancer-address\": \"c7n_gcp.resources.loadbalancer.LoadBalancingAddress\",\n    \"gcp.loadbalancer-backend-bucket\": \"c7n_gcp.resources.loadbalancer.LoadBalancingBackendBucket\",\n    \"gcp.loadbalancer-backend-service\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingBackendService\"),\n    \"gcp.loadbalancer-forwarding-rule\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingForwardingRule\"),\n    \"gcp.loadbalancer-global-address\": \"c7n_gcp.resources.loadbalancer.LoadBalancingGlobalAddress\",\n    \"gcp.loadbalancer-global-forwarding-rule\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingGlobalForwardingRule\"),\n    \"gcp.loadbalancer-health-check\": \"c7n_gcp.resources.loadbalancer.LoadBalancingHealthCheck\",\n    \"gcp.loadbalancer-http-health-check\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingHttpHealthCheck\"),\n    \"gcp.loadbalancer-https-health-check\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingHttpsHealthCheck\"),\n    \"gcp.loadbalancer-ssl-certificate\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingSslCertificate\"),\n    \"gcp.loadbalancer-ssl-policy\": \"c7n_gcp.resources.loadbalancer.LoadBalancingSslPolicy\",\n    \"gcp.loadbalancer-target-http-proxy\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingTargetHttpProxy\"),\n    \"gcp.loadbalancer-target-https-proxy\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingTargetHttpsProxy\"),\n    \"gcp.loadbalancer-target-instance\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingTargetInstance\"),\n    \"gcp.loadbalancer-target-pool\": \"c7n_gcp.resources.loadbalancer.LoadBalancingTargetPool\",\n    \"gcp.loadbalancer-target-ssl-proxy\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingTargetSslProxy\"),\n    \"gcp.loadbalancer-target-tcp-proxy\": (\n        \"c7n_gcp.resources.loadbalancer.LoadBalancingTargetTcpProxy\"),\n    \"gcp.loadbalancer-url-map\": \"c7n_gcp.resources.loadbalancer.LoadBalancingUrlMap\",\n    \"gcp.log-exclusion\": \"c7n_gcp.resources.logging.LogExclusion\",\n    \"gcp.log-project-metric\": \"c7n_gcp.resources.logging.LogProjectMetric\",\n    \"gcp.log-project-sink\": \"c7n_gcp.resources.logging.LogProjectSink\",\n    \"gcp.ml-job\": \"c7n_gcp.resources.mlengine.MLJob\",\n    \"gcp.ml-model\": \"c7n_gcp.resources.mlengine.MLModel\",\n    \"gcp.organization\": \"c7n_gcp.resources.resourcemanager.Organization\",\n    \"gcp.project\": \"c7n_gcp.resources.resourcemanager.Project\",\n    \"gcp.project-role\": \"c7n_gcp.resources.iam.ProjectRole\",\n    \"gcp.pubsub-snapshot\": \"c7n_gcp.resources.pubsub.PubSubSnapshot\",\n    \"gcp.pubsub-subscription\": \"c7n_gcp.resources.pubsub.PubSubSubscription\",\n    \"gcp.pubsub-topic\": \"c7n_gcp.resources.pubsub.PubSubTopic\",\n    \"gcp.route\": \"c7n_gcp.resources.network.Route\",\n    \"gcp.router\": \"c7n_gcp.resources.network.Router\",\n    \"gcp.service\": \"c7n_gcp.resources.service.Service\",\n    \"gcp.service-account\": \"c7n_gcp.resources.iam.ServiceAccount\",\n    \"gcp.service-account-key\": \"c7n_gcp.resources.iam.ServiceAccountKey\",\n    \"gcp.snapshot\": \"c7n_gcp.resources.compute.Snapshot\",\n    \"gcp.sourcerepo\": \"c7n_gcp.resources.source.SourceRepository\",\n    \"gcp.spanner-database-instance\": \"c7n_gcp.resources.spanner.SpannerDatabaseInstance\",\n    \"gcp.spanner-instance\": \"c7n_gcp.resources.spanner.SpannerInstance\",\n    \"gcp.sql-backup-run\": \"c7n_gcp.resources.sql.SqlBackupRun\",\n    \"gcp.sql-instance\": \"c7n_gcp.resources.sql.SqlInstance\",\n    \"gcp.sql-ssl-cert\": \"c7n_gcp.resources.sql.SqlSslCert\",\n    \"gcp.sql-user\": \"c7n_gcp.resources.sql.SqlUser\",\n    \"gcp.subnet\": \"c7n_gcp.resources.network.Subnet\",\n    \"gcp.vpc\": \"c7n_gcp.resources.network.Network\"\n}\n", "path": "tools/c7n_gcp/c7n_gcp/resources/resource_map.py"}, {"content": "# Copyright The Cloud Custodian Authors.\n# SPDX-License-Identifier: Apache-2.0\nimport re\n\nfrom c7n.utils import type_schema\n\nfrom c7n_gcp.provider import resources\nfrom c7n_gcp.query import QueryResourceManager, TypeInfo, ChildResourceManager, ChildTypeInfo\nfrom c7n_gcp.actions import MethodAction\n\n\n@resources.register('project-role')\nclass ProjectRole(QueryResourceManager):\n    \"\"\"GCP Project Role\n    https://cloud.google.com/iam/docs/reference/rest/v1/organizations.roles#Role\n    \"\"\"\n    class resource_type(TypeInfo):\n        service = 'iam'\n        version = 'v1'\n        component = 'projects.roles'\n        enum_spec = ('list', 'roles[]', None)\n        scope = 'project'\n        scope_key = 'parent'\n        scope_template = 'projects/{}'\n        name = id = \"name\"\n        default_report_fields = ['name', 'title', 'description', 'stage', 'deleted']\n        asset_type = \"iam.googleapis.com/Role\"\n\n        @staticmethod\n        def get(client, resource_info):\n            return client.execute_query(\n                'get', verb_arguments={\n                    'name': 'projects/{}/roles/{}'.format(\n                        resource_info['project_id'],\n                        resource_info['role_name'].rsplit('/', 1)[-1])})\n\n\n@resources.register('service-account')\nclass ServiceAccount(QueryResourceManager):\n\n    class resource_type(TypeInfo):\n        service = 'iam'\n        version = 'v1'\n        component = 'projects.serviceAccounts'\n        enum_spec = ('list', 'accounts[]', [])\n        scope = 'project'\n        scope_key = 'name'\n        scope_template = 'projects/{}'\n        id = \"name\"\n        name = 'email'\n        default_report_fields = ['name', 'displayName', 'email', 'description', 'disabled']\n        asset_type = \"iam.googleapis.com/ServiceAccount\"\n\n        @staticmethod\n        def get(client, resource_info):\n            return client.execute_query(\n                'get', verb_arguments={\n                    'name': 'projects/{}/serviceAccounts/{}'.format(\n                        resource_info['project_id'],\n                        resource_info['email_id'])})\n\n\n@resources.register('service-account-key')\nclass ServiceAccountKey(ChildResourceManager):\n    \"\"\"GCP Resource\n    https://cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys\n    \"\"\"\n    def _get_parent_resource_info(self, child_instance):\n        project_id, sa = re.match(\n            'projects/(.*?)/serviceAccounts/(.*?)/keys/.*',\n            child_instance['name']).groups()\n        return {'project_id': project_id,\n                'email_id': sa}\n\n    def get_resource_query(self):\n        \"\"\"Does nothing as self does not need query values unlike its parent\n        which receives them with the use_child_query flag.\"\"\"\n        pass\n\n    class resource_type(ChildTypeInfo):\n        service = 'iam'\n        version = 'v1'\n        component = 'projects.serviceAccounts.keys'\n        enum_spec = ('list', 'keys[]', [])\n        scope = None\n        scope_key = 'name'\n        name = id = 'name'\n        default_report_fields = ['name', 'privateKeyType', 'keyAlgorithm',\n          'validAfterTime', 'validBeforeTime', 'keyOrigin', 'keyType']\n        parent_spec = {\n            'resource': 'service-account',\n            'child_enum_params': [\n                ('name', 'name')\n            ],\n            'use_child_query': True\n        }\n        asset_type = \"iam.googleapis.com/ServiceAccountKey\"\n        scc_type = \"google.iam.ServiceAccountKey\"\n        permissions = (\"iam.serviceAccounts.list\",)\n\n        @staticmethod\n        def get(client, resource_info):\n            project, sa, key = re.match(\n                '.*?/projects/(.*?)/serviceAccounts/(.*?)/keys/(.*)',\n                resource_info['resourceName']).groups()\n            return client.execute_query(\n                'get', {\n                    'name': 'projects/{}/serviceAccounts/{}/keys/{}'.format(\n                        project, sa, key)})\n\n\n@ServiceAccountKey.action_registry.register('delete')\nclass DeleteServiceAccountKey(MethodAction):\n\n    schema = type_schema('delete')\n    method_spec = {'op': 'delete'}\n    permissions = (\"iam.serviceAccountKeys.delete\",)\n\n    def get_resource_params(self, m, r):\n        return {'name': r['name']}\n\n\n@resources.register('iam-role')\nclass Role(QueryResourceManager):\n    \"\"\"GCP Organization Role\n    https://cloud.google.com/iam/docs/reference/rest/v1/organizations.roles#Role\n    \"\"\"\n    class resource_type(TypeInfo):\n        service = 'iam'\n        version = 'v1'\n        component = 'roles'\n        enum_spec = ('list', 'roles[]', None)\n        scope = \"global\"\n        name = id = \"name\"\n        default_report_fields = ['name', 'title', 'description', 'stage', 'deleted']\n        asset_type = \"iam.googleapis.com/Role\"\n\n        @staticmethod\n        def get(client, resource_info):\n            return client.execute_command(\n                'get', {\n                    'name': 'roles/{}'.format(\n                        resource_info['name'])})\n", "path": "tools/c7n_gcp/c7n_gcp/resources/iam.py"}]}