1use crate::category::Category;
2use crate::severity::Severity;
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5use std::fmt;
6use std::sync::LazyLock;
7
8#[derive(Debug, Clone)]
10pub struct RuleDefinition {
11 pub id: &'static str,
12 pub category: Category,
13 pub description: &'static str,
14 pub origin: RuleOrigin,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize)]
19#[cfg_attr(feature = "wasm-bindings", derive(tsify::Tsify))]
20#[cfg_attr(feature = "uniffi-bindings", derive(uniffi::Record))]
21#[serde(rename_all = "camelCase")]
22pub struct RuleInfo {
23 pub id: String,
24 pub severity: Severity,
25 #[serde(default, skip_serializing_if = "Option::is_none")]
26 #[cfg_attr(feature = "uniffi-bindings", uniffi(default))]
27 pub category: Option<String>,
28 pub description: String,
29 pub origin: RuleOrigin,
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Hash)]
34#[cfg_attr(feature = "wasm-bindings", derive(tsify::Tsify))]
35#[cfg_attr(feature = "uniffi-bindings", derive(uniffi::Enum))]
36#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
37pub enum RuleOrigin {
38 Schema,
43 CfnLint,
45 Engine,
47 Custom,
49 Guard,
51}
52
53impl RuleOrigin {
54 pub const fn as_str(&self) -> &'static str {
55 match self {
56 RuleOrigin::Schema => "SCHEMA",
57 RuleOrigin::CfnLint => "CFN_LINT",
58 RuleOrigin::Engine => "ENGINE",
59 RuleOrigin::Custom => "CUSTOM",
60 RuleOrigin::Guard => "GUARD",
61 }
62 }
63}
64
65impl fmt::Display for RuleOrigin {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 f.write_str(self.as_str())
68 }
69}
70
71impl RuleDefinition {
72 pub fn severity(&self) -> Severity {
75 let prefix = self.id.chars().next().unwrap_or_else(|| panic!("RuleDefinition has empty ID"));
76 Severity::from_prefix(prefix)
77 }
78
79 pub fn to_rule_info(&self) -> RuleInfo {
80 RuleInfo::from(self)
81 }
82}
83
84impl From<&RuleDefinition> for RuleInfo {
85 fn from(rule: &RuleDefinition) -> Self {
86 RuleInfo {
87 id: rule.id.to_string(),
88 severity: rule.severity(),
89 category: Some(rule.category.as_str().into()),
90 description: rule.description.to_string(),
91 origin: rule.origin,
92 }
93 }
94}
95
96#[derive(Debug, Clone, PartialEq)]
98pub struct RuleMetadataEntry {
99 pub category: Option<String>,
100 pub description: String,
101 pub severity: Severity,
102 pub origin: RuleOrigin,
103}
104
105static RULE_REGISTRY_BY_ID: LazyLock<HashMap<&'static str, &'static RuleDefinition>> =
111 LazyLock::new(|| RULE_REGISTRY.iter().map(|r| (r.id, r)).collect());
112
113pub fn lookup_rule(id: &str) -> Option<&'static RuleDefinition> {
115 RULE_REGISTRY_BY_ID.get(id).copied()
116}
117
118pub fn build_rule_metadata_map() -> HashMap<String, RuleMetadataEntry> {
120 RULE_REGISTRY
121 .iter()
122 .map(|r| {
123 (
124 r.id.to_string(),
125 RuleMetadataEntry {
126 category: Some(r.category.as_str().into()),
127 description: r.description.to_string(),
128 severity: r.severity(),
129 origin: r.origin,
130 },
131 )
132 })
133 .collect()
134}
135
136pub const RULE_REGISTRY: &[RuleDefinition] = &[
137 RuleDefinition {
138 id: "F0000",
139 category: Category::Structure,
140 description: "Duplicate key in template",
141 origin: RuleOrigin::Schema,
142 },
143 RuleDefinition {
144 id: "F0001",
145 category: Category::Structure,
146 description: "Resources section must exist and be non-empty",
147 origin: RuleOrigin::Schema,
148 },
149 RuleDefinition {
150 id: "E0001",
151 category: Category::Structure,
152 description: "SAM (AWS::Serverless) transform would reject the template",
153 origin: RuleOrigin::CfnLint,
154 },
155 RuleDefinition {
156 id: "F0002",
157 category: Category::Structure,
158 description: "AWSTemplateFormatVersion must be 2010-09-09",
159 origin: RuleOrigin::Schema,
160 },
161 RuleDefinition {
162 id: "F0003",
163 category: Category::Structure,
164 description: "Maximum 200 parameters",
165 origin: RuleOrigin::Schema,
166 },
167 RuleDefinition {
168 id: "F0004",
169 category: Category::Structure,
170 description: "Maximum 200 outputs",
171 origin: RuleOrigin::Schema,
172 },
173 RuleDefinition {
174 id: "F0005",
175 category: Category::Structure,
176 description: "Top-level keys must be valid section names",
177 origin: RuleOrigin::Schema,
178 },
179 RuleDefinition {
180 id: "F0006",
181 category: Category::Structure,
182 description: "Logical IDs must be alphanumeric",
183 origin: RuleOrigin::Schema,
184 },
185 RuleDefinition {
186 id: "F0007",
187 category: Category::Structure,
188 description: "Maximum 500 resources",
189 origin: RuleOrigin::Schema,
190 },
191 RuleDefinition {
192 id: "F0008",
193 category: Category::Structure,
194 description: "Maximum 200 mappings",
195 origin: RuleOrigin::Schema,
196 },
197 RuleDefinition {
198 id: "F0009",
199 category: Category::Structure,
200 description: "Maximum 200 conditions",
201 origin: RuleOrigin::Schema,
202 },
203 RuleDefinition {
204 id: "F0010",
205 category: Category::Intrinsic,
206 description: "Fn::Sub second argument must be a map",
207 origin: RuleOrigin::Schema,
208 },
209 RuleDefinition {
210 id: "F0011",
211 category: Category::Structure,
212 description: "Description exceeds maximum 1024 characters",
213 origin: RuleOrigin::Schema,
214 },
215 RuleDefinition {
216 id: "F0013",
217 category: Category::Intrinsic,
218 description: "Fn::If must have exactly 3 elements",
219 origin: RuleOrigin::Schema,
220 },
221 RuleDefinition {
222 id: "F0014",
223 category: Category::Intrinsic,
224 description: "Boolean condition function (Fn::Equals/Fn::And/Fn::Or/Fn::Not) has invalid structure",
225 origin: RuleOrigin::Schema,
226 },
227 RuleDefinition {
228 id: "F0015",
229 category: Category::Parameter,
230 description: "Default value must match parameter Type",
231 origin: RuleOrigin::Schema,
232 },
233 RuleDefinition {
234 id: "F0016",
235 category: Category::Parameter,
236 description: "AllowedValues entries must match parameter Type",
237 origin: RuleOrigin::Schema,
238 },
239 RuleDefinition {
240 id: "F0017",
241 category: Category::Structure,
242 description: "Mapping level must be a map",
243 origin: RuleOrigin::Schema,
244 },
245 RuleDefinition {
246 id: "F1004",
247 category: Category::Structure,
248 description: "Description must be a string",
249 origin: RuleOrigin::Schema,
250 },
251 RuleDefinition {
252 id: "F0040",
253 category: Category::Structure,
254 description: "Output must have Value property",
255 origin: RuleOrigin::Schema,
256 },
257 RuleDefinition {
258 id: "F0050",
259 category: Category::Structure,
260 description: "Mapping must have valid 3-level structure",
261 origin: RuleOrigin::Schema,
262 },
263 RuleDefinition {
264 id: "E2001",
265 category: Category::Parameter,
266 description: "Parameters have appropriate properties",
267 origin: RuleOrigin::CfnLint,
268 },
269 RuleDefinition {
270 id: "F2002",
271 category: Category::Parameter,
272 description: "Parameter Type must be valid",
273 origin: RuleOrigin::Schema,
274 },
275 RuleDefinition {
276 id: "F2003",
277 category: Category::Parameter,
278 description: "Parameter name must be alphanumeric",
279 origin: RuleOrigin::Schema,
280 },
281 RuleDefinition {
282 id: "F2011",
283 category: Category::Parameter,
284 description: "Parameter name exceeds maximum length",
285 origin: RuleOrigin::Schema,
286 },
287 RuleDefinition {
288 id: "F2012",
289 category: Category::Parameter,
290 description: "Parameter Default must be in AllowedValues",
291 origin: RuleOrigin::Schema,
292 },
293 RuleDefinition {
294 id: "F3007",
295 category: Category::Structure,
296 description: "Logical ID used as both parameter and resource",
297 origin: RuleOrigin::Schema,
298 },
299 RuleDefinition {
300 id: "F3016",
301 category: Category::Structure,
302 description: "DeletionPolicy must be valid",
303 origin: RuleOrigin::Schema,
304 },
305 RuleDefinition {
306 id: "F0018",
307 category: Category::Structure,
308 description: "UpdateReplacePolicy must be valid",
309 origin: RuleOrigin::Schema,
310 },
311 RuleDefinition {
312 id: "E3038",
313 category: Category::Structure,
314 description: "Check if Serverless Resources have Serverless Transform",
315 origin: RuleOrigin::CfnLint,
316 },
317 RuleDefinition {
318 id: "E5001",
319 category: Category::Structure,
320 description: "Check that Modules resources are valid",
321 origin: RuleOrigin::CfnLint,
322 },
323 RuleDefinition {
324 id: "F6004",
325 category: Category::Structure,
326 description: "Output name must be alphanumeric",
327 origin: RuleOrigin::Schema,
328 },
329 RuleDefinition {
330 id: "F6005",
331 category: Category::Structure,
332 description: "Output Export name validation",
333 origin: RuleOrigin::Schema,
334 },
335 RuleDefinition {
336 id: "F6011",
337 category: Category::Structure,
338 description: "Output name exceeds maximum length",
339 origin: RuleOrigin::Schema,
340 },
341 RuleDefinition {
342 id: "F6101",
343 category: Category::Structure,
344 description: "Output value must be a string",
345 origin: RuleOrigin::Schema,
346 },
347 RuleDefinition {
348 id: "F7002",
349 category: Category::Structure,
350 description: "Mapping name exceeds maximum length",
351 origin: RuleOrigin::Schema,
352 },
353 RuleDefinition {
354 id: "E8002",
355 category: Category::Structure,
356 description: "Condition referenced by resource is not defined",
357 origin: RuleOrigin::Schema,
358 },
359 RuleDefinition {
360 id: "I1003",
361 category: Category::Structure,
362 description: "Validate if we are approaching the max size of a description",
363 origin: RuleOrigin::CfnLint,
364 },
365 RuleDefinition {
366 id: "I2010",
367 category: Category::Structure,
368 description: "Parameter limit",
369 origin: RuleOrigin::CfnLint,
370 },
371 RuleDefinition {
372 id: "I2011",
373 category: Category::Structure,
374 description: "Parameter name limit",
375 origin: RuleOrigin::CfnLint,
376 },
377 RuleDefinition {
378 id: "I3012",
379 category: Category::Structure,
380 description: "Resource name limit",
381 origin: RuleOrigin::CfnLint,
382 },
383 RuleDefinition {
384 id: "I6010",
385 category: Category::Structure,
386 description: "Output limit",
387 origin: RuleOrigin::CfnLint,
388 },
389 RuleDefinition {
390 id: "I6011",
391 category: Category::Structure,
392 description: "Output name limit",
393 origin: RuleOrigin::CfnLint,
394 },
395 RuleDefinition {
396 id: "I7002",
397 category: Category::Structure,
398 description: "Mapping name limit",
399 origin: RuleOrigin::CfnLint,
400 },
401 RuleDefinition {
402 id: "I7010",
403 category: Category::Structure,
404 description: "Mapping limit",
405 origin: RuleOrigin::CfnLint,
406 },
407 RuleDefinition {
408 id: "W2001",
409 category: Category::BestPractice,
410 description: "Check if Parameters are Used",
411 origin: RuleOrigin::CfnLint,
412 },
413 RuleDefinition {
414 id: "W2002",
415 category: Category::BestPractice,
416 description: "Parameter type is not officially supported by CloudFormation",
417 origin: RuleOrigin::CfnLint,
418 },
419 RuleDefinition {
420 id: "W7001",
421 category: Category::BestPractice,
422 description: "Check if Mappings are Used",
423 origin: RuleOrigin::CfnLint,
424 },
425 RuleDefinition {
426 id: "E8001",
427 category: Category::Structure,
428 description: "Conditions section must have valid structure",
429 origin: RuleOrigin::Schema,
430 },
431 RuleDefinition {
432 id: "E8003",
433 category: Category::Intrinsic,
434 description: "Fn::Equals must take exactly two scalar operands",
435 origin: RuleOrigin::Schema,
436 },
437 RuleDefinition {
438 id: "E8004",
439 category: Category::Intrinsic,
440 description: "Fn::And must take between 2 and 10 boolean conditions",
441 origin: RuleOrigin::Schema,
442 },
443 RuleDefinition {
444 id: "E8005",
445 category: Category::Intrinsic,
446 description: "Fn::Not must take exactly one boolean condition",
447 origin: RuleOrigin::Schema,
448 },
449 RuleDefinition {
450 id: "E8006",
451 category: Category::Intrinsic,
452 description: "Fn::Or must take between 2 and 10 boolean conditions",
453 origin: RuleOrigin::Schema,
454 },
455 RuleDefinition {
456 id: "W8001",
457 category: Category::BestPractice,
458 description: "Check if Conditions are Used",
459 origin: RuleOrigin::CfnLint,
460 },
461 RuleDefinition {
462 id: "W8003",
463 category: Category::BestPractice,
464 description: "Fn::Equals will always return true or false",
465 origin: RuleOrigin::CfnLint,
466 },
467 RuleDefinition {
468 id: "E8007",
469 category: Category::Intrinsic,
470 description: "Condition function value must be a string referencing a defined condition",
471 origin: RuleOrigin::Schema,
472 },
473 RuleDefinition {
474 id: "F8600",
475 category: Category::Structure,
476 description: "Rules section must be an object",
477 origin: RuleOrigin::Schema,
478 },
479 RuleDefinition {
480 id: "F8601",
481 category: Category::Structure,
482 description: "Rule must be an object",
483 origin: RuleOrigin::Schema,
484 },
485 RuleDefinition {
486 id: "F8603",
487 category: Category::Structure,
488 description: "Rule missing required Assertions property",
489 origin: RuleOrigin::Schema,
490 },
491 RuleDefinition {
492 id: "F8604",
493 category: Category::Structure,
494 description: "Rule Assertions must be an array",
495 origin: RuleOrigin::Schema,
496 },
497 RuleDefinition {
498 id: "F8605",
499 category: Category::Structure,
500 description: "Rule Assertions must not be empty",
501 origin: RuleOrigin::Schema,
502 },
503 RuleDefinition {
504 id: "F8606",
505 category: Category::Structure,
506 description: "Rule RuleCondition must be a condition function",
507 origin: RuleOrigin::Schema,
508 },
509 RuleDefinition {
510 id: "F8607",
511 category: Category::Structure,
512 description: "Rule assertion must be an object",
513 origin: RuleOrigin::Schema,
514 },
515 RuleDefinition {
516 id: "F8609",
517 category: Category::Structure,
518 description: "Rule assertion missing required Assert property",
519 origin: RuleOrigin::Schema,
520 },
521 RuleDefinition {
522 id: "F8610",
523 category: Category::Structure,
524 description: "Rule assertion Assert must be a condition function",
525 origin: RuleOrigin::Schema,
526 },
527 RuleDefinition {
528 id: "F8611",
529 category: Category::Structure,
530 description: "Disallowed function in Rules section",
531 origin: RuleOrigin::Schema,
532 },
533 RuleDefinition {
534 id: "W8602",
535 category: Category::BestPractice,
536 description: "Rule has unknown property",
537 origin: RuleOrigin::Engine,
538 },
539 RuleDefinition {
540 id: "W8608",
541 category: Category::BestPractice,
542 description: "Rule assertion has unknown property",
543 origin: RuleOrigin::Engine,
544 },
545 RuleDefinition {
546 id: "F1010",
547 category: Category::Intrinsic,
548 description: "Ref target must exist",
549 origin: RuleOrigin::Schema,
550 },
551 RuleDefinition {
552 id: "F1012",
553 category: Category::Intrinsic,
554 description: "FindInMap map name must exist in Mappings",
555 origin: RuleOrigin::Schema,
556 },
557 RuleDefinition {
558 id: "E9003",
559 category: Category::Intrinsic,
560 description: "GetAtt return type may not match usage context",
561 origin: RuleOrigin::CfnLint,
562 },
563 RuleDefinition {
564 id: "F1018",
565 category: Category::Intrinsic,
566 description: "Sub variables must resolve",
567 origin: RuleOrigin::Schema,
568 },
569 RuleDefinition {
570 id: "F1020",
571 category: Category::Intrinsic,
572 description: "Ref/GetAtt target must exist",
573 origin: RuleOrigin::Schema,
574 },
575 RuleDefinition {
576 id: "E9004",
577 category: Category::Intrinsic,
578 description: "GetAtt attribute must exist on target resource type",
579 origin: RuleOrigin::Schema,
580 },
581 RuleDefinition {
582 id: "E1029",
583 category: Category::Intrinsic,
584 description: "Substitution variable ${X} requires Fn::Sub",
585 origin: RuleOrigin::CfnLint,
586 },
587 RuleDefinition {
588 id: "E1040",
589 category: Category::Intrinsic,
590 description: "Check if GetAtt matches destination format",
591 origin: RuleOrigin::CfnLint,
592 },
593 RuleDefinition {
594 id: "E1041",
595 category: Category::Intrinsic,
596 description: "Check if Ref matches destination format",
597 origin: RuleOrigin::CfnLint,
598 },
599 RuleDefinition {
600 id: "F1050",
601 category: Category::Intrinsic,
602 description: "Select index must be non-negative",
603 origin: RuleOrigin::Schema,
604 },
605 RuleDefinition {
606 id: "E1028",
607 category: Category::Intrinsic,
608 description: "Fn::If condition must exist in Conditions section",
609 origin: RuleOrigin::Schema,
610 },
611 RuleDefinition {
612 id: "E1050",
613 category: Category::Intrinsic,
614 description: "Dynamic reference must match the SSM, ssm-secure, or Secrets Manager format",
615 origin: RuleOrigin::CfnLint,
616 },
617 RuleDefinition {
618 id: "W1019",
619 category: Category::Intrinsic,
620 description: "Parameter in Fn::Sub variable map is not used in the template string",
621 origin: RuleOrigin::CfnLint,
622 },
623 RuleDefinition {
624 id: "W1051",
625 category: Category::Intrinsic,
626 description: "Dynamic reference resolves secret value but property expects the secret ARN",
627 origin: RuleOrigin::CfnLint,
628 },
629 RuleDefinition {
630 id: "W1054",
631 category: Category::Intrinsic,
632 description: "String value matches a pseudo parameter; use Ref instead",
633 origin: RuleOrigin::CfnLint,
634 },
635 RuleDefinition {
636 id: "W1100",
637 category: Category::Structure,
638 description: "YAML merge key '<<' is not supported by CloudFormation",
639 origin: RuleOrigin::CfnLint,
640 },
641 RuleDefinition {
642 id: "E9101",
643 category: Category::Intrinsic,
644 description: "Invalid nesting of intrinsic functions",
645 origin: RuleOrigin::Schema,
646 },
647 RuleDefinition {
648 id: "E9106",
649 category: Category::Structure,
650 description: "Circular dependency in condition definitions",
651 origin: RuleOrigin::Schema,
652 },
653 RuleDefinition {
654 id: "F1101",
655 category: Category::Structure,
656 description: "Invalid YAML/JSON syntax",
657 origin: RuleOrigin::Schema,
658 },
659 RuleDefinition {
660 id: "W1102",
661 category: Category::BestPractice,
662 description: "Invalid intrinsic function usage",
663 origin: RuleOrigin::Engine,
664 },
665 RuleDefinition {
666 id: "W1103",
667 category: Category::Intrinsic,
668 description: "Unknown intrinsic function name",
669 origin: RuleOrigin::Engine,
670 },
671 RuleDefinition {
672 id: "E1103",
673 category: Category::Intrinsic,
674 description: "Validate the format of a value",
675 origin: RuleOrigin::CfnLint,
676 },
677 RuleDefinition {
678 id: "E1150",
679 category: Category::Intrinsic,
680 description: "Validate security group format",
681 origin: RuleOrigin::CfnLint,
682 },
683 RuleDefinition {
684 id: "E1151",
685 category: Category::Intrinsic,
686 description: "Validate VPC id format",
687 origin: RuleOrigin::CfnLint,
688 },
689 RuleDefinition {
690 id: "E1152",
691 category: Category::Intrinsic,
692 description: "Validate AMI id format",
693 origin: RuleOrigin::CfnLint,
694 },
695 RuleDefinition {
696 id: "E1153",
697 category: Category::Intrinsic,
698 description: "Validate security group name",
699 origin: RuleOrigin::CfnLint,
700 },
701 RuleDefinition {
702 id: "E1154",
703 category: Category::Intrinsic,
704 description: "Validate VPC subnet id format",
705 origin: RuleOrigin::CfnLint,
706 },
707 RuleDefinition {
708 id: "E1155",
709 category: Category::Intrinsic,
710 description: "Validate CloudWatch logs group name",
711 origin: RuleOrigin::CfnLint,
712 },
713 RuleDefinition {
714 id: "E1156",
715 category: Category::Intrinsic,
716 description: "Validate IAM role ARN format",
717 origin: RuleOrigin::CfnLint,
718 },
719 RuleDefinition {
720 id: "I1022",
721 category: Category::Intrinsic,
722 description: "Use Sub instead of Join",
723 origin: RuleOrigin::CfnLint,
724 },
725 RuleDefinition {
726 id: "W1020",
727 category: Category::BestPractice,
728 description: "Sub isn't needed if it doesn't have a variable defined",
729 origin: RuleOrigin::CfnLint,
730 },
731 RuleDefinition {
732 id: "F2015",
733 category: Category::Parameter,
734 description: "Default value is within parameter constraints",
735 origin: RuleOrigin::Schema,
736 },
737 RuleDefinition {
738 id: "W2506",
739 category: Category::BestPractice,
740 description: "Check if ImageId Parameters have the correct type",
741 origin: RuleOrigin::CfnLint,
742 },
743 RuleDefinition {
744 id: "F3004",
745 category: Category::Reference,
746 description: "Circular dependency detected",
747 origin: RuleOrigin::Schema,
748 },
749 RuleDefinition {
750 id: "E3005",
751 category: Category::Reference,
752 description: "Check DependsOn values for Resources",
753 origin: RuleOrigin::CfnLint,
754 },
755 RuleDefinition {
756 id: "W1001",
757 category: Category::BestPractice,
758 description: "Ref/GetAtt to resource that is available when conditions are applied",
759 origin: RuleOrigin::CfnLint,
760 },
761 RuleDefinition {
762 id: "W3005",
763 category: Category::BestPractice,
764 description: "Check obsolete DependsOn configuration for Resources",
765 origin: RuleOrigin::CfnLint,
766 },
767 RuleDefinition {
768 id: "W2503",
769 category: Category::BestPractice,
770 description: "Resource references conditional resource with mutually exclusive condition",
771 origin: RuleOrigin::Engine,
772 },
773 RuleDefinition {
774 id: "E2504",
775 category: Category::Resource,
776 description: "FIFO queue name must end with .fifo",
777 origin: RuleOrigin::Engine,
778 },
779 RuleDefinition {
780 id: "E2529",
781 category: Category::Resource,
782 description: "Check for SubscriptionFilters beyond 2 attachments to a CloudWatch Log Group",
783 origin: RuleOrigin::CfnLint,
784 },
785 RuleDefinition {
786 id: "E2530",
787 category: Category::Resource,
788 description: "SnapStart supports the configured runtime",
789 origin: RuleOrigin::CfnLint,
790 },
791 RuleDefinition {
792 id: "E3001",
793 category: Category::Resource,
794 description: "Basic CloudFormation Resource Check",
795 origin: RuleOrigin::CfnLint,
796 },
797 RuleDefinition {
798 id: "E3003",
799 category: Category::Resource,
800 description: "Required Resource properties are missing",
801 origin: RuleOrigin::CfnLint,
802 },
803 RuleDefinition {
804 id: "E3010",
805 category: Category::Resource,
806 description: "Resource limit not exceeded",
807 origin: RuleOrigin::CfnLint,
808 },
809 RuleDefinition {
810 id: "E3013",
811 category: Category::Resource,
812 description: "CloudFront Aliases",
813 origin: RuleOrigin::CfnLint,
814 },
815 RuleDefinition {
816 id: "E3016",
817 category: Category::Resource,
818 description: "Check UpdatePolicy values for Resources",
819 origin: RuleOrigin::CfnLint,
820 },
821 RuleDefinition {
822 id: "E3019",
823 category: Category::Resource,
824 description: "Validate that all resources have unique primary identifiers",
825 origin: RuleOrigin::CfnLint,
826 },
827 RuleDefinition {
828 id: "E3022",
829 category: Category::Resource,
830 description: "Resource SubnetRouteTableAssociation Properties",
831 origin: RuleOrigin::CfnLint,
832 },
833 RuleDefinition {
834 id: "E3024",
835 category: Category::Resource,
836 description: "Validate tag configuration",
837 origin: RuleOrigin::CfnLint,
838 },
839 RuleDefinition {
840 id: "E3025",
841 category: Category::Resource,
842 description: "Validates RDS DB Instance Class",
843 origin: RuleOrigin::CfnLint,
844 },
845 RuleDefinition {
846 id: "W9006",
847 category: Category::BestPractice,
848 description: "String length estimation through Fn::Sub",
849 origin: RuleOrigin::Engine,
850 },
851 RuleDefinition {
852 id: "W9007",
853 category: Category::BestPractice,
854 description: "Array items must be unique when required",
855 origin: RuleOrigin::Engine,
856 },
857 RuleDefinition {
858 id: "W9012",
859 category: Category::BestPractice,
860 description: "Provided pseudo-parameter override value is not a valid AWS value",
861 origin: RuleOrigin::Engine,
862 },
863 RuleDefinition {
864 id: "F3006",
865 category: Category::Schema,
866 description: "AWS resource type must be recognized and available in the configured region",
867 origin: RuleOrigin::Schema,
868 },
869 RuleDefinition {
870 id: "E3039",
871 category: Category::Resource,
872 description: "AttributeDefinitions / KeySchemas mismatch",
873 origin: RuleOrigin::CfnLint,
874 },
875 RuleDefinition {
876 id: "E3041",
877 category: Category::Resource,
878 description: "RecordSet HostedZoneName is a superdomain of or equal to Name",
879 origin: RuleOrigin::CfnLint,
880 },
881 RuleDefinition {
882 id: "E3042",
883 category: Category::Resource,
884 description: "Validate at least one essential container is specified",
885 origin: RuleOrigin::CfnLint,
886 },
887 RuleDefinition {
888 id: "E3048",
889 category: Category::Resource,
890 description: "Validate ECS Fargate tasks have required properties and values",
891 origin: RuleOrigin::CfnLint,
892 },
893 RuleDefinition {
894 id: "E3044",
895 category: Category::Resource,
896 description: "ECS service using FARGATE or EXTERNAL cannot use DAEMON scheduling",
897 origin: RuleOrigin::CfnLint,
898 },
899 RuleDefinition {
900 id: "E3045",
901 category: Category::Resource,
902 description: "Validate AccessControl are set with OwnershipControls",
903 origin: RuleOrigin::CfnLint,
904 },
905 RuleDefinition {
906 id: "E9002",
907 category: Category::Resource,
908 description: "SecurityGroup FromPort must be <= ToPort for the TCP and UDP protocols",
909 origin: RuleOrigin::Engine,
910 },
911 RuleDefinition {
912 id: "E3047",
913 category: Category::Resource,
914 description: "Validate ECS Fargate tasks have the right combination of CPU and memory",
915 origin: RuleOrigin::CfnLint,
916 },
917 RuleDefinition {
918 id: "W3049",
919 category: Category::BestPractice,
920 description: "ELB target group health check uses a fixed port that will not follow an ECS dynamic host port",
921 origin: RuleOrigin::CfnLint,
922 },
923 RuleDefinition {
924 id: "I3049",
925 category: Category::BestPractice,
926 description: "ELB target group relies on the default traffic-port health check for an ECS dynamic host port",
927 origin: RuleOrigin::CfnLint,
928 },
929 RuleDefinition {
930 id: "E3050",
931 category: Category::Resource,
932 description: "Check if REFing to a IAM resource with path set",
933 origin: RuleOrigin::CfnLint,
934 },
935 RuleDefinition {
936 id: "E3051",
937 category: Category::Resource,
938 description: "Validate the structure of a SSM document",
939 origin: RuleOrigin::CfnLint,
940 },
941 RuleDefinition {
942 id: "E3052",
943 category: Category::Resource,
944 description: "Validate ECS service requires NetworkConfiguration",
945 origin: RuleOrigin::CfnLint,
946 },
947 RuleDefinition {
948 id: "E3053",
949 category: Category::Resource,
950 description: "Validate ECS task definition has correct values for HostPort",
951 origin: RuleOrigin::CfnLint,
952 },
953 RuleDefinition {
954 id: "E3054",
955 category: Category::Resource,
956 description: "Validate ECS service using Fargate uses TaskDefinition that allows Fargate",
957 origin: RuleOrigin::CfnLint,
958 },
959 RuleDefinition {
960 id: "E3055",
961 category: Category::Resource,
962 description: "Check CreationPolicy values for Resources",
963 origin: RuleOrigin::CfnLint,
964 },
965 RuleDefinition {
966 id: "E3057",
967 category: Category::Resource,
968 description: "Validate that CloudFront TargetOriginId is a specified Origin",
969 origin: RuleOrigin::CfnLint,
970 },
971 RuleDefinition {
972 id: "E3059",
973 category: Category::Resource,
974 description: "Validate subnet CIDRs are within the CIDRs of the VPC",
975 origin: RuleOrigin::CfnLint,
976 },
977 RuleDefinition {
978 id: "E3060",
979 category: Category::Resource,
980 description: "Validate subnet CIDRs do not overlap with other subnets",
981 origin: RuleOrigin::CfnLint,
982 },
983 RuleDefinition {
984 id: "E3061",
985 category: Category::Resource,
986 description: "Validate the days for tierings in IntelligentTieringConfigurations",
987 origin: RuleOrigin::CfnLint,
988 },
989 RuleDefinition {
990 id: "E3677",
991 category: Category::Resource,
992 description: "Lambda ZipFile requires nodejs or python runtime",
993 origin: RuleOrigin::CfnLint,
994 },
995 RuleDefinition {
996 id: "E3501",
997 category: Category::Resource,
998 description: "Validate SQS queue properties are valid",
999 origin: RuleOrigin::CfnLint,
1000 },
1001 RuleDefinition {
1002 id: "E3502",
1003 category: Category::Resource,
1004 description: "Validate SQS DLQ queues are the same type",
1005 origin: RuleOrigin::CfnLint,
1006 },
1007 RuleDefinition {
1008 id: "E3504",
1009 category: Category::Resource,
1010 description: "Check minimum 90 period is met between BackupPlan cold and delete",
1011 origin: RuleOrigin::CfnLint,
1012 },
1013 RuleDefinition {
1014 id: "E3505",
1015 category: Category::Resource,
1016 description: "Validate SQS VisibilityTimeout is greater than a function's Timeout",
1017 origin: RuleOrigin::CfnLint,
1018 },
1019 RuleDefinition {
1020 id: "E3510",
1021 category: Category::Resource,
1022 description: "Validate identity based IAM policies",
1023 origin: RuleOrigin::CfnLint,
1024 },
1025 RuleDefinition {
1026 id: "E3511",
1027 category: Category::Resource,
1028 description: "Validate IAM role arn pattern",
1029 origin: RuleOrigin::CfnLint,
1030 },
1031 RuleDefinition {
1032 id: "E3512",
1033 category: Category::Resource,
1034 description: "Validate resource based IAM policies",
1035 origin: RuleOrigin::CfnLint,
1036 },
1037 RuleDefinition {
1038 id: "E3513",
1039 category: Category::Resource,
1040 description: "Validate ECR repository policy",
1041 origin: RuleOrigin::CfnLint,
1042 },
1043 RuleDefinition {
1044 id: "E3530",
1045 category: Category::Resource,
1046 description: "Validate IAM trust policies",
1047 origin: RuleOrigin::CfnLint,
1048 },
1049 RuleDefinition {
1050 id: "E3601",
1051 category: Category::Resource,
1052 description: "Validate the structure of a StateMachine definition",
1053 origin: RuleOrigin::CfnLint,
1054 },
1055 RuleDefinition {
1056 id: "E3628",
1057 category: Category::Resource,
1058 description: "Validate EC2 instance types based on region",
1059 origin: RuleOrigin::CfnLint,
1060 },
1061 RuleDefinition {
1062 id: "E3635",
1063 category: Category::Resource,
1064 description: "Validate Neptune DB instance class",
1065 origin: RuleOrigin::CfnLint,
1066 },
1067 RuleDefinition {
1068 id: "E3636",
1069 category: Category::Resource,
1070 description: "Validate CodeBuild projects using S3 also have Location",
1071 origin: RuleOrigin::CfnLint,
1072 },
1073 RuleDefinition {
1074 id: "E3639",
1075 category: Category::Resource,
1076 description: "Validate DynamoDB table ProvisionedThroughput is set when BillingMode is PROVISIONED",
1077 origin: RuleOrigin::CfnLint,
1078 },
1079 RuleDefinition {
1080 id: "E3641",
1081 category: Category::Resource,
1082 description: "Validate GameLift Fleet EC2 instance type",
1083 origin: RuleOrigin::CfnLint,
1084 },
1085 RuleDefinition {
1086 id: "E3660",
1087 category: Category::Resource,
1088 description: "RestApi requires a name when not using an OpenAPI specification",
1089 origin: RuleOrigin::CfnLint,
1090 },
1091 RuleDefinition {
1092 id: "E3663",
1093 category: Category::Resource,
1094 description: "Validate Lambda environment variable names aren't reserved",
1095 origin: RuleOrigin::CfnLint,
1096 },
1097 RuleDefinition {
1098 id: "E3667",
1099 category: Category::Resource,
1100 description: "Validate Redshift cluster node type",
1101 origin: RuleOrigin::CfnLint,
1102 },
1103 RuleDefinition {
1104 id: "E3670",
1105 category: Category::Resource,
1106 description: "Validate the instance types for an AmazonMQ Broker",
1107 origin: RuleOrigin::CfnLint,
1108 },
1109 RuleDefinition {
1110 id: "E3671",
1111 category: Category::Resource,
1112 description: "Validate block device mapping configuration",
1113 origin: RuleOrigin::CfnLint,
1114 },
1115 RuleDefinition {
1116 id: "E3675",
1117 category: Category::Resource,
1118 description: "Validate EMR cluster instance type",
1119 origin: RuleOrigin::CfnLint,
1120 },
1121 RuleDefinition {
1122 id: "E3676",
1123 category: Category::Resource,
1124 description: "Validate ELBv2 protocols that require certificates have a certificate specified",
1125 origin: RuleOrigin::CfnLint,
1126 },
1127 RuleDefinition {
1128 id: "E3679",
1129 category: Category::Resource,
1130 description: "Validate ELB protocols that require certificates have a certificate specified",
1131 origin: RuleOrigin::CfnLint,
1132 },
1133 RuleDefinition {
1134 id: "E3680",
1135 category: Category::Resource,
1136 description: "Application load balancers require at least 2 subnets",
1137 origin: RuleOrigin::CfnLint,
1138 },
1139 RuleDefinition {
1140 id: "E3685",
1141 category: Category::Resource,
1142 description: "Container image functions cannot use Handler, Runtime, or Layers",
1143 origin: RuleOrigin::CfnLint,
1144 },
1145 RuleDefinition {
1146 id: "E9006",
1147 category: Category::Schema,
1148 description: "Property value not valid for conditional extension enum",
1149 origin: RuleOrigin::CfnLint,
1150 },
1151 RuleDefinition {
1152 id: "E3698",
1153 category: Category::Resource,
1154 description: "API Gateway Stage and Deployment must use the same RestApi",
1155 origin: RuleOrigin::CfnLint,
1156 },
1157 RuleDefinition {
1158 id: "E3699",
1159 category: Category::Resource,
1160 description: "API Gateway Method and Authorizer must use the same RestApi",
1161 origin: RuleOrigin::CfnLint,
1162 },
1163 RuleDefinition {
1164 id: "E3700",
1165 category: Category::Resource,
1166 description: "Validate CodePipeline Source actions are only in the first stage",
1167 origin: RuleOrigin::CfnLint,
1168 },
1169 RuleDefinition {
1170 id: "E3701",
1171 category: Category::Resource,
1172 description: "Validate input and output artifact names are used properly",
1173 origin: RuleOrigin::CfnLint,
1174 },
1175 RuleDefinition {
1176 id: "E3702",
1177 category: Category::Resource,
1178 description: "Validate the number of input and output artifacts in a CodePipeline",
1179 origin: RuleOrigin::CfnLint,
1180 },
1181 RuleDefinition {
1182 id: "E3703",
1183 category: Category::Resource,
1184 description: "Validate the configuration of a pipeline action",
1185 origin: RuleOrigin::CfnLint,
1186 },
1187 RuleDefinition {
1188 id: "E3704",
1189 category: Category::Resource,
1190 description: "Validate TransitEncryptionEnabled is set when using Valkey engine",
1191 origin: RuleOrigin::CfnLint,
1192 },
1193 RuleDefinition {
1194 id: "E3705",
1195 category: Category::Resource,
1196 description: "Validate SQS FIFO queue EventSourceMapping BatchSize is at most 10",
1197 origin: RuleOrigin::CfnLint,
1198 },
1199 RuleDefinition {
1200 id: "E3706",
1201 category: Category::Resource,
1202 description: "MaxSize must be greater than or equal to MinSize",
1203 origin: RuleOrigin::CfnLint,
1204 },
1205 RuleDefinition {
1206 id: "E3707",
1207 category: Category::Resource,
1208 description: "Validate RDS DBInstance Engine matches DBCluster Engine",
1209 origin: RuleOrigin::CfnLint,
1210 },
1211 RuleDefinition {
1212 id: "E3708",
1213 category: Category::Resource,
1214 description: "API Gateway Method AuthorizationType must match Authorizer Type",
1215 origin: RuleOrigin::CfnLint,
1216 },
1217 RuleDefinition {
1218 id: "I9002",
1219 category: Category::BestPractice,
1220 description: "Property is ignored in this configuration (from extension)",
1221 origin: RuleOrigin::Engine,
1222 },
1223 RuleDefinition {
1224 id: "I9003",
1225 category: Category::BestPractice,
1226 description: "Region-scoped values validated against all regions because no region was supplied",
1227 origin: RuleOrigin::Engine,
1228 },
1229 RuleDefinition {
1230 id: "I3037",
1231 category: Category::BestPractice,
1232 description: "Check if a list that allows duplicates has any duplicates",
1233 origin: RuleOrigin::CfnLint,
1234 },
1235 RuleDefinition {
1236 id: "I3510",
1237 category: Category::Security,
1238 description: "Validate statement resources match the actions",
1239 origin: RuleOrigin::CfnLint,
1240 },
1241 RuleDefinition {
1242 id: "W1028",
1243 category: Category::BestPractice,
1244 description: "Check Fn::If has a path that cannot be reached",
1245 origin: RuleOrigin::CfnLint,
1246 },
1247 RuleDefinition {
1248 id: "W1030",
1249 category: Category::BestPractice,
1250 description: "Validate the values that come from a Ref function",
1251 origin: RuleOrigin::CfnLint,
1252 },
1253 RuleDefinition {
1254 id: "W1053",
1255 category: Category::BestPractice,
1256 description: "Dynamic references should not contain spaces",
1257 origin: RuleOrigin::CfnLint,
1258 },
1259 RuleDefinition {
1260 id: "W2010",
1261 category: Category::Security,
1262 description: "NoEcho parameters are not masked when used in Metadata and Outputs",
1263 origin: RuleOrigin::CfnLint,
1264 },
1265 RuleDefinition {
1266 id: "W2502",
1267 category: Category::BestPractice,
1268 description: "DependsOn conditional resource without matching condition",
1269 origin: RuleOrigin::Engine,
1270 },
1271 RuleDefinition {
1272 id: "W2530",
1273 category: Category::BestPractice,
1274 description: "Validate that SnapStart is properly configured",
1275 origin: RuleOrigin::CfnLint,
1276 },
1277 RuleDefinition {
1278 id: "W2533",
1279 category: Category::BestPractice,
1280 description: "Check required properties for Lambda if the deployment package is a .zip file",
1281 origin: RuleOrigin::CfnLint,
1282 },
1283 RuleDefinition {
1284 id: "W3010",
1285 category: Category::BestPractice,
1286 description: "Availability zone properties should not be hardcoded",
1287 origin: RuleOrigin::CfnLint,
1288 },
1289 RuleDefinition {
1290 id: "W1011",
1291 category: Category::Security,
1292 description: "Instead of REFing a parameter for a secret use a dynamic reference",
1293 origin: RuleOrigin::CfnLint,
1294 },
1295 RuleDefinition {
1296 id: "W2501",
1297 category: Category::Security,
1298 description: "Check if Password Properties are correctly configured",
1299 origin: RuleOrigin::CfnLint,
1300 },
1301 RuleDefinition {
1302 id: "W2508",
1303 category: Category::Security,
1304 description: "Security group allows open access to sensitive port",
1305 origin: RuleOrigin::Engine,
1306 },
1307 RuleDefinition {
1308 id: "W2509",
1309 category: Category::Security,
1310 description: "Password parameter should have NoEcho",
1311 origin: RuleOrigin::Engine,
1312 },
1313 RuleDefinition {
1314 id: "W2511",
1315 category: Category::Security,
1316 description: "Check IAM Resource Policies syntax",
1317 origin: RuleOrigin::CfnLint,
1318 },
1319 RuleDefinition {
1320 id: "W2512",
1321 category: Category::Security,
1322 description: "IAM policy with NotAction",
1323 origin: RuleOrigin::Engine,
1324 },
1325 RuleDefinition {
1326 id: "W9008",
1327 category: Category::Security,
1328 description: "RDS instance should have StorageEncrypted",
1329 origin: RuleOrigin::Engine,
1330 },
1331 RuleDefinition {
1332 id: "W9011",
1333 category: Category::Security,
1334 description: "RDS instance PubliclyAccessible is true",
1335 origin: RuleOrigin::Engine,
1336 },
1337 RuleDefinition {
1338 id: "W3663",
1339 category: Category::Security,
1340 description: "Validate SourceAccount is required property",
1341 origin: RuleOrigin::CfnLint,
1342 },
1343 RuleDefinition {
1344 id: "E3687",
1345 category: Category::Resource,
1346 description: "Validate to and from ports based on the protocol",
1347 origin: RuleOrigin::CfnLint,
1348 },
1349 RuleDefinition {
1350 id: "W3687",
1351 category: Category::BestPractice,
1352 description: "Validate that ports aren't specified for certain protocols",
1353 origin: RuleOrigin::CfnLint,
1354 },
1355 RuleDefinition {
1356 id: "I2530",
1357 category: Category::BestPractice,
1358 description: "Validate that SnapStart is configured for >= Java11 runtimes",
1359 origin: RuleOrigin::CfnLint,
1360 },
1361 RuleDefinition {
1362 id: "I3011",
1363 category: Category::BestPractice,
1364 description: "Check stateful resources have a set UpdateReplacePolicy/DeletionPolicy",
1365 origin: RuleOrigin::CfnLint,
1366 },
1367 RuleDefinition {
1368 id: "I3013",
1369 category: Category::BestPractice,
1370 description: "Check resources with auto expiring content have explicit retention period",
1371 origin: RuleOrigin::CfnLint,
1372 },
1373 RuleDefinition {
1374 id: "I9040",
1375 category: Category::BestPractice,
1376 description: "Resource should have Tags",
1377 origin: RuleOrigin::Engine,
1378 },
1379 RuleDefinition {
1380 id: "I3042",
1381 category: Category::BestPractice,
1382 description: "ARNs should use correctly placed Pseudo Parameters",
1383 origin: RuleOrigin::CfnLint,
1384 },
1385 RuleDefinition {
1386 id: "I3100",
1387 category: Category::BestPractice,
1388 description: "Checks for legacy instance type generations",
1389 origin: RuleOrigin::CfnLint,
1390 },
1391 RuleDefinition {
1392 id: "W9010",
1393 category: Category::Security,
1394 description: "Hardcoded AMI ID",
1395 origin: RuleOrigin::Engine,
1396 },
1397 RuleDefinition {
1398 id: "W9013",
1399 category: Category::Security,
1400 description: "Hardcoded account ID in ARN",
1401 origin: RuleOrigin::Engine,
1402 },
1403 RuleDefinition {
1404 id: "W9053",
1405 category: Category::BestPractice,
1406 description: "Conditions are semantically equivalent and can be consolidated",
1407 origin: RuleOrigin::Engine,
1408 },
1409 RuleDefinition {
1410 id: "W9052",
1411 category: Category::Structure,
1412 description: "Deterministic validation budgets were exhausted; see report metadata for completeness impact",
1413 origin: RuleOrigin::Engine,
1414 },
1415 RuleDefinition {
1416 id: "W9002",
1417 category: Category::BestPractice,
1418 description: "Hardcoded ARN property",
1419 origin: RuleOrigin::Engine,
1420 },
1421 RuleDefinition {
1422 id: "W3011",
1423 category: Category::BestPractice,
1424 description: "Check resources with UpdateReplacePolicy/DeletionPolicy have both",
1425 origin: RuleOrigin::CfnLint,
1426 },
1427 RuleDefinition {
1428 id: "E2531",
1429 category: Category::Deprecation,
1430 description: "Check if Lambda Function Runtimes are blocked for create",
1431 origin: RuleOrigin::CfnLint,
1432 },
1433 RuleDefinition {
1434 id: "E2533",
1435 category: Category::Deprecation,
1436 description: "Check if Lambda Function Runtimes are updatable",
1437 origin: RuleOrigin::CfnLint,
1438 },
1439 RuleDefinition {
1440 id: "E3710",
1441 category: Category::Deprecation,
1442 description: "Resource type is from a service that has been shut down",
1443 origin: RuleOrigin::CfnLint,
1444 },
1445 RuleDefinition {
1446 id: "W2531",
1447 category: Category::Deprecation,
1448 description: "Check if EOL Lambda Function Runtimes are used",
1449 origin: RuleOrigin::CfnLint,
1450 },
1451 RuleDefinition {
1452 id: "W3045",
1453 category: Category::Deprecation,
1454 description: "Controlling access to an S3 bucket should be done with bucket policies",
1455 origin: RuleOrigin::CfnLint,
1456 },
1457 RuleDefinition {
1458 id: "W3696",
1459 category: Category::Deprecation,
1460 description: "Resource type is from a service that is sunsetting",
1461 origin: RuleOrigin::CfnLint,
1462 },
1463 RuleDefinition {
1464 id: "W3697",
1465 category: Category::Deprecation,
1466 description: "Resource type is from a service in maintenance mode",
1467 origin: RuleOrigin::CfnLint,
1468 },
1469 RuleDefinition {
1470 id: "E6001",
1471 category: Category::Structure,
1472 description: "Outputs have appropriate properties",
1473 origin: RuleOrigin::CfnLint,
1474 },
1475 RuleDefinition {
1476 id: "E6003",
1477 category: Category::Structure,
1478 description: "Outputs section must be an object of named output definitions",
1479 origin: RuleOrigin::CfnLint,
1480 },
1481 RuleDefinition {
1482 id: "E6005",
1483 category: Category::Structure,
1484 description: "Condition referenced by an output must exist in the Conditions section",
1485 origin: RuleOrigin::Schema,
1486 },
1487 RuleDefinition {
1488 id: "E7001",
1489 category: Category::Structure,
1490 description: "Mappings are appropriately configured",
1491 origin: RuleOrigin::CfnLint,
1492 },
1493 RuleDefinition {
1494 id: "E3002",
1495 category: Category::Schema,
1496 description: "Resource properties are invalid",
1497 origin: RuleOrigin::CfnLint,
1498 },
1499 RuleDefinition {
1500 id: "E3012",
1501 category: Category::Schema,
1502 description: "Check resource properties values",
1503 origin: RuleOrigin::CfnLint,
1504 },
1505 RuleDefinition {
1506 id: "E3030",
1507 category: Category::Schema,
1508 description: "Check if properties have a valid value",
1509 origin: RuleOrigin::CfnLint,
1510 },
1511 RuleDefinition {
1512 id: "E3031",
1513 category: Category::Schema,
1514 description: "Check if property values adhere to a specific pattern",
1515 origin: RuleOrigin::CfnLint,
1516 },
1517 RuleDefinition {
1518 id: "E3032",
1519 category: Category::Schema,
1520 description: "Check if an array has between min and max number of values",
1521 origin: RuleOrigin::CfnLint,
1522 },
1523 RuleDefinition {
1524 id: "E3034",
1525 category: Category::Schema,
1526 description: "Check if a number is between min and max",
1527 origin: RuleOrigin::CfnLint,
1528 },
1529 RuleDefinition {
1530 id: "F3002",
1531 category: Category::Schema,
1532 description: "Additional properties are not allowed",
1533 origin: RuleOrigin::Schema,
1534 },
1535 RuleDefinition {
1536 id: "F3003",
1537 category: Category::Schema,
1538 description: "Required property missing",
1539 origin: RuleOrigin::Schema,
1540 },
1541 RuleDefinition {
1542 id: "F3012",
1543 category: Category::Schema,
1544 description: "Property type mismatch",
1545 origin: RuleOrigin::Schema,
1546 },
1547 RuleDefinition {
1548 id: "F3014",
1549 category: Category::Schema,
1550 description: "Exactly one of properties required (requiredXor)",
1551 origin: RuleOrigin::Schema,
1552 },
1553 RuleDefinition {
1554 id: "F3017",
1555 category: Category::Schema,
1556 description: "Value not valid under anyOf",
1557 origin: RuleOrigin::Schema,
1558 },
1559 RuleDefinition {
1560 id: "F3018",
1561 category: Category::Schema,
1562 description: "Value not valid under oneOf",
1563 origin: RuleOrigin::Schema,
1564 },
1565 RuleDefinition {
1566 id: "F3020",
1567 category: Category::Schema,
1568 description: "Mutually exclusive properties",
1569 origin: RuleOrigin::Schema,
1570 },
1571 RuleDefinition {
1572 id: "F3021",
1573 category: Category::Schema,
1574 description: "Dependent property required",
1575 origin: RuleOrigin::Schema,
1576 },
1577 RuleDefinition {
1578 id: "F3030",
1579 category: Category::Schema,
1580 description: "Value does not match the required constant",
1581 origin: RuleOrigin::Schema,
1582 },
1583 RuleDefinition {
1584 id: "W3030",
1585 category: Category::Schema,
1586 description: "Value not in allowed enum",
1587 origin: RuleOrigin::CfnLint,
1588 },
1589 RuleDefinition {
1590 id: "F3031",
1591 category: Category::Schema,
1592 description: "Value does not match pattern",
1593 origin: RuleOrigin::Schema,
1594 },
1595 RuleDefinition {
1596 id: "F3032",
1597 category: Category::Schema,
1598 description: "Array item count out of bounds",
1599 origin: RuleOrigin::Schema,
1600 },
1601 RuleDefinition {
1602 id: "F3033",
1603 category: Category::Schema,
1604 description: "String length out of bounds",
1605 origin: RuleOrigin::Schema,
1606 },
1607 RuleDefinition {
1608 id: "F3034",
1609 category: Category::Schema,
1610 description: "Numeric value out of bounds",
1611 origin: RuleOrigin::Schema,
1612 },
1613 RuleDefinition {
1614 id: "F3037",
1615 category: Category::Schema,
1616 description: "Array items not unique",
1617 origin: RuleOrigin::Schema,
1618 },
1619 RuleDefinition {
1620 id: "E3040",
1621 category: Category::Schema,
1622 description: "Read only property should not be specified",
1623 origin: RuleOrigin::CfnLint,
1624 },
1625 RuleDefinition {
1626 id: "W9054",
1627 category: Category::BestPractice,
1628 description: "Write-only property referenced in output",
1629 origin: RuleOrigin::Engine,
1630 },
1631 RuleDefinition {
1632 id: "F3058",
1633 category: Category::Schema,
1634 description: "One of properties required (requiredOr)",
1635 origin: RuleOrigin::Schema,
1636 },
1637 RuleDefinition {
1638 id: "I9001",
1639 category: Category::BestPractice,
1640 description: "Create-only property updated triggers resource replacement",
1641 origin: RuleOrigin::Engine,
1642 },
1643 RuleDefinition {
1644 id: "W9003",
1645 category: Category::BestPractice,
1646 description: "Property type coercion warning",
1647 origin: RuleOrigin::CfnLint,
1648 },
1649 RuleDefinition {
1650 id: "W9009",
1651 category: Category::Deprecation,
1652 description: "Resource type sunset or shutdown",
1653 origin: RuleOrigin::Engine,
1654 },
1655 RuleDefinition {
1656 id: "E1002",
1657 category: Category::Structure,
1658 description: "Validate if a template size is too large",
1659 origin: RuleOrigin::CfnLint,
1660 },
1661 RuleDefinition {
1662 id: "E1005",
1663 category: Category::Structure,
1664 description: "Validate Transform configuration",
1665 origin: RuleOrigin::CfnLint,
1666 },
1667 RuleDefinition {
1668 id: "E1015",
1669 category: Category::Intrinsic,
1670 description: "GetAz validation of parameters",
1671 origin: RuleOrigin::Schema,
1672 },
1673 RuleDefinition {
1674 id: "E1016",
1675 category: Category::Intrinsic,
1676 description: "ImportValue validation of parameters",
1677 origin: RuleOrigin::Schema,
1678 },
1679 RuleDefinition {
1680 id: "E1011",
1681 category: Category::Intrinsic,
1682 description: "Fn::FindInMap operands must be strings or one of Ref/Fn::FindInMap",
1683 origin: RuleOrigin::Schema,
1684 },
1685 RuleDefinition {
1686 id: "E1017",
1687 category: Category::Intrinsic,
1688 description: "Fn::Select requires exactly two operands and a list source",
1689 origin: RuleOrigin::Schema,
1690 },
1691 RuleDefinition {
1692 id: "E1018",
1693 category: Category::Intrinsic,
1694 description: "Fn::Split source must be a string or a string-producing intrinsic",
1695 origin: RuleOrigin::Schema,
1696 },
1697 RuleDefinition {
1698 id: "E1019",
1699 category: Category::Intrinsic,
1700 description: "Fn::Sub variable map values must be strings or string-producing intrinsics",
1701 origin: RuleOrigin::Schema,
1702 },
1703 RuleDefinition {
1704 id: "E1021",
1705 category: Category::Intrinsic,
1706 description: "Fn::Base64 argument must be a string or a string-producing intrinsic",
1707 origin: RuleOrigin::Schema,
1708 },
1709 RuleDefinition {
1710 id: "E1022",
1711 category: Category::Intrinsic,
1712 description: "Fn::Join requires a string delimiter and a list of strings or string-producing intrinsics",
1713 origin: RuleOrigin::Schema,
1714 },
1715 RuleDefinition {
1716 id: "E1024",
1717 category: Category::Intrinsic,
1718 description: "Fn::Cidr requires a CIDR-format ipBlock string and integer count/cidrBits",
1719 origin: RuleOrigin::Schema,
1720 },
1721 RuleDefinition {
1722 id: "E1027",
1723 category: Category::Intrinsic,
1724 description: "Check dynamic references secure strings are in supported locations",
1725 origin: RuleOrigin::CfnLint,
1726 },
1727 RuleDefinition {
1728 id: "E1030",
1729 category: Category::Intrinsic,
1730 description: "Fn::Length argument must be an array or a list-producing function",
1731 origin: RuleOrigin::Schema,
1732 },
1733 RuleDefinition {
1734 id: "E1031",
1735 category: Category::Intrinsic,
1736 description: "Fn::ToJsonString argument must be a non-empty array/object or a supported function",
1737 origin: RuleOrigin::Schema,
1738 },
1739 RuleDefinition {
1740 id: "F1030",
1741 category: Category::Intrinsic,
1742 description: "Fn::Length requires the AWS::LanguageExtensions transform",
1743 origin: RuleOrigin::Schema,
1744 },
1745 RuleDefinition {
1746 id: "F1031",
1747 category: Category::Intrinsic,
1748 description: "Fn::ToJsonString requires the AWS::LanguageExtensions transform",
1749 origin: RuleOrigin::Schema,
1750 },
1751 RuleDefinition {
1752 id: "F1032",
1753 category: Category::Intrinsic,
1754 description: "Fn::ForEach requires the AWS::LanguageExtensions transform",
1755 origin: RuleOrigin::Schema,
1756 },
1757 RuleDefinition {
1758 id: "E1033",
1759 category: Category::Intrinsic,
1760 description: "GetStackOutput validation of parameters",
1761 origin: RuleOrigin::Schema,
1762 },
1763 RuleDefinition {
1764 id: "E1051",
1765 category: Category::Intrinsic,
1766 description: "Validate dynamic references to secrets manager are only in resource properties",
1767 origin: RuleOrigin::CfnLint,
1768 },
1769 RuleDefinition {
1770 id: "E1052",
1771 category: Category::Intrinsic,
1772 description: "Validate dynamic references to SSM are in a valid location",
1773 origin: RuleOrigin::CfnLint,
1774 },
1775 RuleDefinition {
1776 id: "E3011",
1777 category: Category::Resource,
1778 description: "Check property names in Resources",
1779 origin: RuleOrigin::CfnLint,
1780 },
1781 RuleDefinition {
1782 id: "E3023",
1783 category: Category::Resource,
1784 description: "Validate Route53 RecordSets",
1785 origin: RuleOrigin::CfnLint,
1786 },
1787 RuleDefinition {
1788 id: "E3026",
1789 category: Category::Resource,
1790 description: "Check Elastic Cache Redis Cluster settings",
1791 origin: RuleOrigin::CfnLint,
1792 },
1793 RuleDefinition {
1794 id: "E3027",
1795 category: Category::Resource,
1796 description: "Validate AWS Event ScheduleExpression format",
1797 origin: RuleOrigin::CfnLint,
1798 },
1799 RuleDefinition {
1800 id: "E3029",
1801 category: Category::Resource,
1802 description: "Validate Route53 record set aliases",
1803 origin: RuleOrigin::CfnLint,
1804 },
1805 RuleDefinition {
1806 id: "E3062",
1807 category: Category::Resource,
1808 description: "Validates RDS DB Instance Class based on Engine and EngineVersion",
1809 origin: RuleOrigin::CfnLint,
1810 },
1811 RuleDefinition {
1812 id: "E3617",
1813 category: Category::Resource,
1814 description: "Validate ManagedBlockchain instance type",
1815 origin: RuleOrigin::CfnLint,
1816 },
1817 RuleDefinition {
1818 id: "E3620",
1819 category: Category::Resource,
1820 description: "Validate a DocDB DB Instance class",
1821 origin: RuleOrigin::CfnLint,
1822 },
1823 RuleDefinition {
1824 id: "E3621",
1825 category: Category::Resource,
1826 description: "Validate the instance types for AppStream Fleet",
1827 origin: RuleOrigin::CfnLint,
1828 },
1829 RuleDefinition {
1830 id: "E3647",
1831 category: Category::Resource,
1832 description: "Validate ElastiCache cluster cache node type",
1833 origin: RuleOrigin::CfnLint,
1834 },
1835 RuleDefinition {
1836 id: "E3672",
1837 category: Category::Resource,
1838 description: "Validate the cluster node type for a DAX Cluster",
1839 origin: RuleOrigin::CfnLint,
1840 },
1841 RuleDefinition {
1842 id: "E3694",
1843 category: Category::Resource,
1844 description: "Validates RDS DB Cluster instance class",
1845 origin: RuleOrigin::CfnLint,
1846 },
1847 RuleDefinition {
1848 id: "E3640",
1849 category: Category::Resource,
1850 description: "Validate SageMaker processing instance types based on region",
1851 origin: RuleOrigin::CfnLint,
1852 },
1853 RuleDefinition {
1854 id: "E3642",
1855 category: Category::Resource,
1856 description: "Validate SageMaker hosting instance types based on region",
1857 origin: RuleOrigin::CfnLint,
1858 },
1859 RuleDefinition {
1860 id: "E3643",
1861 category: Category::Resource,
1862 description: "Validate SageMaker transform instance types based on region",
1863 origin: RuleOrigin::CfnLint,
1864 },
1865 RuleDefinition {
1866 id: "E3644",
1867 category: Category::Resource,
1868 description: "Validate SageMaker cluster instance types based on region",
1869 origin: RuleOrigin::CfnLint,
1870 },
1871 RuleDefinition {
1872 id: "E3652",
1873 category: Category::Resource,
1874 description: "Validate Elasticsearch domain cluster instance",
1875 origin: RuleOrigin::CfnLint,
1876 },
1877 RuleDefinition {
1878 id: "E3653",
1879 category: Category::Resource,
1880 description: "Validate OpenSearch domain cluster instance type",
1881 origin: RuleOrigin::CfnLint,
1882 },
1883 RuleDefinition {
1884 id: "I2003",
1885 category: Category::Structure,
1886 description: "Validate AllowedPattern is a valid regex",
1887 origin: RuleOrigin::CfnLint,
1888 },
1889 RuleDefinition {
1890 id: "W3002",
1891 category: Category::BestPractice,
1892 description: "Warn when properties are configured to only work with the package command",
1893 origin: RuleOrigin::CfnLint,
1894 },
1895 RuleDefinition {
1896 id: "W3037",
1897 category: Category::Security,
1898 description: "Check IAM Permission configuration",
1899 origin: RuleOrigin::CfnLint,
1900 },
1901 RuleDefinition {
1902 id: "W3660",
1903 category: Category::BestPractice,
1904 description: "Validate if multiple resources are modifying a Rest API definition",
1905 origin: RuleOrigin::CfnLint,
1906 },
1907 RuleDefinition {
1908 id: "W3664",
1909 category: Category::BestPractice,
1910 description: "Validate Lambda permission Principal matches SourceArn resource type",
1911 origin: RuleOrigin::CfnLint,
1912 },
1913 RuleDefinition {
1914 id: "W3671",
1915 category: Category::BestPractice,
1916 description: "Iops is ignored for certain EBS volume types",
1917 origin: RuleOrigin::CfnLint,
1918 },
1919 RuleDefinition {
1920 id: "W3688",
1921 category: Category::BestPractice,
1922 description: "When restoring DBCluster certain properties are ignored",
1923 origin: RuleOrigin::CfnLint,
1924 },
1925 RuleDefinition {
1926 id: "W3689",
1927 category: Category::BestPractice,
1928 description: "When using a source DB certain properties are ignored",
1929 origin: RuleOrigin::CfnLint,
1930 },
1931 RuleDefinition {
1932 id: "W3693",
1933 category: Category::BestPractice,
1934 description: "Validate Aurora DB cluster configuration for ignored properties",
1935 origin: RuleOrigin::CfnLint,
1936 },
1937 RuleDefinition {
1938 id: "W3694",
1939 category: Category::BestPractice,
1940 description: "SNS Subscription Endpoint should match Protocol",
1941 origin: RuleOrigin::CfnLint,
1942 },
1943 RuleDefinition {
1944 id: "E3715",
1945 category: Category::Resource,
1946 description: "VirtualName must use ephemeral device format when Ebs is absent",
1947 origin: RuleOrigin::CfnLint,
1948 },
1949 RuleDefinition {
1950 id: "W3698",
1951 category: Category::BestPractice,
1952 description: "VirtualName is ignored when Ebs is specified",
1953 origin: RuleOrigin::CfnLint,
1954 },
1955 RuleDefinition {
1956 id: "E3689",
1957 category: Category::Resource,
1958 description: "RDS DB cluster MonitoringRoleArn and a MonitoringInterval greater than 0 must be specified together",
1959 origin: RuleOrigin::CfnLint,
1960 },
1961 RuleDefinition {
1962 id: "E3717",
1963 category: Category::Resource,
1964 description: "Lambda function Timeout may exceed 900 seconds only with CapacityProviderConfig",
1965 origin: RuleOrigin::CfnLint,
1966 },
1967 RuleDefinition {
1968 id: "E3718",
1969 category: Category::Resource,
1970 description: "API Gateway TOKEN and REQUEST authorizers must keep AuthorizerResultTtlInSeconds within 0 to 3600",
1971 origin: RuleOrigin::CfnLint,
1972 },
1973 RuleDefinition {
1974 id: "E3719",
1975 category: Category::Resource,
1976 description: "RDS DB instances on non-Aurora engines must keep BackupRetentionPeriod at most 35 days",
1977 origin: RuleOrigin::CfnLint,
1978 },
1979 RuleDefinition {
1980 id: "E3723",
1981 category: Category::Resource,
1982 description: "API Gateway Stage method setting ResourcePath must start with '/' when a setting is configured",
1983 origin: RuleOrigin::CfnLint,
1984 },
1985];
1986
1987#[cfg(test)]
1988mod tests {
1989 use super::*;
1990 use std::collections::HashSet;
1991
1992 #[test]
1993 fn severity_matches_id_prefix_for_all_rules() {
1994 for rule in RULE_REGISTRY {
1995 let prefix = rule.id.chars().next().unwrap();
1996 let expected = Severity::from_prefix(prefix);
1997 assert_eq!(rule.severity(), expected, "Rule {} severity mismatch", rule.id);
1998 }
1999 }
2000
2001 #[test]
2002 fn registry_contains_no_duplicate_ids() {
2003 let mut seen = HashSet::new();
2004 for rule in RULE_REGISTRY {
2005 assert!(seen.insert(rule.id), "Duplicate rule ID: {}", rule.id);
2006 }
2007 }
2008
2009 #[test]
2010 fn lookup_rule_returns_definition_for_registered_id() {
2011 let rule = lookup_rule("E9002").expect("E9002 should exist");
2012 assert_eq!(rule.category, Category::Resource);
2013 }
2014
2015 #[test]
2016 fn lookup_rule_returns_none_for_unregistered_id() {
2017 assert!(lookup_rule("Z9999").is_none(), "unregistered rule ID Z9999 should return None");
2018 }
2019
2020 #[test]
2021 fn lookup_rule_index_covers_every_registered_rule() {
2022 for rule in RULE_REGISTRY {
2023 let looked_up =
2024 lookup_rule(rule.id).unwrap_or_else(|| panic!("registered rule {} is missing from the index", rule.id));
2025 assert_eq!(looked_up.id, rule.id);
2026 assert_eq!(looked_up.category, rule.category, "category mismatch for rule {}", rule.id);
2027 assert_eq!(looked_up.origin, rule.origin, "origin mismatch for rule {}", rule.id);
2028 }
2029 assert_eq!(
2030 RULE_REGISTRY_BY_ID.len(),
2031 RULE_REGISTRY.len(),
2032 "the lookup index must contain exactly one entry per registered rule"
2033 );
2034 }
2035
2036 #[test]
2037 fn to_rule_info_populates_all_fields_from_definition() {
2038 let rule = lookup_rule("F0001").unwrap();
2039 let info = rule.to_rule_info();
2040 assert_eq!(info.id, "F0001");
2041 assert_eq!(info.severity, Severity::Fatal);
2042 assert_eq!(info.category.as_deref(), Some(Category::Structure.as_str()));
2043 assert_eq!(info.origin, RuleOrigin::Schema);
2044 }
2045
2046 #[test]
2047 fn metadata_map_contains_entry_for_every_registered_rule() {
2048 let map = build_rule_metadata_map();
2049 assert_eq!(map.len(), RULE_REGISTRY.len());
2050 for rule in RULE_REGISTRY {
2051 assert!(map.contains_key(rule.id), "Missing rule: {}", rule.id);
2052 }
2053 }
2054
2055 #[test]
2056 fn rule_origin_as_str_returns_screaming_snake_case() {
2057 assert_eq!(RuleOrigin::Schema.as_str(), "SCHEMA");
2058 assert_eq!(RuleOrigin::CfnLint.as_str(), "CFN_LINT");
2059 assert_eq!(RuleOrigin::Engine.as_str(), "ENGINE");
2060 assert_eq!(RuleOrigin::Custom.as_str(), "CUSTOM");
2061 assert_eq!(RuleOrigin::Guard.as_str(), "GUARD");
2062 }
2063
2064 #[test]
2065 fn rule_origin_serde_round_trips() {
2066 for origin in
2067 [RuleOrigin::Schema, RuleOrigin::CfnLint, RuleOrigin::Engine, RuleOrigin::Custom, RuleOrigin::Guard]
2068 {
2069 let json = serde_json::to_string(&origin).unwrap();
2070 let deserialized: RuleOrigin = serde_json::from_str(&json).unwrap();
2071 assert_eq!(deserialized, origin, "round-trip failed for {:?}", origin);
2072 }
2073 }
2074
2075 #[test]
2076 fn rule_info_serde_round_trips() {
2077 let rule = lookup_rule("E3012").unwrap();
2078 let info = rule.to_rule_info();
2079 let json = serde_json::to_string(&info).unwrap();
2080 let deserialized: RuleInfo = serde_json::from_str(&json).unwrap();
2081 assert_eq!(deserialized.id, info.id);
2082 assert_eq!(deserialized.severity, info.severity);
2083 assert_eq!(deserialized.category, info.category);
2084 assert_eq!(deserialized.description, info.description);
2085 assert_eq!(deserialized.origin, info.origin);
2086 }
2087
2088 #[test]
2089 fn rule_ids_match_expected_format() {
2090 let id_re = regex::Regex::new(r"^[FEWID]\d{4}$").unwrap();
2091 for rule in RULE_REGISTRY {
2092 assert!(id_re.is_match(rule.id), "Rule ID '{}' does not match [FEWID]NNNN format", rule.id);
2093 }
2094 }
2095
2096 #[test]
2097 fn no_empty_descriptions() {
2098 for rule in RULE_REGISTRY {
2099 assert!(!rule.description.trim().is_empty(), "Rule {} has empty description", rule.id);
2100 }
2101 }
2102}