Repository: getmoto/moto
Pull request #8909 (2025-05-18 08:12:49)

chore: update EC2 Instance Types
Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action


Patch:
diff --git a/moto/acmpca/models.py b/moto/acmpca/models.py
index 428fb2037..a5351271b 100644
--- a/moto/acmpca/models.py
+++ b/moto/acmpca/models.py
@@ -1,6 +1,7 @@
 """ACMPCABackend class with methods for supported APIs."""
 
 import base64
+import contextlib
 import datetime
 from typing import Any, Dict, List, Optional, Tuple, cast
 
@@ -248,13 +249,16 @@ class CertificateAuthority(BaseModel):
                 ]
             )
 
-        cn = csr.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME)
-        if cn:
+        # Subject Alternative Name passthrough from CSR to the new certificate
+        with contextlib.suppress(x509.ExtensionNotFound):
+            san = csr.extensions.get_extension_for_oid(
+                x509.ExtensionOID.SUBJECT_ALTERNATIVE_NAME
+            )
             extensions.append(
                 (
-                    x509.SubjectAlternativeName([x509.DNSName(cn[0].value)]),  # type: ignore[arg-type]
-                    False,
-                ),
+                    san.value,
+                    san.critical,
+                )
             )
 
         return extensions
diff --git a/moto/cloudwatch/models.py b/moto/cloudwatch/models.py
index c98dd9d6b..150871f97 100644
--- a/moto/cloudwatch/models.py
+++ b/moto/cloudwatch/models.py
@@ -24,7 +24,11 @@ from .exceptions import (
     ValidationError,
 )
 from .metric_data_expression_parser import parse_expression
-from .utils import make_arn_for_alarm, make_arn_for_dashboard
+from .utils import (
+    make_arn_for_alarm,
+    make_arn_for_dashboard,
+    make_arn_for_rule,
+)
 
 _EMPTY_LIST: Any = tuple()
 
@@ -433,6 +437,25 @@ class Statistics:
         )
 
 
+class InsightRule(BaseModel):
+    def __init__(
+        self,
+        account_id: str,
+        region_name: str,
+        definition: str,
+        name: str,
+        state: str,
+        schema: Optional[str],
+        managed_rule: Optional[bool],
+    ):
+        self.definition = definition
+        self.name = name
+        self.schema = schema or '{"Name" : "CloudWatchLogRule", "Version" : 1}'
+        self.state = state
+        self.managed_rule = managed_rule or False
+        self.rule_arn = make_arn_for_rule(region_name, account_id, name)
+
+
 class CloudWatchBackend(BaseBackend):
     def __init__(self, region_name: str, account_id: str):
         super().__init__(region_name, account_id)
@@ -440,6 +463,7 @@ class CloudWatchBackend(BaseBackend):
         self.dashboards: Dict[str, Dashboard] = {}
         self.metric_data: List[MetricDatumBase] = []
         self.paged_metric_data: Dict[str, List[MetricDatumBase]] = {}
+        self.insight_rules: Dict[str, InsightRule] = {}
         self.tagger = TaggingService()
 
     @property
@@ -1012,5 +1036,97 @@ class CloudWatchBackend(BaseBackend):
                         f'Missing required parameter in MetricData[{query_num}].StatisticValues: "{stat}"'
                     )
 
+    def put_insight_rule(
+        self,
+        name: str,
+        state: str,
+        definition: str,
+        tags: Optional[List[Dict[str, str]]] = None,
+    ) -> InsightRule:
+        rule = InsightRule(
+            account_id=self.account_id,
+            region_name=self.region_name,
+            definition=definition,
+            name=name,
+            state=state,
+            schema='{"Name" : "CloudWatchLogRule", "Version" : 1}',
+            managed_rule=False,
+        )
+        if tags:
+            self.tagger.tag_resource(rule.rule_arn, tags)
+
+        self.insight_rules[name] = rule
+
+        return rule
+
+    def describe_insight_rules(
+        self,
+        next_token: Optional[str] = "",
+        max_results: Optional[int] = 500,
+    ) -> List[InsightRule]:
+        rules = list(self.insight_rules.values())
+
+        if max_results is None or len(rules) <= max_results:
+            return rules
+
+        return rules[:max_results]
+
+    def delete_insight_rules(self, rule_names: List[str]) -> List[Dict[str, Any]]:
+        failures = []
+        for rule_name in list(self.insight_rules.keys()):
+            if rule_name in rule_names:
+                rule = self.insight_rules.get(rule_name)
+                if rule and rule.managed_rule:
+                    failures.append(
+                        {
+                            "FailureResource": rule_name,
+                            "ExceptionType": "InvalidParameterValue",
+                            "FailureCode": 400,
+                            "FailureDescription": "The value of an input parameter is bad or out-of-range.",
+                        }
+                    )
+                else:
+                    del self.insight_rules[rule_name]
+
+        return failures
+
+    def disable_insight_rules(self, rule_names: List[str]) -> List[Dict[str, Any]]:
+        failures = []
+        for rule_name in list(self.insight_rules.keys()):
+            if rule_name in rule_names:
+                rule = self.insight_rules.get(rule_name)
+                if rule and rule.managed_rule:
+                    failures.append(
+                        {
+                            "FailureResource": rule_name,
+                            "ExceptionType": "InvalidParameterValue",
+                            "FailureCode": 400,
+                            "FailureDescription": "The value of an input parameter is bad or out-of-range.",
+                        }
+                    )
+                else:
+                    self.insight_rules[rule_name].state = "DISABLED"
+
+        return failures
+
+    def enable_insight_rules(self, rule_names: List[str]) -> List[Dict[str, Any]]:
+        failures = []
+        for rule_name in list(self.insight_rules.keys()):
+            if rule_name in rule_names:
+                rule = self.insight_rules.get(rule_name)
+                if rule and rule.managed_rule:
+                    failures.append(
+                        {
+                            "FailureResource": rule_name,
+                            "ExceptionType": "InvalidParameterValue",
+                            "FailureCode": 400,
+                            "FailureDescription": "The value of an input parameter is bad or out-of-range.",
+                        }
+                    )
+                else:
+                    self.insight_rules[rule_name].state = "ENABLED"
+
+        return failures
+
 
 cloudwatch_backends = BackendDict(CloudWatchBackend, "cloudwatch")
diff --git a/moto/cloudwatch/responses.py b/moto/cloudwatch/responses.py
index 40d7d3c9c..0f646f117 100644
--- a/moto/cloudwatch/responses.py
+++ b/moto/cloudwatch/responses.py
@@ -340,6 +340,54 @@ class CloudWatchResponse(BaseResponse):
         template = self.response_template(UNTAG_RESOURCE_TEMPLATE)
         return template.render()
 
+    def put_insight_rule(self) -> str:
+        name = self._get_param("RuleName")
+        state = self._get_param("RuleState")
+        definition = self._get_param("RuleDefinition")
+        tags = self._get_multi_param("Tags.member")
+
+        rule = self.cloudwatch_backend.put_insight_rule(
+            name=name,
+            state=state,
+            definition=definition,
+            tags=tags,
+        )
+
+        template = self.response_template(PUT_INSIGHT_RULE_TEMPLATE)
+        return template.render(rule=rule)
+
+    def describe_insight_rules(self) -> str:
+        rules = self.cloudwatch_backend.describe_insight_rules()
+        next_token = self._get_param("NextToken")
+
+        template = self.response_template(DESCRIBE_INSIGHT_RULES_TEMPLATE)
+
+        return template.render(next_token=next_token, rules=rules)
+
+    def delete_insight_rules(self) -> str:
+        names = self._get_multi_param("RuleNames.member")
+        failures = self.cloudwatch_backend.delete_insight_rules(rule_names=names)
+
+        template = self.response_template(DELETE_INSIGHT_RULES_TEMPLATE)
+
+        return template.render(failures=failures)
+
+    def disable_insight_rules(self) -> str:
+        names = self._get_multi_param("RuleNames.member")
+        rule_names = self.cloudwatch_backend.disable_insight_rules(rule_names=names)
+
+        template = self.response_template(DISABLE_INSIGHT_RULES_TEMPLATE)
+
+        return template.render(rule_names=rule_names)
+
+    def enable_insight_rules(self) -> str:
+        names = self._get_multi_param("RuleNames.member")
+        rule_names = self.cloudwatch_backend.enable_insight_rules(rule_names=names)
+
+        template = self.response_template(ENABLE_INSIGHT_RULES_TEMPLATE)
+
+        return template.render(rule_names=rule_names)
+
 
 PUT_METRIC_ALARM_TEMPLATE = """<PutMetricAlarmResponse xmlns="http://monitoring.amazonaws.com/doc/2010-08-01/">
    <ResponseMetadata>
@@ -736,3 +784,72 @@ UNTAG_RESOURCE_TEMPLATE = """<UntagResourceResponse xmlns="http://monitoring.ama
     <RequestId>{{ request_id }}</RequestId>
   </ResponseMetadata>
 </UntagResourceResponse>"""
+
+PUT_INSIGHT_RULE_TEMPLATE = """<PutInsightRuleResponse xmlns="http://monitoring.amazonaws.com/doc/2010-08-01/">
+   <PutInsightRuleResult></PutInsightRuleResult>
+   <ResponseMetadata>
+      <RequestId>{{ request_id }}</RequestId>
+   </ResponseMetadata>
+</PutInsightRuleResponse>"""
+
+DESCRIBE_INSIGHT_RULES_TEMPLATE = """<DescribeInsightRulesResponse xmlns="http://monitoring.amazonaws.com/doc/2010-08-01/">
+    <DescribeInsightRulesResult>
+        <NextToken> {{next_token}} </NextToken>
+        <InsightRules>
+            {% for rule in rules %}
+            <member>
+                <Name>{{ rule.name }}</Name>
+                <State>{{ rule.state }}</State>
+                <Schema>{{ rule.schema }}</Schema>
+                <Definition>{{ rule.definition }}</Definition>
+                <ManagedRule>{{ rule.managed_rule }}</ManagedRule>
+            </member>
+            {% endfor %}
+        </InsightRules>
+    </DescribeInsightRulesResult>
+</DescribeInsightRulesResponse>"""
+
+DELETE_INSIGHT_RULES_TEMPLATE = """<DeleteInsightRulesResponse xmlns="http://monitoring.amazonaws.com/doc/2010-08-01/">
+    <DeleteInsightRulesResult>
+        <Failures>
+            {% for failure in failures %}
+            <member>
+                <FailureResource>{{ failure.FailureResource }}</FailureResource>
+                <ExceptionType>{{ failure.ExceptionType }}</ExceptionType>
+                <FailureCode>{{ failure.FailureCode }}</FailureCode>
+                <FailureDescription>{{ failure.FailureDescription }}</FailureDescription>
+            </member>
+            {% endfor %}
+        </Failures>
+    </DeleteInsightRulesResult>
+</DeleteInsightRulesResponse>"""
+
+DISABLE_INSIGHT_RULES_TEMPLATE = """<DisableInsightRulesResponse xmlns="http://monitoring.amazonaws.com/doc/2010-08-01/">
+    <DisableInsightRulesResult>
+        <Failures>
+            {% for failure in failures %}
+            <member>
+                <FailureResource>{{ failure.FailureResource }}</FailureResource>
+                <ExceptionType>{{ failure.ExceptionType }}</ExceptionType>
+                <FailureCode>{{ failure.FailureCode }}</FailureCode>
+                <FailureDescription>{{ failure.FailureDescription }}</FailureDescription>
+            </member>
+            {% endfor %}
+        </Failures>
+    </DisableInsightRulesResult>
+</DisableInsightRulesResponse>"""
+
+ENABLE_INSIGHT_RULES_TEMPLATE = """<EnableInsightRulesResponse xmlns="http://monitoring.amazonaws.com/doc/2010-08-01/">
+    <EnableInsightRulesResult>
+        <Failures>
+            {% for failure in failures %}
+            <member>
+                <FailureResource>{{ failure.FailureResource }}</FailureResource>
+                <ExceptionType>{{ failure.ExceptionType }}</ExceptionType>
+                <FailureCode>{{ failure.FailureCode }}</FailureCode>
+                <FailureDescription>{{ failure.FailureDescription }}</FailureDescription>
+            </member>
+            {% endfor %}
+        </Failures>
+    </EnableInsightRulesResult>
+</EnableInsightRulesResponse>"""
diff --git a/moto/cloudwatch/utils.py b/moto/cloudwatch/utils.py
index 539410446..4b70e7ba0 100644
--- a/moto/cloudwatch/utils.py
+++ b/moto/cloudwatch/utils.py
@@ -7,3 +7,7 @@ def make_arn_for_dashboard(account_id: str, region_name: str, name: str) -> str:
 
 def make_arn_for_alarm(region: str, account_id: str, alarm_name: str) -> str:
     return f"arn:{get_partition(region)}:cloudwatch:{region}:{account_id}:alarm:{alarm_name}"
+
+
+def make_arn_for_rule(region: str, account_id: str, rule_name: str) -> str:
+    return f"arn:{get_partition(region)}:cloudwatch:{region}:{account_id}:insight-rule/{rule_name}"
diff --git a/moto/ec2/resources/instance_types.json b/moto/ec2/resources/instance_types.json
index cd510c218..58883f55d 100644
--- a/moto/ec2/resources/instance_types.json
+++ b/moto/ec2/resources/instance_types.json
@@ -71816,6 +71816,237 @@
    ]
   }
  },
+ "p6-b200.48xlarge": {
+  "AutoRecoverySupported": false,
+  "BareMetal": false,
+  "BurstablePerformanceSupported": false,
+  "CurrentGeneration": true,
+  "DedicatedHostsSupported": false,
+  "EbsInfo": {
+   "EbsOptimizedInfo": {
+    "BaselineBandwidthInMbps": 100000,
+    "BaselineIops": 400000,
+    "BaselineThroughputInMBps": 12500.0,
+    "MaximumBandwidthInMbps": 100000,
+    "MaximumIops": 400000,
+    "MaximumThroughputInMBps": 12500.0
+   },
+   "EbsOptimizedSupport": "default",
+   "EncryptionSupport": "supported",
+   "NvmeSupport": "required"
+  },
+  "FreeTierEligible": false,
+  "GpuInfo": {
+   "Gpus": [
+    {
+     "Count": 8,
+     "Manufacturer": "NVIDIA",
+     "MemoryInfo": {
+      "SizeInMiB": 183359
+     },
+     "Name": "NVIDIA"
+    }
+   ],
+   "TotalGpuMemoryInMiB": 1466872
+  },
+  "HibernationSupported": false,
+  "Hypervisor": "nitro",
+  "InstanceStorageInfo": {
+   "Disks": [
+    {
+     "Count": 8,
+     "SizeInGB": 3800,
+     "Type": "ssd"
+    }
+   ],
+   "EncryptionSupport": "required",
+   "NvmeSupport": "required",
+   "TotalSizeInGB": 30400
+  },
+  "InstanceStorageSupported": true,
+  "InstanceType": "p6-b200.48xlarge",
+  "MemoryInfo": {
+   "SizeInMiB": 2097152
+  },
+  "NetworkInfo": {
+   "DefaultNetworkCardIndex": 0,
+   "EfaInfo": {
+    "MaximumEfaInterfaces": 8
+   },
+   "EfaSupported": true,
+   "EnaSrdSupported": true,
+   "EnaSupport": "required",
+   "EncryptionInTransitSupported": true,
+   "FlexibleEnaQueuesSupport": "unsupported",
+   "Ipv4AddressesPerInterface": 50,
+   "Ipv6AddressesPerInterface": 50,
+   "Ipv6Supported": true,
+   "MaximumNetworkCards": 8,
+   "MaximumNetworkInterfaces": 32,
+   "NetworkCards": [
+    {
+     "BaselineBandwidthInGbps": 200.0,
+     "DefaultEnaQueueCountPerInterface": 32,
+     "MaximumNetworkInterfaces": 4,
+     "NetworkCardIndex": 0,
+     "NetworkPerformance": "200 Gigabit",
+     "PeakBandwidthInGbps": 200.0
+    },
+    {
+     "BaselineBandwidthInGbps": 200.0,
+     "DefaultEnaQueueCountPerInterface": 32,
+     "MaximumNetworkInterfaces": 4,
+     "NetworkCardIndex": 1,
+     "NetworkPerformance": "200 Gigabit",
+     "PeakBandwidthInGbps": 200.0
+    },
+    {
+     "BaselineBandwidthInGbps": 200.0,
+     "DefaultEnaQueueCountPerInterface": 32,
+     "MaximumNetworkInterfaces": 4,
+     "NetworkCardIndex": 2,
+     "NetworkPerformance": "200 Gigabit",
+     "PeakBandwidthInGbps": 200.0
+    },
+    {
+     "BaselineBandwidthInGbps": 200.0,
+     "DefaultEnaQueueCountPerInterface": 32,
+     "MaximumNetworkInterfaces": 4,
+     "NetworkCardIndex": 3,
+     "NetworkPerformance": "200 Gigabit",
+     "PeakBandwidthInGbps": 200.0
+    },
+    {
+     "BaselineBandwidthInGbps": 200.0,
+     "DefaultEnaQueueCountPerInterface": 32,
+     "MaximumNetworkInterfaces": 4,
+     "NetworkCardIndex": 4,
+     "NetworkPerformance": "200 Gigabit",
+     "PeakBandwidthInGbps": 200.0
+    },
+    {
+     "BaselineBandwidthInGbps": 200.0,
+     "DefaultEnaQueueCountPerInterface": 32,
+     "MaximumNetworkInterfaces": 4,
+     "NetworkCardIndex": 5,
+     "NetworkPerformance": "200 Gigabit",
+     "PeakBandwidthInGbps": 200.0
+    },
+    {
+     "BaselineBandwidthInGbps": 200.0,
+     "DefaultEnaQueueCountPerInterface": 32,
+     "MaximumNetworkInterfaces": 4,
+     "NetworkCardIndex": 6,
+     "NetworkPerformance": "200 Gigabit",
+     "PeakBandwidthInGbps": 200.0
+    },
+    {
+     "BaselineBandwidthInGbps": 200.0,
+     "DefaultEnaQueueCountPerInterface": 32,
+     "MaximumNetworkInterfaces": 4,
+     "NetworkCardIndex": 7,
+     "NetworkPerformance": "200 Gigabit",
+     "PeakBandwidthInGbps": 200.0
+    }
+   ],
+   "NetworkPerformance": "3200 Gigabit"
+  },
+  "NitroEnclavesSupport": "unsupported",
+  "NitroTpmInfo": {
+   "SupportedVersions": [
+    "2.0"
+   ]
+  },
+  "NitroTpmSupport": "supported",
+  "PhcSupport": "supported",
+  "PlacementGroupInfo": {
+   "SupportedStrategies": [
+    "cluster",
+    "partition",
+    "spread"
+   ]
+  },
+  "ProcessorInfo": {
+   "Manufacturer": "Intel",
+   "SupportedArchitectures": [
+    "x86_64"
+   ],
+   "SustainedClockSpeedInGhz": 2.4
+  },
+  "SupportedBootModes": [
+   "legacy-bios",
+   "uefi"
+  ],
+  "SupportedRootDeviceTypes": [
+   "ebs"
+  ],
+  "SupportedUsageClasses": [
+   "capacity-block",
+   "on-demand",
+   "spot"
+  ],
+  "SupportedVirtualizationTypes": [
+   "hvm"
+  ],
+  "VCpuInfo": {
+   "DefaultCores": 96,
+   "DefaultThreadsPerCore": 2,
+   "DefaultVCpus": 192,
+   "ValidCores": [
+    4,
+    6,
+    8,
+    10,
+    12,
+    14,
+    16,
+    18,
+    20,
+    22,
+    24,
+    26,
+    28,
+    30,
+    32,
+    34,
+    36,
+    38,
+    40,
+    42,
+    44,
+    46,
+    48,
+    50,
+    52,
+    54,
+    56,
+    58,
+    60,
+    62,
+    64,
+    66,
+    68,
+    70,
+    72,
+    74,
+    76,
+    78,
+    80,
+    82,
+    84,
+    86,
+    88,
+    90,
+    92,
+    94,
+    96
+   ],
+   "ValidThreadsPerCore": [
+    1,
+    2
+   ]
+  }
+ },
  "r3.2xlarge": {
   "AutoRecoverySupported": true,
   "BareMetal": false,
@@ -101347,7 +101578,12 @@
    "NetworkPerformance": "100 Gigabit"
   },
   "NitroEnclavesSupport": "unsupported",
-  "NitroTpmSupport": "unsupported",
+  "NitroTpmInfo": {
+   "SupportedVersions": [
+    "2.0"
+   ]
+  },
+  "NitroTpmSupport": "supported",
   "PhcSupport": "unsupported",
   "PlacementGroupInfo": {
    "SupportedStrategies": [
@@ -101451,12 +101687,12 @@
   "DedicatedHostsSupported": true,
   "EbsInfo": {
    "EbsOptimizedInfo": {
-    "BaselineBandwidthInMbps": 60000,
-    "BaselineIops": 420000,
-    "BaselineThroughputInMBps": 7500.0,
-    "MaximumBandwidthInMbps": 60000,
-    "MaximumIops": 420000,
-    "MaximumThroughputInMBps": 7500.0
+    "BaselineBandwidthInMbps": 100000,
+    "BaselineIops": 560000,
+    "BaselineThroughputInMBps": 12500.0,
+    "MaximumBandwidthInMbps": 100000,
+    "MaximumIops": 560000,
+    "MaximumThroughputInMBps": 12500.0
    },
    "EbsOptimizedSupport": "default",
    "EncryptionSupport": "supported",
@@ -101607,12 +101843,12 @@
   "DedicatedHostsSupported": true,
   "EbsInfo": {
    "EbsOptimizedInfo": {
-    "BaselineBandwidthInMbps": 60000,
-    "BaselineIops": 420000,
-    "BaselineThroughputInMBps": 7500.0,
-    "MaximumBandwidthInMbps": 60000,
-    "MaximumIops": 420000,
-    "MaximumThroughputInMBps": 7500.0
+    "BaselineBandwidthInMbps": 100000,
+    "BaselineIops": 560000,
+    "BaselineThroughputInMBps": 12500.0,
+    "MaximumBandwidthInMbps": 100000,
+    "MaximumIops": 560000,
+    "MaximumThroughputInMBps": 12500.0
    },
    "EbsOptimizedSupport": "default",
    "EncryptionSupport": "supported",
@@ -101818,7 +102054,12 @@
    "NetworkPerformance": "200 Gigabit"
   },
   "NitroEnclavesSupport": "unsupported",
-  "NitroTpmSupport": "unsupported",
+  "NitroTpmInfo": {
+   "SupportedVersions": [
+    "2.0"
+   ]
+  },
+  "NitroTpmSupport": "supported",
   "PhcSupport": "unsupported",
   "PlacementGroupInfo": {
    "SupportedStrategies": [
@@ -101977,7 +102218,12 @@
    "NetworkPerformance": "200 Gigabit"
   },
   "NitroEnclavesSupport": "unsupported",
-  "NitroTpmSupport": "unsupported",
+  "NitroTpmInfo": {
+   "SupportedVersions": [
+    "2.0"
+   ]
+  },
+  "NitroTpmSupport": "supported",
   "PhcSupport": "unsupported",
   "PlacementGroupInfo": {
    "SupportedStrategies": [
@@ -102136,7 +102382,12 @@
    "NetworkPerformance": "200 Gigabit"
   },
   "NitroEnclavesSupport": "unsupported",
-  "NitroTpmSupport": "unsupported",
+  "NitroTpmInfo": {
+   "SupportedVersions": [
+    "2.0"
+   ]
+  },
+  "NitroTpmSupport": "supported",
   "PhcSupport": "unsupported",
   "PlacementGroupInfo": {
    "SupportedStrategies": [
diff --git a/moto/resourcegroupstaggingapi/models.py b/moto/resourcegroupstaggingapi/models.py
index 2685528d9..3c38c0ec9 100644
--- a/moto/resourcegroupstaggingapi/models.py
+++ b/moto/resourcegroupstaggingapi/models.py
@@ -6,6 +6,7 @@ from moto.awslambda.models import LambdaBackend, lambda_backends
 from moto.backup.models import BackupBackend, backup_backends
 from moto.clouddirectory import CloudDirectoryBackend, clouddirectory_backends
 from moto.cloudfront.models import CloudFrontBackend, cloudfront_backends
+from moto.cloudwatch.models import CloudWatchBackend, cloudwatch_backends
 from moto.core.base_backend import BackendDict, BaseBackend
 from moto.core.exceptions import RESTError
 from moto.dms.models import DatabaseMigrationServiceBackend, dms_backends
@@ -205,6 +206,10 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend):
     def cloudfront_backend(self) -> CloudFrontBackend:
         return cloudfront_backends[self.account_id][self.partition]
 
+    @property
+    def cloudwatch_backend(self) -> CloudWatchBackend:
+        return cloudwatch_backends[self.account_id][self.region_name]
+
     def _get_resources_generator(
         self,
         tag_filters: Optional[List[Dict[str, Any]]] = None,
@@ -354,6 +359,35 @@ class ResourceGroupsTaggingAPIBackend(BaseBackend):
                     continue
                 yield {"ResourceARN": f"{dist.arn}", "Tags": tags}
 
+        if self.cloudwatch_backend:
+            cloudwatch_resource_map: Dict[str, Dict[str, Any]] = {
+                "cloudwatch:alarm": self.cloudwatch_backend.alarms,
+                "cloudwatch:insight-rule": self.cloudwatch_backend.insight_rules,
+            }
+            for resource_type, resource_source in cloudwatch_resource_map.items():
+                if (
+                    not resource_type_filters
+                    or "cloudwatch" in resource_type_filters
+                    or resource_type in resource_type_filters
+                ):
+                    for resource in resource_source.values():
+                        if resource_type == "cloudwatch:alarm":
+                            end_of_arn = f"alarm:{resource.name}"
+                        elif resource_type == "cloudwatch:insight-rule":
+                            end_of_arn = f"insight-rule/{resource.name}"
+
+                        arn = f"arn:{get_partition(self.region_name)}:cloudwatch:{self.region_name}:{self.account_id}:{end_of_arn}"
+
+                        cw_tags = self.cloudwatch_backend.list_tags_for_resource(arn)
+
+                        tags = format_tags(cw_tags)
+                        if not tags or not tag_filter(tags):
+                            continue
+                        yield {
+                            "ResourceARN": arn,
+                            "Tags": tags,
+                        }
+
         # DMS
         if not resource_type_filters or "dms:endpoint" in resource_type_filters:
             for endpoint in self.dms_backend.endpoints.values():


Test patch:
diff --git a/tests/test_acmpca/test_acmpca.py b/tests/test_acmpca/test_acmpca.py
index ec98ae770..2fb446d49 100644
--- a/tests/test_acmpca/test_acmpca.py
+++ b/tests/test_acmpca/test_acmpca.py
@@ -480,11 +480,25 @@ def test_end_entity_certificate_issuance():
     )
     builder = cryptography.x509.verification.PolicyBuilder().store(store)
     verifier = builder.build_server_verifier(DNSName("bezoscorp.com"))
-    chain = verifier.verify(
-        cryptography.x509.load_pem_x509_certificate(ee_cert.encode("utf-8")), []
-    )
+    ee_x509 = cryptography.x509.load_pem_x509_certificate(ee_cert.encode("utf-8"))
+    chain = verifier.verify(ee_x509, [])
     assert len(chain) == 2
 
+    # Ensure extensions are passed through
+    san_extension = ee_x509.extensions.get_extension_for_oid(
+        cryptography.x509.oid.ExtensionOID.SUBJECT_ALTERNATIVE_NAME
+    )
+    assert san_extension.value.get_values_for_type(cryptography.x509.OtherName)
+    assert san_extension.value.get_values_for_type(cryptography.x509.RFC822Name) == [
+        "hello@moto.com"
+    ]
+    assert san_extension.value.get_values_for_type(cryptography.x509.DNSName) == [
+        "bezoscorp.com"
+    ]
+    assert san_extension.value.get_values_for_type(
+        cryptography.x509.UniformResourceIdentifier
+    ) == ["https://github.com/getmoto/moto"]
+
 
 @mock_aws
 def test_tag_certificate_authority():
@@ -597,6 +611,22 @@ def create_csr(private_key, country, state, org, cn):
             cryptography.x509.BasicConstraints(ca=False, path_length=None),
             critical=True,
         )
+        .add_extension(
+            cryptography.x509.SubjectAlternativeName(
+                [
+                    cryptography.x509.DNSName(cn),
+                    cryptography.x509.RFC822Name("hello@moto.com"),
+                    cryptography.x509.OtherName(
+                        type_id=cryptography.x509.ObjectIdentifier("2.5.4.3"),
+                        value=b"\x13\x02mo",
+                    ),
+                    cryptography.x509.UniformResourceIdentifier(
+                        "https://github.com/getmoto/moto"
+                    ),
+                ]
+            ),
+            critical=False,
+        )
         .sign(private_key, hashes.SHA256())
     )
     return csr.public_bytes(serialization.Encoding.PEM)
diff --git a/tests/test_cloudwatch/test_cloudwatch_insight_rules.py b/tests/test_cloudwatch/test_cloudwatch_insight_rules.py
new file mode 100644
index 000000000..dbdeda965
--- /dev/null
+++ b/tests/test_cloudwatch/test_cloudwatch_insight_rules.py
@@ -0,0 +1,154 @@
+import boto3
+import pytest
+
+from moto import mock_aws
+
+
+@mock_aws
+@pytest.mark.parametrize(
+    "region,partition", [("eu-west-1", "aws"), ("cn-north-1", "aws-cn")]
+)
+def test_put_insight_rule(region, partition):
+    cloudwatch = boto3.client("cloudwatch", region)
+
+    rule_name = "MySampleInsightRule"
+    log_group_name = "my-log-group"
+    rule_body = f"""
+    {{
+      "Schema": "CloudWatchLogRule",
+      "LogGroupNames": ["{log_group_name}"],
+      "LogFormat": "JSON",
+      "Filter": "[timestamp, request, statusCode = *]",
+      "Contribution": {{
+        "Keys": ["statusCode"],
+        "ValueOf": "Count"
+      }}
+    }}
+    """
+    cloudwatch.put_insight_rule(
+        RuleName=rule_name, RuleDefinition=rule_body, RuleState="ENABLED"
+    )
+
+    rules = cloudwatch.describe_insight_rules()["InsightRules"]
+    assert len(rules) == 1
+    rule = rules[0]
+    assert rule["Name"] == "MySampleInsightRule"
+    assert rule["State"] == "ENABLED"
+    assert rule["Schema"] == '{"Name" : "CloudWatchLogRule", "Version" : 1}'
+    assert rule["Definition"] == rule_body
+    assert rule["ManagedRule"] is not True
+
+
+@mock_aws
+def test_delete_insight_rules():
+    cloudwatch = boto3.client("cloudwatch", region_name="eu-central-1")
+
+    rule_name = "MySampleInsightRule"
+    log_group_name = "my-log-group"
+    rule_body = f"""
+    {{
+      "Schema": "CloudWatchLogRule",
+      "LogGroupNames": ["{log_group_name}"],
+      "LogFormat": "JSON",
+      "Filter": "[timestamp, request, statusCode = *]",
+      "Contribution": {{
+        "Keys": ["statusCode"],
+        "ValueOf": "Count"
+      }}
+    }}
+    """
+
+    cloudwatch.put_insight_rule(
+        RuleName=rule_name, RuleDefinition=rule_body, RuleState="ENABLED"
+    )
+
+    cloudwatch.put_insight_rule(
+        RuleName=f"{rule_name}_Backup", RuleDefinition=rule_body, RuleState="ENABLED"
+    )
+    rules = cloudwatch.describe_insight_rules()["InsightRules"]
+    assert len(rules) == 2
+
+    cloudwatch.delete_insight_rules(RuleNames=[rule_name])
+    rules = cloudwatch.describe_insight_rules()["InsightRules"]
+    assert len(rules) == 1
+
+    rule = rules[0]
+    assert rule["Name"] == "MySampleInsightRule_Backup"
+
+
+@mock_aws
+def test_disable_insight_rules():
+    cloudwatch = boto3.client("cloudwatch", region_name="eu-central-1")
+
+    rule_name = "MySampleInsightRule"
+    log_group_name = "my-log-group"
+    rule_body = f"""
+    {{
+      "Schema": "CloudWatchLogRule",
+      "LogGroupNames": ["{log_group_name}"],
+      "LogFormat": "JSON",
+      "Filter": "[timestamp, request, statusCode = *]",
+      "Contribution": {{
+        "Keys": ["statusCode"],
+        "ValueOf": "Count"
+      }}
+    }}
+    """
+
+    cloudwatch.put_insight_rule(
+        RuleName=rule_name, RuleDefinition=rule_body, RuleState="ENABLED"
+    )
+
+    cloudwatch.put_insight_rule(
+        RuleName=f"{rule_name}_Backup", RuleDefinition=rule_body, RuleState="ENABLED"
+    )
+
+    cloudwatch.disable_insight_rules(RuleNames=[rule_name])
+
+    rules = cloudwatch.describe_insight_rules()
+
+    # Ensuring correct rule was disabled, other should remain enabled
+    for r in rules["InsightRules"]:
+        if r["Name"] == rule_name:
+            assert r["State"] == "DISABLED"
+        else:
+            assert r["State"] == "ENABLED"
+
+
+@mock_aws
+def test_enable_insight_rules():
+    cloudwatch = boto3.client("cloudwatch", region_name="eu-central-1")
+
+    rule_name = "MySampleInsightRule"
+    log_group_name = "my-log-group"
+    rule_body = f"""
+    {{
+      "Schema": "CloudWatchLogRule",
+      "LogGroupNames": ["{log_group_name}"],
+      "LogFormat": "JSON",
+      "Filter": "[timestamp, request, statusCode = *]",
+      "Contribution": {{
+        "Keys": ["statusCode"],
+        "ValueOf": "Count"
+      }}
+    }}
+    """
+
+    cloudwatch.put_insight_rule(
+        RuleName=rule_name, RuleDefinition=rule_body, RuleState="DISABLED"
+    )
+
+    cloudwatch.put_insight_rule(
+        RuleName=f"{rule_name}_Backup", RuleDefinition=rule_body, RuleState="DISABLED"
+    )
+
+    cloudwatch.enable_insight_rules(RuleNames=[rule_name])
+
+    rules = cloudwatch.describe_insight_rules()
+
+    # Ensuring correct rule was enabled, other should remain disabled
+    for r in rules["InsightRules"]:
+        if r["Name"] == rule_name:
+            assert r["State"] == "ENABLED"
+        else:
+            assert r["State"] == "DISABLED"
diff --git a/tests/test_cloudwatch/test_cloudwatch_tags.py b/tests/test_cloudwatch/test_cloudwatch_tags.py
index 4eac59820..8bc7ca612 100644
--- a/tests/test_cloudwatch/test_cloudwatch_tags.py
+++ b/tests/test_cloudwatch/test_cloudwatch_tags.py
@@ -199,3 +199,37 @@ def test_untag_resource_error_not_exists():
     assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 404
     assert ex.response["Error"]["Code"] == "ResourceNotFoundException"
     assert ex.response["Error"]["Message"] == "Unknown"
+
+
+@mock_aws
+def test_tag_insight_rules_resource():
+    client = boto3.client("cloudwatch", region_name="eu-central-1")
+
+    rule_name = "MySampleInsightRule"
+    log_group_name = "my-log-group"
+    rule_body = f"""
+    {{
+      "Schema": "CloudWatchLogRule",
+      "LogGroupNames": ["{log_group_name}"],
+      "LogFormat": "JSON",
+      "Filter": "[timestamp, request, statusCode = *]",
+      "Contribution": {{
+        "Keys": ["statusCode"],
+        "ValueOf": "Count"
+      }}
+    }}
+    """
+    tags = [{"Key": "ThisIsAKey", "Value": "ThisIsAValue"}]
+
+    client.put_insight_rule(
+        RuleName=rule_name, RuleDefinition=rule_body, RuleState="ENABLED", Tags=tags
+    )
+
+    arn = (
+        "arn:aws:cloudwatch:eu-central-1:123456789012:insight-rule/MySampleInsightRule"
+    )
+
+    response = client.list_tags_for_resource(ResourceARN=arn)
+    assert sorted(response["Tags"], key=itemgetter("Key")) == [
+        {"Key": "ThisIsAKey", "Value": "ThisIsAValue"},
+    ]
diff --git a/tests/test_resourcegroupstaggingapi/test_resourcegroupstaggingapi.py b/tests/test_resourcegroupstaggingapi/test_resourcegroupstaggingapi.py
index 1437df8ee..32d175790 100644
--- a/tests/test_resourcegroupstaggingapi/test_resourcegroupstaggingapi.py
+++ b/tests/test_resourcegroupstaggingapi/test_resourcegroupstaggingapi.py
@@ -605,6 +605,59 @@ def test_get_tag_values_lexv2_models():
     ]
 
 
+@mock_aws
+def test_get_tag_values_cloudwatch():
+    cloudwatch = boto3.client("cloudwatch", "us-east-1")
+
+    name = "tester"
+    cloudwatch.put_metric_alarm(
+        AlarmActions=["arn:alarm"],
+        AlarmDescription="A test",
+        AlarmName=name,
+        ComparisonOperator="GreaterThanOrEqualToThreshold",
+        Dimensions=[{"Name": "InstanceId", "Value": "i-0123457"}],
+        EvaluationPeriods=5,
+        InsufficientDataActions=["arn:insufficient"],
+        Namespace=f"{name}_namespace",
+        MetricName=f"{name}_metric",
+        OKActions=["arn:ok"],
+        Period=60,
+        Statistic="Average",
+        Threshold=2,
+        Unit="Seconds",
+        Tags=[{"Key": "key-1", "Value": "value-1"}],
+    )
+
+    cloudwatch.put_insight_rule(
+        RuleName=name,
+        RuleDefinition="""{"Schema": "CloudWatchLogRule}""",
+        RuleState="ENABLED",
+        Tags=[{"Key": "key-2", "Value": "value-2"}],
+    )
+    rtapi = boto3.client("resourcegroupstaggingapi", "us-east-1")
+
+    # Test alarm tag filtering
+    resp = rtapi.get_resources(
+        ResourceTypeFilters=["cloudwatch:alarm"],
+        TagFilters=[{"Key": "key-1", "Values": ["value-1"]}],
+    )
+    assert len(resp["ResourceTagMappingList"]) == 1
+    assert {"Key": "key-1", "Value": "value-1"} in resp["ResourceTagMappingList"][0][
+        "Tags"
+    ]
+
+    # Test insight-rule tag filtering
+    resp = rtapi.get_resources(
+        ResourceTypeFilters=["cloudwatch:insight-rule"],
+        TagFilters=[{"Key": "key-2", "Values": ["value-2"]}],
+    )
+
+    assert len(resp["ResourceTagMappingList"]) == 1
+    assert {"Key": "key-2", "Value": "value-2"} in resp["ResourceTagMappingList"][0][
+        "Tags"
+    ]
+
+
 @mock_aws
 def test_get_many_resources():
     elbv2 = boto3.client("elbv2", region_name="us-east-1")