[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"cheat-sheet---en":3,"domain-info---en":3,"topic-info----en":3,"prev-aws-certified-cloudops-engineer-associate-deployment-provisioning-automation-machine-and-container-images-container-images-and-ecr-en":4,"lesson-aws-certified-cloudops-engineer-associate-deployment-provisioning-automation-machine-and-container-images-container-images-and-ecr-en":1008,"next-aws-certified-cloudops-engineer-associate-deployment-provisioning-automation-machine-and-container-images-container-images-and-ecr-en":1021},null,{"locked":5,"reason":3,"meta":6,"item":19},false,{"title":7,"description":8,"isFree":9,"estimatedMinutes":10,"difficulty":11,"learningObjectives":12},"AMIs and EC2 Image Builder","What an AMI actually contains, where the line between baking and bootstrapping sits, how an EC2 Image Builder pipeline turns a base image into a tested and distributed golden AMI, and the difference between deprecating, disabling, and deregistering an image.",true,26,"intermediate",[13,14,15,16,17,18],"Describe what an AMI contains and which properties are fixed at creation time","Decide what belongs baked into an image and what belongs in launch-time bootstrapping","Explain the five EC2 Image Builder resources and how a pipeline assembles them into a build","Predict what happens when the test stage of an Image Builder pipeline fails","Compare deprecating, disabling, and deregistering an AMI, and choose the right one for a given requirement","State what is required to share an AMI backed by encrypted snapshots with another account",{"id":20,"title":7,"body":21,"description":8,"difficulty":11,"estimatedMinutes":10,"extension":907,"infographics":908,"isFree":9,"learningObjectives":925,"meta":926,"navigation":9,"path":927,"quiz":928,"seo":1005,"stem":1006,"__hash__":1007},"courses/courses/aws-certified-cloudops-engineer-associate/en/domains/03-deployment-provisioning-automation/01-machine-and-container-images/01-amis-and-ec2-image-builder.md",{"type":22,"value":23,"toc":896},"minimark",[24,28,31,36,39,63,66,72,78,81,85,96,99,176,183,190,197,201,209,212,215,219,222,304,307,325,524,545,550,554,557,562,602,612,615,619,622,636,639,642,646,649,652,674,681,684,688,691,807,819,822,833,844,848,886,889,892],[25,26,27],"p",{},"An Auto Scaling group adds an instance during a traffic spike. The instance boots in about 40 seconds, then spends 8 more minutes in user data: patching the OS, pulling three agents, and compiling a dependency. By the time it passes its health check, the spike is over. Worse, the instance that launched last Tuesday installed slightly different package versions from the one that launched today, because both resolved \"latest\" against a repository that moved in between.",[25,29,30],{},"Both problems have the same fix. Do that work once, before the launch, and store the result as an image.",[32,33,35],"h2",{"id":34},"what-an-ami-actually-is","What an AMI actually is",[25,37,38],{},"An Amazon Machine Image is not a file you can download. It is a record in EC2 that points at one or more EBS snapshots and carries the metadata needed to turn those snapshots into a bootable instance:",[40,41,42,51,57],"ul",{},[43,44,45,46,50],"li",{},"The ",[47,48,49],"strong",{},"block device mapping",": which snapshot becomes the root volume, what size it is, which additional volumes attach, and whether they delete on termination.",[43,52,45,53,56],{},[47,54,55],{},"boot and platform metadata",": architecture (x86_64 or arm64), virtualization type, root device type, and boot mode.",[43,58,59,62],{},[47,60,61],{},"Launch permissions",": which accounts, organizations, or OUs may launch from it.",[25,64,65],{},"Two consequences follow from that structure, and both show up on the exam.",[25,67,68,71],{},[47,69,70],{},"An AMI is Regional."," The snapshots live in one Region, so the AMI ID is meaningful only in that Region. To launch the same image in a second Region you copy it there, and the copy gets a different AMI ID. This is why a CloudFormation template that hardcodes an AMI ID breaks the moment someone deploys it elsewhere.",[25,73,74,77],{},[47,75,76],{},"You do not pay for the AMI, you pay for its snapshots."," The AMI record itself is free. Every AMI you have ever created is quietly billing you for the snapshot storage behind it, which is why the cleanup section at the end of this lesson matters more than it sounds.",[25,79,80],{},"An AMI is also fixed at these properties. You cannot change an x86_64 AMI into an arm64 one, or convert an instance-store-backed AMI into an EBS-backed one. When you need a different combination, you build a new image.",[32,82,84],{"id":83},"bake-or-bootstrap-the-decision-that-shapes-everything-else","Bake or bootstrap: the decision that shapes everything else",[25,86,87,88,91,92,95],{},"Every piece of configuration a server needs can arrive one of two ways. ",[47,89,90],{},"Baking"," puts it in the image at build time. ",[47,93,94],{},"Bootstrapping"," applies it at launch time through user data, a Systems Manager association, or a configuration management tool.",[25,97,98],{},"Nothing forces you to pick one. The useful question is which half of your configuration goes where.",[100,101,102,117],"table",{},[103,104,105],"thead",{},[106,107,108,111,114],"tr",{},[109,110],"th",{},[109,112,113],{},"Bake into the AMI",[109,115,116],{},"Bootstrap at launch",[118,119,120,132,143,154,165],"tbody",{},[106,121,122,126,129],{},[123,124,125],"td",{},"Launch time cost",[123,127,128],{},"Zero, the work already happened",[123,130,131],{},"Paid on every single launch",[106,133,134,137,140],{},[123,135,136],{},"Consistency",[123,138,139],{},"Byte-identical across every instance",[123,141,142],{},"Depends on what upstream repositories serve that minute",[106,144,145,148,151],{},[123,146,147],{},"Changing it",[123,149,150],{},"Rebuild the image and replace instances",[123,152,153],{},"Change the script, next launch picks it up",[106,155,156,159,162],{},[123,157,158],{},"Per-environment values",[123,160,161],{},"Forces a separate image per environment",[123,163,164],{},"Handled naturally",[106,166,167,170,173],{},[123,168,169],{},"Auditability",[123,171,172],{},"One image ID answers \"what is on this box\"",[123,174,175],{},"You have to reconstruct it from logs",[25,177,178,179,182],{},"The decision rule that falls out of that table: ",[47,180,181],{},"bake what is slow and stable, bootstrap what is fast and varies."," OS patches, agents, runtimes, and compiled dependencies are slow and stable, so they belong in the image. The database endpoint, the environment name, and the instance's role in the cluster are fast and vary per deployment, so they belong in user data or Parameter Store.",[25,184,185,186,189],{},"An image built this way is usually called a ",[47,187,188],{},"golden AMI",": a hardened, patched, pre-loaded base that every workload in the organization launches from.",[25,191,192,193,196],{},"Here is the misconception this section exists to kill: ",[47,194,195],{},"\"a golden AMI means everything is in the image.\""," Push it that far and you end up rebuilding an image to change a log level, and maintaining one image per environment per application. The image is a starting line, not a finished server.",[32,198,200],{"id":199},"why-hand-built-golden-amis-stop-working","Why hand-built golden AMIs stop working",[25,202,203,204,208],{},"The first golden AMI is easy. Launch an instance, patch it, install what you need, run ",[205,206,207],"code",{},"create-image",", write the AMI ID in a wiki page.",[25,210,211],{},"The second month is where it falls apart. New CVEs land, so the image needs a rebuild, and the person who built it is on leave and never wrote down step 4. Nobody tested the new image before an Auto Scaling group started launching from it. The image exists in us-east-1 only, and the DR Region needs it too. There is no record of what changed between version 3 and version 4.",[25,213,214],{},"Those failures are not about laziness. They are what happens when a build process lives in someone's memory instead of in a file. EC2 Image Builder exists to move it into files.",[32,216,218],{"id":217},"the-five-image-builder-resources","The five Image Builder resources",[25,220,221],{},"Image Builder splits an image build into five resources, and once you see what each one owns, the service stops feeling large.",[100,223,224,237],{},[103,225,226],{},[106,227,228,231,234],{},[109,229,230],{},"Resource",[109,232,233],{},"Answers the question",[109,235,236],{},"Contains",[118,238,239,252,265,278,291],{},[106,240,241,246,249],{},[123,242,243],{},[47,244,245],{},"Image recipe",[123,247,248],{},"What goes in the image?",[123,250,251],{},"Base image, ordered list of components, instance-level settings such as the root volume size",[106,253,254,259,262],{},[123,255,256],{},[47,257,258],{},"Component",[123,260,261],{},"How is one customization performed?",[123,263,264],{},"An AWSTOE YAML document with phases and steps: install a package, harden a setting, run a test",[106,266,267,272,275],{},[123,268,269],{},[47,270,271],{},"Infrastructure configuration",[123,273,274],{},"Where is the image built?",[123,276,277],{},"Instance types, subnet, security groups, IAM instance profile, SNS topic, S3 log bucket, terminate-on-failure",[106,279,280,285,288],{},[123,281,282],{},[47,283,284],{},"Distribution settings",[123,286,287],{},"Where does the finished image go?",[123,289,290],{},"Target Regions, output AMI name, KMS key, accounts and OUs to share or copy to, launch template configuration",[106,292,293,298,301],{},[123,294,295],{},[47,296,297],{},"Image pipeline",[123,299,300],{},"When does this run?",[123,302,303],{},"A recipe plus an infrastructure configuration plus distribution settings, plus a schedule",[25,305,306],{},"Two of these deserve a closer look.",[25,308,309,312,313,316,317,320,321,324],{},[47,310,311],{},"Components"," are where your actual customization lives. A component is a plain YAML document that AWSTOE runs on the build instance, and it comes in two flavors: ",[47,314,315],{},"build components"," customize the instance before the snapshot, and ",[47,318,319],{},"test components"," validate the instance after it. AWS publishes managed components for common jobs, including ",[205,322,323],{},"update-linux"," and the STIG and CIS hardening sets, and you write your own for anything specific to you.",[326,327,332],"pre",{"className":328,"code":329,"language":330,"meta":331,"style":331},"language-yaml shiki shiki-themes material-theme-lighter github-light github-dark","name: InstallAndVerifyNginx\ndescription: Install nginx and confirm it answers on port 80\nschemaVersion: 1.0\nphases:\n  - name: build\n    steps:\n      - name: InstallNginx\n        action: ExecuteBash\n        inputs:\n          commands:\n            - dnf install -y nginx\n            - systemctl enable nginx\n  - name: validate\n    steps:\n      - name: ConfirmBinary\n        action: ExecuteBash\n        inputs:\n          commands:\n            - nginx -v\n","yaml","",[205,333,334,351,362,374,383,397,405,418,429,437,445,454,462,474,481,493,502,509,516],{"__ignoreMap":331},[335,336,339,343,347],"span",{"class":337,"line":338},"line",1,[335,340,342],{"class":341},"sQzsp","name",[335,344,346],{"class":345},"sP7_E",":",[335,348,350],{"class":349},"s_sjI"," InstallAndVerifyNginx\n",[335,352,354,357,359],{"class":337,"line":353},2,[335,355,356],{"class":341},"description",[335,358,346],{"class":345},[335,360,361],{"class":349}," Install nginx and confirm it answers on port 80\n",[335,363,365,368,370],{"class":337,"line":364},3,[335,366,367],{"class":341},"schemaVersion",[335,369,346],{"class":345},[335,371,373],{"class":372},"srdBf"," 1.0\n",[335,375,377,380],{"class":337,"line":376},4,[335,378,379],{"class":341},"phases",[335,381,382],{"class":345},":\n",[335,384,386,389,392,394],{"class":337,"line":385},5,[335,387,388],{"class":345},"  -",[335,390,391],{"class":341}," name",[335,393,346],{"class":345},[335,395,396],{"class":349}," build\n",[335,398,400,403],{"class":337,"line":399},6,[335,401,402],{"class":341},"    steps",[335,404,382],{"class":345},[335,406,408,411,413,415],{"class":337,"line":407},7,[335,409,410],{"class":345},"      -",[335,412,391],{"class":341},[335,414,346],{"class":345},[335,416,417],{"class":349}," InstallNginx\n",[335,419,421,424,426],{"class":337,"line":420},8,[335,422,423],{"class":341},"        action",[335,425,346],{"class":345},[335,427,428],{"class":349}," ExecuteBash\n",[335,430,432,435],{"class":337,"line":431},9,[335,433,434],{"class":341},"        inputs",[335,436,382],{"class":345},[335,438,440,443],{"class":337,"line":439},10,[335,441,442],{"class":341},"          commands",[335,444,382],{"class":345},[335,446,448,451],{"class":337,"line":447},11,[335,449,450],{"class":345},"            -",[335,452,453],{"class":349}," dnf install -y nginx\n",[335,455,457,459],{"class":337,"line":456},12,[335,458,450],{"class":345},[335,460,461],{"class":349}," systemctl enable nginx\n",[335,463,465,467,469,471],{"class":337,"line":464},13,[335,466,388],{"class":345},[335,468,391],{"class":341},[335,470,346],{"class":345},[335,472,473],{"class":349}," validate\n",[335,475,477,479],{"class":337,"line":476},14,[335,478,402],{"class":341},[335,480,382],{"class":345},[335,482,484,486,488,490],{"class":337,"line":483},15,[335,485,410],{"class":345},[335,487,391],{"class":341},[335,489,346],{"class":345},[335,491,492],{"class":349}," ConfirmBinary\n",[335,494,496,498,500],{"class":337,"line":495},16,[335,497,423],{"class":341},[335,499,346],{"class":345},[335,501,428],{"class":349},[335,503,505,507],{"class":337,"line":504},17,[335,506,434],{"class":341},[335,508,382],{"class":345},[335,510,512,514],{"class":337,"line":511},18,[335,513,442],{"class":341},[335,515,382],{"class":345},[335,517,519,521],{"class":337,"line":518},19,[335,520,450],{"class":345},[335,522,523],{"class":349}," nginx -v\n",[25,525,526,527,530,531,534,535,538,539,541,542,544],{},"The phase names are not decoration. Image Builder decides when a component runs by which phases it defines: a component runs in the build stage if it defines ",[205,528,529],{},"build"," or ",[205,532,533],{},"validate",", and it runs in the test stage if it defines ",[205,536,537],{},"test"," and nothing else. A component cannot straddle the two, and you cannot chain a value produced in ",[205,540,529],{}," into a ",[205,543,537],{}," step, because those stages run on different instances.",[25,546,547,549],{},[47,548,271],{}," is the resource people forget until a build fails. The build instance runs in your VPC, which means it needs a subnet with a route to reach package repositories, a security group that permits that traffic, and an instance profile with the Image Builder permissions. It is also where the troubleshooting switch lives: by default the build instance terminates when a build fails, and turning that off keeps the instance alive so you can log in and read the AWSTOE logs.",[32,551,553],{"id":552},"what-one-pipeline-run-actually-does","What one pipeline run actually does",[25,555,556],{},"Walk one build end to end, because the ordering explains several exam answers.",[558,559],"infographic",{"alt":560,"slug":561},"A pipeline run flows from the image recipe and infrastructure configuration through the build stage to a snapshot, then through the test stage to a pass or fail fork, where only a passing image reaches the distribution settings and the target Regions.","amis-and-ec2-image-builder-pipeline-flow",[563,564,565,577,583,596],"ol",{},[43,566,567,570,571,573,574,576],{},[47,568,569],{},"Build stage."," Image Builder launches an EC2 instance from the base image, inside the subnet from your infrastructure configuration. AWSTOE runs the ",[205,572,529],{}," phase of every build component in recipe order, then the ",[205,575,533],{}," phase of each. If any step fails, the build stops here.",[43,578,579,582],{},[47,580,581],{},"Snapshot."," With the customizations applied, Image Builder stops the instance and takes a snapshot, producing the candidate image.",[43,584,585,588,589,592,593,595],{},[47,586,587],{},"Test stage."," For an AMI workflow, Image Builder launches a ",[47,590,591],{},"new"," instance from that candidate image and runs the ",[205,594,537],{}," phase of every component in the recipe. This is a real launch of the real artifact, not a re-check of the build instance, which is why it catches a first-boot service that fails to start.",[43,597,598,601],{},[47,599,600],{},"Distribution."," Only if every test passed does Image Builder copy the AMI into each Region in your distribution settings, apply the configured KMS key, set launch permissions, and optionally update a launch template to point at the new AMI ID.",[25,603,604,605,530,608,611],{},"That last option is worth pausing on. Distribution can write the new AMI ID into a specific version of an EC2 launch template, so an Auto Scaling group pointed at that template's ",[205,606,607],{},"$Latest",[205,609,610],{},"$Default"," version picks up the new image without anyone editing anything.",[25,613,614],{},"The service itself is free. You pay for the EC2 build and test instances while they run, the EBS snapshots the images occupy, S3 log storage, Amazon Inspector if you turn on vulnerability scanning during the build, and ECR storage for container image outputs.",[32,616,618],{"id":617},"scheduling-build-on-a-clock-or-build-on-a-change","Scheduling: build on a clock, or build on a change",[25,620,621],{},"A pipeline can run on demand, on a cron schedule, or in response to an EventBridge rule. The schedule has a second setting that carries most of the value, and it is a common exam target.",[40,623,624,630],{},[43,625,626,629],{},[47,627,628],{},"Run at the scheduled time, always."," Every scheduled slot produces a build, whether or not anything upstream changed. You get a fresh image on a fixed cadence and pay for a build each time.",[43,631,632,635],{},[47,633,634],{},"Run at the scheduled time only if dependency updates are available."," Image Builder checks whether the base image or any component has a newer semantic version, and skips the build if nothing moved.",[25,637,638],{},"The second option only works if your recipe uses semantic versioning for the base image and components, which in the console means choosing \"use latest available OS version\" and \"use latest version available\" rather than pinning an exact version string. Pin everything to fixed versions and Image Builder has nothing to compare, so it either rebuilds every time or never detects an update, depending on how the recipe is written.",[25,640,641],{},"A weekly pipeline set to build only on dependency updates is the shape most teams want: no image churn during a quiet week, and a fresh patched image the moment AWS publishes a new base AMI.",[32,643,645],{"id":644},"distributing-and-sharing-the-result","Distributing and sharing the result",[25,647,648],{},"Distribution settings handle the cross-Region and cross-account work that people otherwise do by hand.",[25,650,651],{},"Within your own account, distribution copies the AMI into each target Region. Across accounts you have two different options, and the difference is about ownership:",[40,653,654,664],{},[43,655,656,658,659,663],{},[47,657,61],{}," let another account launch from ",[660,661,662],"em",{},"your"," AMI. You still own the image, you still pay for the snapshots, and the other account pays only for the instances it launches. Revoke the permission and their future launches stop.",[43,665,666,669,670,673],{},[47,667,668],{},"Target accounts and OUs"," create a ",[660,671,672],{},"copy"," of the AMI in each target account. That account owns its copy and pays for its snapshots, and the copy survives anything you do to the original.",[25,675,676,677,680],{},"Encryption adds one requirement that trips up more people than any other part of AMI sharing. An AMI whose snapshots are encrypted with the default AWS managed key ",[47,678,679],{},"cannot be shared at all",", because you cannot edit that key's policy. Sharing an encrypted AMI means encrypting its snapshots with a customer managed KMS key and granting the target accounts permission to use that key. The usual fix is a copy: copy the AMI to itself, specifying your own KMS key, then share the copy.",[25,682,683],{},"Two smaller behaviors worth knowing. You do not have to share the underlying snapshots separately, because EC2 grants launch access to them on your behalf. And your user-defined tags do not travel with a shared AMI, so the receiving account sees an untagged image.",[32,685,687],{"id":686},"retiring-an-image-three-verbs-that-are-not-synonyms","Retiring an image: three verbs that are not synonyms",[25,689,690],{},"An organization that builds a weekly golden AMI has 52 images a year, per Region, per OS. Cleaning them up is a real operational task, and AWS gives you three distinct actions that learners routinely blur together.",[100,692,693,708],{},[103,694,695],{},[106,696,697,699,702,705],{},[109,698],{},[109,700,701],{},"Deprecate",[109,703,704],{},"Disable",[109,706,707],{},"Deregister",[118,709,710,724,738,755,768,782,796],{},[106,711,712,715,718,721],{},[123,713,714],{},"Can new instances launch from it?",[123,716,717],{},"Yes, if the launcher knows the AMI ID",[123,719,720],{},"No, launches fail",[123,722,723],{},"No",[106,725,726,729,732,735],{},[123,727,728],{},"Auto Scaling groups and launch templates",[123,730,731],{},"Keep working",[123,733,734],{},"Keep referencing it, and their launches fail",[123,736,737],{},"Their launches fail",[106,739,740,743,746,752],{},[123,741,742],{},"Visible in listings",[123,744,745],{},"Hidden from users, visible to the owner",[123,747,748,749],{},"Hidden by default, visible only to the owner with ",[205,750,751],{},"--include-disabled",[123,753,754],{},"Gone",[106,756,757,760,763,766],{},[123,758,759],{},"Sharing",[123,761,762],{},"Unaffected",[123,764,765],{},"All launch permissions removed, AMI becomes private",[123,767,754],{},[106,769,770,773,776,779],{},[123,771,772],{},"Reversible",[123,774,775],{},"Yes, cancel the deprecation date",[123,777,778],{},"Yes, re-enable, but sharing is not restored",[123,780,781],{},"No, except from the Recycle Bin if a retention rule matched",[106,783,784,787,790,793],{},[123,785,786],{},"Snapshots still billed",[123,788,789],{},"Yes",[123,791,792],{},"Yes, and they cannot be deleted while the AMI is disabled",[123,794,795],{},"Only if you left them behind",[106,797,798,801,803,805],{},[123,799,800],{},"Running instances",[123,802,762],{},[123,804,762],{},[123,806,762],{},[25,808,809,810,812,813,815,816,818],{},"Read that table as an escalation ladder. ",[47,811,701],{}," is a signal: stop choosing this image, but nothing breaks. ",[47,814,704],{}," is a stop: launches fail, and you can undo it. ",[47,817,707],{}," is deletion.",[25,820,821],{},"The numbers AWS asks about directly: you can set a deprecation date up to 10 years out for a private AMI, public AMIs default to deprecation 2 years after creation, and the only way to move a public AMI's deprecation later is to make it private by sharing it with specific accounts.",[25,823,824,825,828,829,832],{},"Then there is the cost trap. Deregistering an AMI does ",[47,826,827],{},"not"," delete its backing snapshots by default. A team that deregisters 40 stale AMIs and expects the storage bill to drop is in for a surprise, because the snapshots are still there. Pass ",[205,830,831],{},"--delete-associated-snapshots"," on the deregister call, or clean them up afterwards. A snapshot referenced by more than one AMI is kept regardless.",[25,834,835,836,839,840,843],{},"You do not have to do any of this by hand. ",[47,837,838],{},"Image Builder lifecycle policies"," apply deprecate, disable, and delete actions to the images a pipeline produced, using age-based and count-based rules with exclusion rules to protect images you must keep. ",[47,841,842],{},"Amazon Data Lifecycle Manager"," covers the same ground for EBS-backed AMIs generally, including AMIs you did not build with Image Builder.",[32,845,847],{"id":846},"exam-tips","Exam tips",[40,849,850,865,868,871,874,877,880,883],{},[43,851,852,853,856,857,860,861,864],{},"\"Stop launches now, and let us undo it later\" is ",[47,854,855],{},"disable",". \"Mark as out of date but keep it working\" is ",[47,858,859],{},"deprecate",". \"Delete it\" is ",[47,862,863],{},"deregister",". Options that mix the effects are the distractors.",[43,866,867],{},"If a stem says an Auto Scaling group is still launching from an old image after the team deprecated it, that is the expected behavior, not a bug. Deprecation hides an AMI from listings; it never blocks a launch by ID.",[43,869,870],{},"Deregistering does not stop the snapshot bill on its own. Any answer that treats deregistration as a complete cleanup is wrong.",[43,872,873],{},"Encrypted AMI sharing needs a customer managed KMS key plus a grant to the target account. If the stem mentions the default AWS managed key, the sharing cannot work, and the answer involves copying with your own key.",[43,875,876],{},"An Image Builder pipeline that fails its tests distributes nothing. If a question asks why a new AMI never appeared in the DR Region, a failed test component is a prime suspect, alongside the Region simply not being in the distribution settings.",[43,878,879],{},"\"Build only when the base image is patched\" is the dependency-update schedule setting, and it depends on semantic versioning in the recipe.",[43,881,882],{},"Image Builder itself is free. Charges come from the build and test instances, snapshots, logs, Inspector, and ECR.",[43,884,885],{},"Watch for the bake-versus-bootstrap split in scenario stems. Long launch times point at baking; per-environment configuration points at bootstrapping.",[25,887,888],{},"The idea to carry forward is that an image is a build artifact with a version, a test suite, and an expiry, not a server someone once configured. That framing is what makes the whole domain coherent: the image is built from a file, tested before it ships, distributed by policy, and retired on schedule.",[25,890,891],{},"Everything in this lesson assumed the unit you ship is a machine. The next lesson swaps that assumption. When the machine already exists and only the application changes, you ship a container image instead, and almost every idea here reappears in a smaller and faster form.",[893,894,895],"style",{},"html pre.shiki code .sQzsp, html code.shiki .sQzsp{--shiki-light:#E53935;--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":331,"searchDepth":364,"depth":364,"links":897},[898,899,900,901,902,903,904,905,906],{"id":34,"depth":353,"text":35},{"id":83,"depth":353,"text":84},{"id":199,"depth":353,"text":200},{"id":217,"depth":353,"text":218},{"id":552,"depth":353,"text":553},{"id":617,"depth":353,"text":618},{"id":644,"depth":353,"text":645},{"id":686,"depth":353,"text":687},{"id":846,"depth":353,"text":847},"md",[909],{"slug":561,"concept":910,"style":911,"aspectRatio":912,"labels":913},"A left-to-right flow of one EC2 Image Builder pipeline run. Three configuration resources sit above the flow and drop into the stage they feed: the image recipe into the build stage, the infrastructure configuration into the build stage, and the distribution settings into the distribution step. The flow itself runs build stage, snapshot, test stage, then a decision fork where a failed test dead-ends and a passed test continues into distribution across Regions and accounts. The fork is the emphasis of the image: the test stage is a gate, not a report.","diagram","16:9",[914,915,916,917,918,919,920,921,922,923,924],"EC2 Image Builder pipeline","Image recipe: base image, build components, instance settings","Infrastructure configuration: instance type, subnet, security group, instance profile, logs","Distribution settings: target Regions, accounts and OUs, KMS key, launch template","Build stage: launch build instance, run build and validate phases","Snapshot","Test stage: launch a fresh instance from the snapshot, run test phases","Tests fail: build instance terminates, nothing is distributed","Tests pass: distribution runs","Output AMI in every target Region and account","The test stage is a gate, not a report: an image that fails its tests never reaches a Region.",[13,14,15,16,17,18],{},"/courses/aws-certified-cloudops-engineer-associate/en/domains/03-deployment-provisioning-automation/01-machine-and-container-images/01-amis-and-ec2-image-builder",{"passingScore":929,"questions":930},70,[931,940,950,958,966,974,982,991,999],{"question":932,"type":933,"options":934,"correctAnswer":937,"explanation":939},"An Auto Scaling group is still launching instances from an AMI that a security review just rejected. The team needs launches from that AMI to stop right now, and they want to be able to reverse the change if the rejection turns out to be a false positive. What should they do?","single",[935,936,937,938],"Deprecate the AMI","Deregister the AMI","Disable the AMI","Remove the AMI's launch permissions","Disabling puts the AMI into the disabled state so any launch that references it fails, and the AMI can be re-enabled later. Deprecating is the tempting wrong answer because it sounds final, but a deprecated AMI is only hidden from listings and Auto Scaling groups keep launching from it by ID. Deregistering would stop the launches too, but it is permanent.",{"question":941,"type":942,"options":943,"correctAnswers":948,"explanation":949},"Which statements about disabling an AMI are correct? (Choose 2.)","multiple",[944,945,946,947],"All launch permissions are removed and the AMI becomes private","Instances already running from the AMI are stopped","You stop paying for the AMI's EBS snapshots","The AMI can be re-enabled, but accounts it was shared with do not regain access automatically",[944,947],"Disabling strips sharing as a side effect, which is the part people miss: re-enabling brings the AMI back but you have to share it again. Running instances are untouched by any AMI lifecycle action, and the snapshots stay in place and stay billed because the AMI still exists.",{"question":951,"type":933,"options":952,"correctAnswer":953,"explanation":957},"By default, what deprecation date does a public AMI receive?",[953,954,955,956],"Two years from the AMI creation date","Ten years from the AMI creation date","No deprecation date is set by default","Ninety days after the AMI was last used to launch an instance","AWS sets a 2-year default deprecation date on public AMIs so stale public images fall out of listings on their own. Ten years is the upper limit you can set on a private AMI, not a default, and the only way to push a public AMI's deprecation later is to make it private by sharing it with specific accounts instead.",{"question":959,"type":933,"options":960,"correctAnswer":964,"explanation":965},"An EC2 Image Builder pipeline builds successfully, but a test component fails during the test stage. What happens?",[961,962,963,964],"The image is distributed with a warning recorded in the pipeline history","The image is distributed only to the Region where it was built","The pipeline retries the build stage automatically","The image is not distributed to any target","Distribution only runs when every configured test succeeds, which is what makes the test stage a gate rather than a report. That gate is the whole reason to define test components: a golden AMI that boots but fails its own health check should never reach a Region.",{"question":967,"type":933,"options":968,"correctAnswer":970,"explanation":973},"A pipeline is scheduled daily with the option to run only when dependency updates are available, but it rebuilds every single day even when nothing changed. What is the most likely cause?",[969,970,971,972],"The pipeline schedule uses UTC instead of the local time zone","The base image or the components are not pinned with semantic versioning","The infrastructure configuration terminates the build instance on failure","The distribution settings target more than one Region","Image Builder detects dependency updates by comparing semantic versions of the base image and the components, so recipes that do not use semantic versioning give it nothing to compare and every scheduled run becomes a full build. Time zones, failure handling, and distribution targets have no effect on whether a build is skipped.",{"question":975,"type":933,"options":976,"correctAnswer":979,"explanation":981},"An operations team deregisters 40 old AMIs to reduce their EBS bill, and the bill barely moves. Why?",[977,978,979,980],"Deregistered AMIs move to the Recycle Bin and keep billing until the retention period expires","AMI deregistration is asynchronous and takes up to 30 days to take effect","Deregistering an AMI does not delete its backing snapshots unless you ask for that explicitly","Snapshot storage is billed to the account that launched instances from the AMI","The AMI is a pointer plus metadata; the storage cost lives in the snapshots behind it, and those survive deregistration unless you pass the delete-associated-snapshots option or clean them up afterwards. A snapshot shared by more than one AMI is kept even when you do ask for deletion.",{"question":983,"type":942,"options":984,"correctAnswers":989,"explanation":990},"You need to share an AMI backed by encrypted snapshots with another AWS account. Which two conditions must be met? (Choose 2.)",[985,986,987,988],"The snapshots must be encrypted with a customer managed KMS key, not the default AWS managed key","The snapshots must be shared explicitly in addition to the AMI","The target account must be granted permission to use the KMS key","The AMI's user-defined tags must be copied to the target account first",[985,987],"An AMI encrypted with the default AWS managed key can never be shared, because that key policy cannot be edited, so the fix is always to re-encrypt with a customer managed key during a copy. Sharing the snapshots separately is not required since EC2 grants launch access to them, and user-defined tags simply do not travel with a shared AMI.",{"question":992,"type":933,"options":993,"correctAnswer":995,"explanation":998},"A deployment takes 9 minutes because every new instance patches the OS and installs three agents from user data at launch. The team wants scale-out to complete in under 2 minutes while still allowing a per-environment database endpoint to be set at boot. What should they do?",[994,995,996,997],"Move everything, including the database endpoint, into a golden AMI built by a pipeline","Bake the patches and agents into a golden AMI, and keep the endpoint in user data","Keep user data as is and increase the Auto Scaling group's health check grace period","Replace user data with a Systems Manager State Manager association that runs after launch","Baking moves the slow and stable work to build time, where the wait costs nothing, and bootstrapping keeps the per-environment values out of the image so one AMI serves every environment. Baking the endpoint too would force a separate image per environment, and a longer grace period hides the delay instead of removing it.",{"question":1000,"type":933,"options":1001,"correctAnswer":1003,"explanation":1004},"True or False: an AMI created in eu-west-1 can be used to launch an instance in eu-west-2 by referencing its AMI ID.",[1002,1003],"True","False","An AMI is a Regional resource, and an AMI ID has no meaning outside the Region that holds it. To launch in a second Region you copy the AMI there and get a new AMI ID, which is exactly what Image Builder distribution settings automate for every target Region on every build.",{"title":7,"description":8},"courses/aws-certified-cloudops-engineer-associate/en/domains/03-deployment-provisioning-automation/01-machine-and-container-images/01-amis-and-ec2-image-builder","oLoaIhpUCXgDLIiKivoCn8G9shg_6f-BcZB1K2vRpDw",{"locked":9,"reason":1009,"meta":1010,"item":3},"paywall",{"title":1011,"description":1012,"isFree":5,"estimatedMinutes":1013,"difficulty":11,"learningObjectives":1014},"Container Images and Amazon ECR","How container images are layered and addressed by digest, how ECR authentication and its three permission layers work, and how tag immutability, basic and enhanced scanning, lifecycle policies, replication, and pull through cache keep a registry usable in production.",25,[1015,1016,1017,1018,1019,1020],"Explain how container image layers, manifests, tags, and digests relate to each other","Authenticate Docker to an ECR private registry and describe how long the credential lasts","Distinguish IAM identity policies, repository policies, and registry policies in ECR","Compare ECR basic scanning with enhanced scanning and pick the right one for a requirement","Write an ECR lifecycle policy and predict which images it will expire","Choose between registry replication and a pull through cache rule for a given goal",{"locked":5,"reason":3,"meta":1022,"item":1034},{"title":1023,"description":1024,"isFree":9,"estimatedMinutes":1025,"difficulty":11,"learningObjectives":1026},"CloudFormation Fundamentals","How a CloudFormation template describes infrastructure: the template sections, parameters with real guardrails, intrinsic functions, the dependency graph CloudFormation builds for you, and the resource attributes that decide what survives a delete.",30,[1027,1028,1029,1030,1031,1032,1033],"Distinguish a template, a stack, a logical ID, and a physical ID","Identify the template sections and explain which one is required","Choose the right parameter type and constraints to catch bad input before any resource is created","Select the correct intrinsic function for a given reference, and explain why Ref and Fn::GetAtt are not interchangeable","Predict the order in which CloudFormation creates resources, and know when DependsOn is required","Compare Fn::ImportValue, Fn::GetStackOutput, and nested stack outputs for sharing values between stacks","Keep credentials out of a template using dynamic references, and state what NoEcho does not protect",{"id":1035,"title":1023,"body":1036,"description":1024,"difficulty":11,"estimatedMinutes":1025,"extension":907,"infographics":3084,"isFree":9,"learningObjectives":3099,"meta":3100,"navigation":9,"path":3101,"quiz":3102,"seo":3173,"stem":3174,"__hash__":3175},"courses/courses/aws-certified-cloudops-engineer-associate/en/domains/03-deployment-provisioning-automation/02-infrastructure-as-code/01-cloudformation-fundamentals.md",{"type":22,"value":1037,"toc":3072},[1038,1041,1044,1048,1051,1058,1064,1071,1131,1145,1148,1155,1159,1162,1299,1305,1311,1315,1318,1442,1445,1482,1496,1509,1524,1551,1555,1558,1566,1602,1620,1628,1658,1674,1686,1727,1760,1763,1903,1909,1913,1916,2057,2072,2075,2079,2082,2129,2136,2140,2143,2148,2278,2283,2450,2463,2466,2470,2473,2533,2547,2550,2589,2592,2696,2705,2709,2715,2770,2773,2793,2796,2807,2811,2819,2827,2882,2903,2925,2973,2980,2989,2991,3063,3066,3069],[25,1039,1040],{},"A team built staging by hand: a VPC, two subnets, a security group, a load balancer, an Auto Scaling group, and an RDS instance. It took an afternoon of clicking. Now production needs the same thing, in a second Region, and nobody can reconstruct the exact security group rules from memory. Somebody opens the console side by side with staging and starts copying.",[25,1042,1043],{},"That is the problem CloudFormation removes. You describe the infrastructure once, in a file, and AWS builds it. Build it again next week in another account and you get the same result, because the description is the source of truth instead of somebody's memory.",[32,1045,1047],{"id":1046},"template-stack-and-the-two-kinds-of-id","Template, stack, and the two kinds of ID",[25,1049,1050],{},"Three words carry most of the meaning, and mixing them up makes every later concept harder.",[25,1052,1053,1054,1057],{},"A ",[47,1055,1056],{},"template"," is the file. JSON or YAML, stored in Git, reviewed like code, doing nothing on its own.",[25,1059,1053,1060,1063],{},[47,1061,1062],{},"stack"," is what you get when CloudFormation processes that template: a live collection of AWS resources managed as one unit. Update the stack and CloudFormation works out which resources need to change. Delete the stack and, by default, everything in it goes.",[25,1065,1066,1067,1070],{},"Inside the template, every resource has a ",[47,1068,1069],{},"logical ID",", the name you choose:",[326,1072,1074],{"className":328,"code":1073,"language":330,"meta":331,"style":331},"Resources:\n  WebSecurityGroup:\n    Type: AWS::EC2::SecurityGroup\n    Properties:\n      GroupDescription: Allow HTTPS from the load balancer\n      VpcId: !Ref AppVpc\n",[205,1075,1076,1083,1090,1100,1107,1117],{"__ignoreMap":331},[335,1077,1078,1081],{"class":337,"line":338},[335,1079,1080],{"class":341},"Resources",[335,1082,382],{"class":345},[335,1084,1085,1088],{"class":337,"line":353},[335,1086,1087],{"class":341},"  WebSecurityGroup",[335,1089,382],{"class":345},[335,1091,1092,1095,1097],{"class":337,"line":364},[335,1093,1094],{"class":341},"    Type",[335,1096,346],{"class":345},[335,1098,1099],{"class":349}," AWS::EC2::SecurityGroup\n",[335,1101,1102,1105],{"class":337,"line":376},[335,1103,1104],{"class":341},"    Properties",[335,1106,382],{"class":345},[335,1108,1109,1112,1114],{"class":337,"line":385},[335,1110,1111],{"class":341},"      GroupDescription",[335,1113,346],{"class":345},[335,1115,1116],{"class":349}," Allow HTTPS from the load balancer\n",[335,1118,1119,1122,1124,1128],{"class":337,"line":399},[335,1120,1121],{"class":341},"      VpcId",[335,1123,346],{"class":345},[335,1125,1127],{"class":1126},"sbsja"," !Ref",[335,1129,1130],{"class":349}," AppVpc\n",[25,1132,1133,1136,1137,1140,1141,1144],{},[205,1134,1135],{},"WebSecurityGroup"," is the logical ID. It exists only inside this template and this stack. When CloudFormation creates the group, AWS assigns it a ",[47,1138,1139],{},"physical ID"," such as ",[205,1142,1143],{},"sg-0a1b2c3d4e5f",". The logical ID is how you refer to the resource while authoring; the physical ID is what actually exists in the account.",[25,1146,1147],{},"That distinction becomes load-bearing later. Rename a logical ID and CloudFormation does not see a rename, it sees one resource deleted and a different resource created. The physical ID is also what changes when a resource is replaced during an update, which is the difference between a harmless update and an outage.",[25,1149,1150,1151,1154],{},"One more framing that pays off throughout this topic: a template is ",[47,1152,1153],{},"declarative",". You state the end state, not the steps. You never write \"create the VPC, wait, then create the subnet.\" You state that the subnet belongs to the VPC, and CloudFormation figures out the order.",[32,1156,1158],{"id":1157},"the-template-sections","The template sections",[25,1160,1161],{},"A template has ten possible top-level sections. Exactly one is required.",[100,1163,1164,1174],{},[103,1165,1166],{},[106,1167,1168,1171],{},[109,1169,1170],{},"Section",[109,1172,1173],{},"Purpose",[118,1175,1176,1195,1205,1219,1229,1239,1256,1266,1276,1289],{},[106,1177,1178,1182],{},[123,1179,1180],{},[205,1181,1080],{},[123,1183,1184,1187,1188,1191,1192],{},[47,1185,1186],{},"Required."," The AWS resources to create, each with a logical ID, a ",[205,1189,1190],{},"Type",", and ",[205,1193,1194],{},"Properties",[106,1196,1197,1202],{},[123,1198,1199],{},[205,1200,1201],{},"Parameters",[123,1203,1204],{},"Values supplied at create or update time, so one template serves many environments",[106,1206,1207,1212],{},[123,1208,1209],{},[205,1210,1211],{},"Mappings",[123,1213,1214,1215,1218],{},"A static lookup table read with ",[205,1216,1217],{},"Fn::FindInMap",", typically keyed by Region or environment",[106,1220,1221,1226],{},[123,1222,1223],{},[205,1224,1225],{},"Conditions",[123,1227,1228],{},"Named boolean expressions that decide whether a resource or property is included",[106,1230,1231,1236],{},[123,1232,1233],{},[205,1234,1235],{},"Outputs",[123,1237,1238],{},"Values returned after the stack is built, optionally exported for other stacks",[106,1240,1241,1246],{},[123,1242,1243],{},[205,1244,1245],{},"Transform",[123,1247,1248,1249,1252,1253],{},"Macros to run over the template, including ",[205,1250,1251],{},"AWS::Serverless"," (SAM) and ",[205,1254,1255],{},"AWS::LanguageExtensions",[106,1257,1258,1263],{},[123,1259,1260],{},[205,1261,1262],{},"Metadata",[123,1264,1265],{},"Arbitrary extra data about the template, including console UI hints",[106,1267,1268,1273],{},[123,1269,1270],{},[205,1271,1272],{},"Rules",[123,1274,1275],{},"Validates a parameter or a combination of parameters before provisioning",[106,1277,1278,1283],{},[123,1279,1280],{},[205,1281,1282],{},"AWSTemplateFormatVersion",[123,1284,1285,1286],{},"The template format version, ",[205,1287,1288],{},"2010-09-09",[106,1290,1291,1296],{},[123,1292,1293],{},[205,1294,1295],{},"Description",[123,1297,1298],{},"A text description of the template",[25,1300,1301,1302,1304],{},"A template that only declares ",[205,1303,1080],{}," is valid. Everything else earns its place by making the template reusable, safer, or easier to read.",[25,1306,1307,1308,1310],{},"Section order in the file does not matter to CloudFormation, and neither does the order of resources inside ",[205,1309,1080],{},". That surprises people who expect a script.",[32,1312,1314],{"id":1313},"parameters-input-with-guardrails","Parameters: input with guardrails",[25,1316,1317],{},"A hardcoded template is a template you can only use once. Parameters are how one file serves dev, staging, and production.",[326,1319,1321],{"className":328,"code":1320,"language":330,"meta":331,"style":331},"Parameters:\n  EnvironmentName:\n    Type: String\n    AllowedValues: [dev, staging, prod]\n    Description: Which environment this stack represents\n\n  AppVpcId:\n    Type: AWS::EC2::VPC::Id\n    Description: The VPC to deploy into\n\n  LatestAmiId:\n    Type: AWS::SSM::Parameter::Value\u003CAWS::EC2::Image::Id>\n    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2\n",[205,1322,1323,1329,1336,1345,1372,1382,1387,1394,1403,1412,1416,1423,1432],{"__ignoreMap":331},[335,1324,1325,1327],{"class":337,"line":338},[335,1326,1201],{"class":341},[335,1328,382],{"class":345},[335,1330,1331,1334],{"class":337,"line":353},[335,1332,1333],{"class":341},"  EnvironmentName",[335,1335,382],{"class":345},[335,1337,1338,1340,1342],{"class":337,"line":364},[335,1339,1094],{"class":341},[335,1341,346],{"class":345},[335,1343,1344],{"class":349}," String\n",[335,1346,1347,1350,1352,1355,1358,1361,1364,1366,1369],{"class":337,"line":376},[335,1348,1349],{"class":341},"    AllowedValues",[335,1351,346],{"class":345},[335,1353,1354],{"class":345}," [",[335,1356,1357],{"class":349},"dev",[335,1359,1360],{"class":345},",",[335,1362,1363],{"class":349}," staging",[335,1365,1360],{"class":345},[335,1367,1368],{"class":349}," prod",[335,1370,1371],{"class":345},"]\n",[335,1373,1374,1377,1379],{"class":337,"line":385},[335,1375,1376],{"class":341},"    Description",[335,1378,346],{"class":345},[335,1380,1381],{"class":349}," Which environment this stack represents\n",[335,1383,1384],{"class":337,"line":399},[335,1385,1386],{"emptyLinePlaceholder":9},"\n",[335,1388,1389,1392],{"class":337,"line":407},[335,1390,1391],{"class":341},"  AppVpcId",[335,1393,382],{"class":345},[335,1395,1396,1398,1400],{"class":337,"line":420},[335,1397,1094],{"class":341},[335,1399,346],{"class":345},[335,1401,1402],{"class":349}," AWS::EC2::VPC::Id\n",[335,1404,1405,1407,1409],{"class":337,"line":431},[335,1406,1376],{"class":341},[335,1408,346],{"class":345},[335,1410,1411],{"class":349}," The VPC to deploy into\n",[335,1413,1414],{"class":337,"line":439},[335,1415,1386],{"emptyLinePlaceholder":9},[335,1417,1418,1421],{"class":337,"line":447},[335,1419,1420],{"class":341},"  LatestAmiId",[335,1422,382],{"class":345},[335,1424,1425,1427,1429],{"class":337,"line":456},[335,1426,1094],{"class":341},[335,1428,346],{"class":345},[335,1430,1431],{"class":349}," AWS::SSM::Parameter::Value\u003CAWS::EC2::Image::Id>\n",[335,1433,1434,1437,1439],{"class":337,"line":464},[335,1435,1436],{"class":341},"    Default",[335,1438,346],{"class":345},[335,1440,1441],{"class":349}," /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2\n",[25,1443,1444],{},"Three different parameter types are doing three different jobs there, and the difference matters more than the syntax suggests.",[25,1446,1447,1450,1451,1454,1455,1458,1459,1461,1462,1461,1465,1461,1468,1461,1471,1461,1474,1477,1478,1481],{},[205,1448,1449],{},"EnvironmentName"," is a plain ",[47,1452,1453],{},"String"," locked down by ",[205,1456,1457],{},"AllowedValues",". Constraints (",[205,1460,1457],{},", ",[205,1463,1464],{},"AllowedPattern",[205,1466,1467],{},"MinLength",[205,1469,1470],{},"MaxLength",[205,1472,1473],{},"MinValue",[205,1475,1476],{},"MaxValue",") are checked before any resource is touched, so a typo fails in seconds instead of failing halfway through a 12-minute deployment. Add ",[205,1479,1480],{},"ConstraintDescription"," and the error message says \"must be dev, staging, or prod\" instead of dumping a regular expression at the user.",[25,1483,1484,1487,1488,1491,1492,1495],{},[205,1485,1486],{},"AppVpcId"," uses an ",[47,1489,1490],{},"AWS-specific parameter type",". CloudFormation validates that the VPC actually exists in this account and Region, and the console shows a dropdown instead of a text box. There are types for availability zones, AMI IDs, instance IDs, key pairs, security groups, subnets, volumes, VPCs, and Route 53 hosted zones, plus a ",[205,1493,1494],{},"List\u003C>"," form of each.",[25,1497,1498,1487,1501,1504,1505,1508],{},[205,1499,1500],{},"LatestAmiId",[47,1502,1503],{},"SSM parameter type",". You supply a Parameter Store key, and CloudFormation fetches the current value at create or update time. That one line replaces the entire Region-to-AMI mapping table that older templates carried, and it is the reason the AWS public parameter ",[205,1506,1507],{},"/aws/service/ami-amazon-latest/..."," exists. Note what \"current\" means here: the value is resolved when the stack operation runs, so a stack created last month still holds last month's AMI ID until you update it.",[25,1510,1511,1512,1461,1514,1461,1517,1191,1520,1523],{},"The basic types are ",[205,1513,1453],{},[205,1515,1516],{},"Number",[205,1518,1519],{},"List\u003CNumber>",[205,1521,1522],{},"CommaDelimitedList",". A template can declare up to 200 parameters.",[25,1525,1526,1529,1530,1533,1534,1537,1538,1541,1542,1544,1545,1547,1548,1550],{},[47,1527,1528],{},"The misconception worth killing now:"," parameters are not a secrets mechanism. ",[205,1531,1532],{},"NoEcho: true"," masks a parameter with asterisks in ",[205,1535,1536],{},"describe-stacks"," and ",[205,1539,1540],{},"describe-stack-events",", which is useful, but it is a display filter and nothing more. It does not mask the value in the ",[205,1543,1235],{}," section, in the ",[205,1546,1262],{}," section, or in a resource's ",[205,1549,1262],{}," attribute, and the value still travels through your API call and your CI logs. Secrets belong in a dynamic reference, covered later in this lesson.",[32,1552,1554],{"id":1553},"intrinsic-functions","Intrinsic functions",[25,1556,1557],{},"A template has to refer to things that do not exist yet. The instance needs the security group's ID, but the security group has no ID until CloudFormation creates it. Intrinsic functions are how you write \"whatever that turns out to be.\"",[25,1559,1560,1565],{},[47,1561,1562],{},[205,1563,1564],{},"Ref"," returns a resource's primary identifier, or a parameter's value.",[326,1567,1569],{"className":328,"code":1568,"language":330,"meta":331,"style":331},"SubnetId: !Ref PrivateSubnetA     # returns subnet-0abc123\nInstanceType: !Ref InstanceType   # returns the parameter value\n",[205,1570,1571,1587],{"__ignoreMap":331},[335,1572,1573,1576,1578,1580,1583],{"class":337,"line":338},[335,1574,1575],{"class":341},"SubnetId",[335,1577,346],{"class":345},[335,1579,1127],{"class":1126},[335,1581,1582],{"class":349}," PrivateSubnetA",[335,1584,1586],{"class":1585},"sutJx","     # returns subnet-0abc123\n",[335,1588,1589,1592,1594,1596,1599],{"class":337,"line":353},[335,1590,1591],{"class":341},"InstanceType",[335,1593,346],{"class":345},[335,1595,1127],{"class":1126},[335,1597,1598],{"class":349}," InstanceType",[335,1600,1601],{"class":1585},"   # returns the parameter value\n",[25,1603,1604,1605,1607,1608,1611,1612,1615,1616,1619],{},"What ",[205,1606,1564],{}," returns is resource-specific and documented per type. For ",[205,1609,1610],{},"AWS::EC2::Instance"," it is the instance ID. For ",[205,1613,1614],{},"AWS::S3::Bucket"," it is the bucket name. For ",[205,1617,1618],{},"AWS::IAM::Role"," it is the role name, not the ARN, which is a very common one-line failure.",[25,1621,1622,1627],{},[47,1623,1624],{},[205,1625,1626],{},"Fn::GetAtt"," returns a named attribute instead of the identifier.",[326,1629,1631],{"className":328,"code":1630,"language":330,"meta":331,"style":331},"RoleArn: !GetAtt AppRole.Arn\nDnsName: !GetAtt AppLoadBalancer.DNSName\n",[205,1632,1633,1646],{"__ignoreMap":331},[335,1634,1635,1638,1640,1643],{"class":337,"line":338},[335,1636,1637],{"class":341},"RoleArn",[335,1639,346],{"class":345},[335,1641,1642],{"class":1126}," !GetAtt",[335,1644,1645],{"class":349}," AppRole.Arn\n",[335,1647,1648,1651,1653,1655],{"class":337,"line":353},[335,1649,1650],{"class":341},"DnsName",[335,1652,346],{"class":345},[335,1654,1642],{"class":1126},[335,1656,1657],{"class":349}," AppLoadBalancer.DNSName\n",[25,1659,1660,1661,1663,1664,1667,1668,1670,1671,1673],{},"Read the boundary between them once and you stop guessing: ",[205,1662,1564],{}," gives you the one identifier the resource type nominates; ",[205,1665,1666],{},"GetAtt"," gives you any other published attribute, by name. When a stem asks for an ARN and the resource's ",[205,1669,1564],{}," returns a name, the answer is ",[205,1672,1666],{},".",[25,1675,1676,1681,1682,1685],{},[47,1677,1678],{},[205,1679,1680],{},"Fn::Sub"," does string substitution, and it is the readable replacement for nested ",[205,1683,1684],{},"Fn::Join"," calls.",[326,1687,1689],{"className":328,"code":1688,"language":330,"meta":331,"style":331},"BucketName: !Sub \"${EnvironmentName}-app-logs-${AWS::AccountId}\"\nArn: !Sub \"arn:${AWS::Partition}:s3:::${LogBucket}/*\"\n",[205,1690,1691,1711],{"__ignoreMap":331},[335,1692,1693,1696,1698,1701,1705,1708],{"class":337,"line":338},[335,1694,1695],{"class":341},"BucketName",[335,1697,346],{"class":345},[335,1699,1700],{"class":1126}," !Sub",[335,1702,1704],{"class":1703},"sjJ54"," \"",[335,1706,1707],{"class":349},"${EnvironmentName}-app-logs-${AWS::AccountId}",[335,1709,1710],{"class":1703},"\"\n",[335,1712,1713,1716,1718,1720,1722,1725],{"class":337,"line":353},[335,1714,1715],{"class":341},"Arn",[335,1717,346],{"class":345},[335,1719,1700],{"class":1126},[335,1721,1704],{"class":1703},[335,1723,1724],{"class":349},"arn:${AWS::Partition}:s3:::${LogBucket}/*",[335,1726,1710],{"class":1703},[25,1728,1729,1730,1733,1734,1737,1738,1461,1741,1461,1744,1461,1747,1461,1750,1461,1753,1191,1756,1759],{},"Those ",[205,1731,1732],{},"${AWS::...}"," values are ",[47,1735,1736],{},"pseudo parameters",": values CloudFormation supplies without you declaring them. ",[205,1739,1740],{},"AWS::Region",[205,1742,1743],{},"AWS::AccountId",[205,1745,1746],{},"AWS::StackName",[205,1748,1749],{},"AWS::StackId",[205,1751,1752],{},"AWS::Partition",[205,1754,1755],{},"AWS::URLSuffix",[205,1757,1758],{},"AWS::NoValue",". Using them instead of hardcoded values is what makes a template portable across accounts, Regions, and partitions such as GovCloud.",[25,1761,1762],{},"The rest of the working set, briefly:",[100,1764,1765,1775],{},[103,1766,1767],{},[106,1768,1769,1772],{},[109,1770,1771],{},"Function",[109,1773,1774],{},"Use it for",[118,1776,1777,1789,1799,1809,1822,1832,1842,1852,1862,1884],{},[106,1778,1779,1783],{},[123,1780,1781],{},[205,1782,1217],{},[123,1784,1785,1786,1788],{},"Read a value out of the ",[205,1787,1211],{}," section",[106,1790,1791,1796],{},[123,1792,1793],{},[205,1794,1795],{},"Fn::ImportValue",[123,1797,1798],{},"Read a value exported by another stack in the same account and Region",[106,1800,1801,1806],{},[123,1802,1803],{},[205,1804,1805],{},"Fn::GetStackOutput",[123,1807,1808],{},"Read any stack output, including cross-Region and cross-account",[106,1810,1811,1819],{},[123,1812,1813,1815,1816],{},[205,1814,1684],{}," / ",[205,1817,1818],{},"Fn::Split",[123,1820,1821],{},"Build a string from parts, or break one apart",[106,1823,1824,1829],{},[123,1825,1826],{},[205,1827,1828],{},"Fn::Select",[123,1830,1831],{},"Pick an item from a list by index",[106,1833,1834,1839],{},[123,1835,1836],{},[205,1837,1838],{},"Fn::GetAZs",[123,1840,1841],{},"Get the availability zones of a Region as a list",[106,1843,1844,1849],{},[123,1845,1846],{},[205,1847,1848],{},"Fn::Base64",[123,1850,1851],{},"Encode user data",[106,1853,1854,1859],{},[123,1855,1856],{},[205,1857,1858],{},"Fn::Cidr",[123,1860,1861],{},"Carve subnet CIDR blocks out of a VPC CIDR",[106,1863,1864,1881],{},[123,1865,1866,1461,1869,1461,1872,1461,1875,1461,1878],{},[205,1867,1868],{},"Fn::If",[205,1870,1871],{},"Fn::Equals",[205,1873,1874],{},"Fn::Not",[205,1876,1877],{},"Fn::And",[205,1879,1880],{},"Fn::Or",[123,1882,1883],{},"Condition logic",[106,1885,1886,1897],{},[123,1887,1888,1461,1891,1461,1894],{},[205,1889,1890],{},"Fn::ForEach",[205,1892,1893],{},"Fn::Length",[205,1895,1896],{},"Fn::ToJsonString",[123,1898,1899,1900,1902],{},"Loops and helpers, available only with the ",[205,1901,1255],{}," transform",[25,1904,1905,1906,1908],{},"Intrinsic functions are not usable everywhere. You can use them in resource properties, outputs, metadata attributes, update policy attributes, and conditions. You cannot use them in the ",[205,1907,1201],{}," section, which is why a parameter default can never be computed.",[32,1910,1912],{"id":1911},"the-dependency-graph-you-did-not-have-to-write","The dependency graph you did not have to write",[25,1914,1915],{},"Here is where declarative stops being an abstract word.",[326,1917,1919],{"className":328,"code":1918,"language":330,"meta":331,"style":331},"Resources:\n  AppVpc:\n    Type: AWS::EC2::VPC\n    Properties:\n      CidrBlock: 10.0.0.0/16\n\n  WebSecurityGroup:\n    Type: AWS::EC2::SecurityGroup\n    Properties:\n      GroupDescription: Web tier\n      VpcId: !Ref AppVpc\n\n  WebInstance:\n    Type: AWS::EC2::Instance\n    Properties:\n      ImageId: !Ref LatestAmiId\n      SecurityGroupIds:\n        - !Ref WebSecurityGroup\n",[205,1920,1921,1927,1934,1943,1949,1959,1963,1969,1977,1983,1992,2002,2006,2013,2022,2028,2040,2047],{"__ignoreMap":331},[335,1922,1923,1925],{"class":337,"line":338},[335,1924,1080],{"class":341},[335,1926,382],{"class":345},[335,1928,1929,1932],{"class":337,"line":353},[335,1930,1931],{"class":341},"  AppVpc",[335,1933,382],{"class":345},[335,1935,1936,1938,1940],{"class":337,"line":364},[335,1937,1094],{"class":341},[335,1939,346],{"class":345},[335,1941,1942],{"class":349}," AWS::EC2::VPC\n",[335,1944,1945,1947],{"class":337,"line":376},[335,1946,1104],{"class":341},[335,1948,382],{"class":345},[335,1950,1951,1954,1956],{"class":337,"line":385},[335,1952,1953],{"class":341},"      CidrBlock",[335,1955,346],{"class":345},[335,1957,1958],{"class":349}," 10.0.0.0/16\n",[335,1960,1961],{"class":337,"line":399},[335,1962,1386],{"emptyLinePlaceholder":9},[335,1964,1965,1967],{"class":337,"line":407},[335,1966,1087],{"class":341},[335,1968,382],{"class":345},[335,1970,1971,1973,1975],{"class":337,"line":420},[335,1972,1094],{"class":341},[335,1974,346],{"class":345},[335,1976,1099],{"class":349},[335,1978,1979,1981],{"class":337,"line":431},[335,1980,1104],{"class":341},[335,1982,382],{"class":345},[335,1984,1985,1987,1989],{"class":337,"line":439},[335,1986,1111],{"class":341},[335,1988,346],{"class":345},[335,1990,1991],{"class":349}," Web tier\n",[335,1993,1994,1996,1998,2000],{"class":337,"line":447},[335,1995,1121],{"class":341},[335,1997,346],{"class":345},[335,1999,1127],{"class":1126},[335,2001,1130],{"class":349},[335,2003,2004],{"class":337,"line":456},[335,2005,1386],{"emptyLinePlaceholder":9},[335,2007,2008,2011],{"class":337,"line":464},[335,2009,2010],{"class":341},"  WebInstance",[335,2012,382],{"class":345},[335,2014,2015,2017,2019],{"class":337,"line":476},[335,2016,1094],{"class":341},[335,2018,346],{"class":345},[335,2020,2021],{"class":349}," AWS::EC2::Instance\n",[335,2023,2024,2026],{"class":337,"line":483},[335,2025,1104],{"class":341},[335,2027,382],{"class":345},[335,2029,2030,2033,2035,2037],{"class":337,"line":495},[335,2031,2032],{"class":341},"      ImageId",[335,2034,346],{"class":345},[335,2036,1127],{"class":1126},[335,2038,2039],{"class":349}," LatestAmiId\n",[335,2041,2042,2045],{"class":337,"line":504},[335,2043,2044],{"class":341},"      SecurityGroupIds",[335,2046,382],{"class":345},[335,2048,2049,2052,2054],{"class":337,"line":511},[335,2050,2051],{"class":345},"        -",[335,2053,1127],{"class":1126},[335,2055,2056],{"class":349}," WebSecurityGroup\n",[25,2058,2059,2060,2062,2063,1191,2066,2062,2069,2071],{},"Nothing in that template states an order. But ",[205,2061,1135],{}," refers to ",[205,2064,2065],{},"AppVpc",[205,2067,2068],{},"WebInstance",[205,2070,1135],{},", so CloudFormation builds a directed graph out of those references and creates resources in an order that satisfies it: VPC, then security group, then instance. Resources with no edge between them are created in parallel, which is why a 40-resource stack does not take 40 times as long as a 1-resource stack.",[25,2073,2074],{},"Deletion runs the same graph in reverse. That is why you cannot delete a VPC stack while an instance from it still exists, and why an unexpected delete order usually means an unexpected reference.",[558,2076],{"alt":2077,"slug":2078},"A directed graph of five template resources where solid arrows labelled Ref and Fn::GetAtt set the creation order automatically, and a single dashed DependsOn arrow supplies the one ordering that no reference expresses.","cloudformation-fundamentals-dependency-graph",[25,2080,2081],{},"Sometimes two resources must be ordered even though neither refers to the other. The classic case is an Elastic IP in a VPC: it needs the internet gateway attached before it can be allocated, but nothing in its properties mentions the attachment. For that, and only that, you declare the edge yourself:",[326,2083,2085],{"className":328,"code":2084,"language":330,"meta":331,"style":331},"  NatEip:\n    Type: AWS::EC2::EIP\n    DependsOn: AttachGateway\n    Properties:\n      Domain: vpc\n",[205,2086,2087,2094,2103,2113,2119],{"__ignoreMap":331},[335,2088,2089,2092],{"class":337,"line":338},[335,2090,2091],{"class":341},"  NatEip",[335,2093,382],{"class":345},[335,2095,2096,2098,2100],{"class":337,"line":353},[335,2097,1094],{"class":341},[335,2099,346],{"class":345},[335,2101,2102],{"class":349}," AWS::EC2::EIP\n",[335,2104,2105,2108,2110],{"class":337,"line":364},[335,2106,2107],{"class":341},"    DependsOn",[335,2109,346],{"class":345},[335,2111,2112],{"class":349}," AttachGateway\n",[335,2114,2115,2117],{"class":337,"line":376},[335,2116,1104],{"class":341},[335,2118,382],{"class":345},[335,2120,2121,2124,2126],{"class":337,"line":385},[335,2122,2123],{"class":341},"      Domain",[335,2125,346],{"class":345},[335,2127,2128],{"class":349}," vpc\n",[25,2130,2131,2132,2135],{},"Reach for ",[205,2133,2134],{},"DependsOn"," when a reference cannot express the ordering, not as a general safety measure. Sprinkling it everywhere serializes a stack that could have deployed in parallel, and it hides the real relationships from the next reader.",[32,2137,2139],{"id":2138},"conditions-and-mappings-one-template-many-environments","Conditions and Mappings: one template, many environments",[25,2141,2142],{},"Production needs a Multi-AZ database and a bastion host. Dev needs neither, and paying for both is silly. Two mechanisms handle this without forking the template.",[25,2144,2145,2147],{},[47,2146,1211],{}," are a static lookup table:",[326,2149,2151],{"className":328,"code":2150,"language":330,"meta":331,"style":331},"Mappings:\n  EnvConfig:\n    dev:\n      InstanceType: t3.small\n      MinSize: 1\n    prod:\n      InstanceType: m6i.large\n      MinSize: 3\n\nResources:\n  AppGroup:\n    Type: AWS::AutoScaling::AutoScalingGroup\n    Properties:\n      MinSize: !FindInMap [EnvConfig, !Ref EnvironmentName, MinSize]\n",[205,2152,2153,2159,2166,2173,2183,2193,2200,2209,2218,2222,2228,2235,2244,2250],{"__ignoreMap":331},[335,2154,2155,2157],{"class":337,"line":338},[335,2156,1211],{"class":341},[335,2158,382],{"class":345},[335,2160,2161,2164],{"class":337,"line":353},[335,2162,2163],{"class":341},"  EnvConfig",[335,2165,382],{"class":345},[335,2167,2168,2171],{"class":337,"line":364},[335,2169,2170],{"class":341},"    dev",[335,2172,382],{"class":345},[335,2174,2175,2178,2180],{"class":337,"line":376},[335,2176,2177],{"class":341},"      InstanceType",[335,2179,346],{"class":345},[335,2181,2182],{"class":349}," t3.small\n",[335,2184,2185,2188,2190],{"class":337,"line":385},[335,2186,2187],{"class":341},"      MinSize",[335,2189,346],{"class":345},[335,2191,2192],{"class":372}," 1\n",[335,2194,2195,2198],{"class":337,"line":399},[335,2196,2197],{"class":341},"    prod",[335,2199,382],{"class":345},[335,2201,2202,2204,2206],{"class":337,"line":407},[335,2203,2177],{"class":341},[335,2205,346],{"class":345},[335,2207,2208],{"class":349}," m6i.large\n",[335,2210,2211,2213,2215],{"class":337,"line":420},[335,2212,2187],{"class":341},[335,2214,346],{"class":345},[335,2216,2217],{"class":372}," 3\n",[335,2219,2220],{"class":337,"line":431},[335,2221,1386],{"emptyLinePlaceholder":9},[335,2223,2224,2226],{"class":337,"line":439},[335,2225,1080],{"class":341},[335,2227,382],{"class":345},[335,2229,2230,2233],{"class":337,"line":447},[335,2231,2232],{"class":341},"  AppGroup",[335,2234,382],{"class":345},[335,2236,2237,2239,2241],{"class":337,"line":456},[335,2238,1094],{"class":341},[335,2240,346],{"class":345},[335,2242,2243],{"class":349}," AWS::AutoScaling::AutoScalingGroup\n",[335,2245,2246,2248],{"class":337,"line":464},[335,2247,1104],{"class":341},[335,2249,382],{"class":345},[335,2251,2252,2254,2256,2259,2261,2264,2266,2268,2271,2273,2276],{"class":337,"line":476},[335,2253,2187],{"class":341},[335,2255,346],{"class":345},[335,2257,2258],{"class":1126}," !FindInMap",[335,2260,1354],{"class":345},[335,2262,2263],{"class":349},"EnvConfig",[335,2265,1360],{"class":345},[335,2267,1127],{"class":1126},[335,2269,2270],{"class":349}," EnvironmentName",[335,2272,1360],{"class":345},[335,2274,2275],{"class":349}," MinSize",[335,2277,1371],{"class":345},[25,2279,2280,2282],{},[47,2281,1225],{}," decide whether something exists at all:",[326,2284,2286],{"className":328,"code":2285,"language":330,"meta":331,"style":331},"Conditions:\n  IsProduction: !Equals [!Ref EnvironmentName, prod]\n\nResources:\n  BastionHost:\n    Type: AWS::EC2::Instance\n    Condition: IsProduction\n    Properties:\n      # ...\n\n  AppDatabase:\n    Type: AWS::RDS::DBInstance\n    Properties:\n      MultiAZ: !If [IsProduction, true, false]\n      DBSnapshotIdentifier: !If [IsProduction, !Ref SnapshotId, !Ref \"AWS::NoValue\"]\n",[205,2287,2288,2294,2317,2321,2327,2334,2342,2352,2358,2363,2367,2374,2383,2389,2417],{"__ignoreMap":331},[335,2289,2290,2292],{"class":337,"line":338},[335,2291,1225],{"class":341},[335,2293,382],{"class":345},[335,2295,2296,2299,2301,2304,2306,2309,2311,2313,2315],{"class":337,"line":353},[335,2297,2298],{"class":341},"  IsProduction",[335,2300,346],{"class":345},[335,2302,2303],{"class":1126}," !Equals",[335,2305,1354],{"class":345},[335,2307,2308],{"class":1126},"!Ref",[335,2310,2270],{"class":349},[335,2312,1360],{"class":345},[335,2314,1368],{"class":349},[335,2316,1371],{"class":345},[335,2318,2319],{"class":337,"line":364},[335,2320,1386],{"emptyLinePlaceholder":9},[335,2322,2323,2325],{"class":337,"line":376},[335,2324,1080],{"class":341},[335,2326,382],{"class":345},[335,2328,2329,2332],{"class":337,"line":385},[335,2330,2331],{"class":341},"  BastionHost",[335,2333,382],{"class":345},[335,2335,2336,2338,2340],{"class":337,"line":399},[335,2337,1094],{"class":341},[335,2339,346],{"class":345},[335,2341,2021],{"class":349},[335,2343,2344,2347,2349],{"class":337,"line":407},[335,2345,2346],{"class":341},"    Condition",[335,2348,346],{"class":345},[335,2350,2351],{"class":349}," IsProduction\n",[335,2353,2354,2356],{"class":337,"line":420},[335,2355,1104],{"class":341},[335,2357,382],{"class":345},[335,2359,2360],{"class":337,"line":431},[335,2361,2362],{"class":1585},"      # ...\n",[335,2364,2365],{"class":337,"line":439},[335,2366,1386],{"emptyLinePlaceholder":9},[335,2368,2369,2372],{"class":337,"line":447},[335,2370,2371],{"class":341},"  AppDatabase",[335,2373,382],{"class":345},[335,2375,2376,2378,2380],{"class":337,"line":456},[335,2377,1094],{"class":341},[335,2379,346],{"class":345},[335,2381,2382],{"class":349}," AWS::RDS::DBInstance\n",[335,2384,2385,2387],{"class":337,"line":464},[335,2386,1104],{"class":341},[335,2388,382],{"class":345},[335,2390,2391,2394,2396,2399,2401,2404,2406,2410,2412,2415],{"class":337,"line":476},[335,2392,2393],{"class":341},"      MultiAZ",[335,2395,346],{"class":345},[335,2397,2398],{"class":1126}," !If",[335,2400,1354],{"class":345},[335,2402,2403],{"class":349},"IsProduction",[335,2405,1360],{"class":345},[335,2407,2409],{"class":2408},"syTEX"," true",[335,2411,1360],{"class":345},[335,2413,2414],{"class":2408}," false",[335,2416,1371],{"class":345},[335,2418,2419,2422,2424,2426,2428,2430,2432,2434,2437,2439,2441,2443,2445,2448],{"class":337,"line":483},[335,2420,2421],{"class":341},"      DBSnapshotIdentifier",[335,2423,346],{"class":345},[335,2425,2398],{"class":1126},[335,2427,1354],{"class":345},[335,2429,2403],{"class":349},[335,2431,1360],{"class":345},[335,2433,1127],{"class":1126},[335,2435,2436],{"class":349}," SnapshotId",[335,2438,1360],{"class":345},[335,2440,1127],{"class":1126},[335,2442,1704],{"class":1703},[335,2444,1758],{"class":349},[335,2446,2447],{"class":1703},"\"",[335,2449,1371],{"class":345},[25,2451,2452,2453,2456,2457,2459,2460,2462],{},"Two details in that last block are worth stopping on. A ",[205,2454,2455],{},"Condition"," on a resource controls whether the resource is created; ",[205,2458,1868],{}," inside a property controls the value of that property. And ",[205,2461,1758],{}," is the pseudo parameter that means \"omit this property entirely,\" which is the only way to express an absent optional property conditionally.",[25,2464,2465],{},"The decision rule: mappings for values that differ, conditions for resources and properties that exist or do not.",[32,2467,2469],{"id":2468},"outputs-and-sharing-values-between-stacks","Outputs, and sharing values between stacks",[25,2471,2472],{},"A stack that builds a VPC is not much use if nothing else can find the subnet IDs.",[326,2474,2476],{"className":328,"code":2475,"language":330,"meta":331,"style":331},"Outputs:\n  AppVpcId:\n    Description: VPC created by this stack\n    Value: !Ref AppVpc\n    Export:\n      Name: !Sub \"${AWS::StackName}-VpcId\"\n",[205,2477,2478,2484,2490,2499,2510,2517],{"__ignoreMap":331},[335,2479,2480,2482],{"class":337,"line":338},[335,2481,1235],{"class":341},[335,2483,382],{"class":345},[335,2485,2486,2488],{"class":337,"line":353},[335,2487,1391],{"class":341},[335,2489,382],{"class":345},[335,2491,2492,2494,2496],{"class":337,"line":364},[335,2493,1376],{"class":341},[335,2495,346],{"class":345},[335,2497,2498],{"class":349}," VPC created by this stack\n",[335,2500,2501,2504,2506,2508],{"class":337,"line":376},[335,2502,2503],{"class":341},"    Value",[335,2505,346],{"class":345},[335,2507,1127],{"class":1126},[335,2509,1130],{"class":349},[335,2511,2512,2515],{"class":337,"line":385},[335,2513,2514],{"class":341},"    Export",[335,2516,382],{"class":345},[335,2518,2519,2522,2524,2526,2528,2531],{"class":337,"line":399},[335,2520,2521],{"class":341},"      Name",[335,2523,346],{"class":345},[335,2525,1700],{"class":1126},[335,2527,1704],{"class":1703},[335,2529,2530],{"class":349},"${AWS::StackName}-VpcId",[335,2532,1710],{"class":1703},[25,2534,2535,2538,2539,2542,2543,2546],{},[205,2536,2537],{},"Value"," makes the output visible on the stack. Adding ",[205,2540,2541],{},"Export"," publishes it under a name that must be unique per account and Region, which is why prefixing with ",[205,2544,2545],{},"${AWS::StackName}"," is the standard habit.",[25,2548,2549],{},"Another stack then consumes it:",[326,2551,2553],{"className":328,"code":2552,"language":330,"meta":331,"style":331},"  AppSubnet:\n    Type: AWS::EC2::Subnet\n    Properties:\n      VpcId: !ImportValue network-stack-VpcId\n",[205,2554,2555,2562,2571,2577],{"__ignoreMap":331},[335,2556,2557,2560],{"class":337,"line":338},[335,2558,2559],{"class":341},"  AppSubnet",[335,2561,382],{"class":345},[335,2563,2564,2566,2568],{"class":337,"line":353},[335,2565,1094],{"class":341},[335,2567,346],{"class":345},[335,2569,2570],{"class":349}," AWS::EC2::Subnet\n",[335,2572,2573,2575],{"class":337,"line":364},[335,2574,1104],{"class":341},[335,2576,382],{"class":345},[335,2578,2579,2581,2583,2586],{"class":337,"line":376},[335,2580,1121],{"class":341},[335,2582,346],{"class":345},[335,2584,2585],{"class":1126}," !ImportValue",[335,2587,2588],{"class":349}," network-stack-VpcId\n",[25,2590,2591],{},"There are now three ways to pass a value from one stack to another, and they differ in strength and reach, not in syntax.",[100,2593,2594,2611],{},[103,2595,2596],{},[106,2597,2598,2600,2604,2608],{},[109,2599],{},[109,2601,2602],{},[205,2603,1795],{},[109,2605,2606],{},[205,2607,1805],{},[109,2609,2610],{},"Nested stack outputs",[118,2612,2613,2627,2638,2654,2668,2682],{},[106,2614,2615,2621,2623,2625],{},[123,2616,2617,2618,2620],{},"Requires an ",[205,2619,2541],{}," on the producer",[123,2622,789],{},[123,2624,723],{},[123,2626,723],{},[106,2628,2629,2632,2634,2636],{},[123,2630,2631],{},"Same account, same Region",[123,2633,789],{},[123,2635,789],{},[123,2637,789],{},[106,2639,2640,2643,2645,2652],{},[123,2641,2642],{},"Cross-Region",[123,2644,723],{},[123,2646,2647,2648,2651],{},"Yes, with the ",[205,2649,2650],{},"Region"," parameter",[123,2653,723],{},[106,2655,2656,2659,2661,2666],{},[123,2657,2658],{},"Cross-account",[123,2660,723],{},[123,2662,2663,2664],{},"Yes, with a ",[205,2665,1637],{},[123,2667,723],{},[106,2669,2670,2673,2676,2679],{},[123,2671,2672],{},"Reference strength",[123,2674,2675],{},"Strong: producer cannot be deleted while imported",[123,2677,2678],{},"Weak: resolved at deploy time only",[123,2680,2681],{},"Owned by the parent stack",[106,2683,2684,2687,2690,2693],{},[123,2685,2686],{},"Can the exported value change while in use?",[123,2688,2689],{},"No, the export is locked",[123,2691,2692],{},"Yes, silently",[123,2694,2695],{},"Managed with the parent",[25,2697,2698,2699,2701,2702,2704],{},"That strength column is the whole trade. ",[205,2700,1795],{}," gives you referential integrity: CloudFormation refuses to delete the exporting stack, and refuses to change or remove an export that another stack imports. That protection is genuinely valuable and genuinely annoying, because it means you cannot rename a subnet export without first unwiring every consumer. ",[205,2703,1805],{}," gives up the protection to buy cross-Region and cross-account reach, and resolves the value fresh on each operation.",[32,2706,2708],{"id":2707},"keeping-credentials-out-of-the-file","Keeping credentials out of the file",[25,2710,2711,2712,1673],{},"Never put a password in a template. That is easy to agree with and easy to violate accidentally, so use the mechanism built for it: ",[47,2713,2714],{},"dynamic references",[326,2716,2718],{"className":328,"code":2717,"language":330,"meta":331,"style":331},"  AppDatabase:\n    Type: AWS::RDS::DBInstance\n    Properties:\n      MasterUsername: '{{resolve:ssm:/app/db/username}}'\n      MasterUserPassword: '{{resolve:secretsmanager:prod/app/db:SecretString:password}}'\n",[205,2719,2720,2726,2734,2740,2756],{"__ignoreMap":331},[335,2721,2722,2724],{"class":337,"line":338},[335,2723,2371],{"class":341},[335,2725,382],{"class":345},[335,2727,2728,2730,2732],{"class":337,"line":353},[335,2729,1094],{"class":341},[335,2731,346],{"class":345},[335,2733,2382],{"class":349},[335,2735,2736,2738],{"class":337,"line":364},[335,2737,1104],{"class":341},[335,2739,382],{"class":345},[335,2741,2742,2745,2747,2750,2753],{"class":337,"line":376},[335,2743,2744],{"class":341},"      MasterUsername",[335,2746,346],{"class":345},[335,2748,2749],{"class":1703}," '",[335,2751,2752],{"class":349},"{{resolve:ssm:/app/db/username}}",[335,2754,2755],{"class":1703},"'\n",[335,2757,2758,2761,2763,2765,2768],{"class":337,"line":385},[335,2759,2760],{"class":341},"      MasterUserPassword",[335,2762,346],{"class":345},[335,2764,2749],{"class":1703},[335,2766,2767],{"class":349},"{{resolve:secretsmanager:prod/app/db:SecretString:password}}",[335,2769,2755],{"class":1703},[25,2771,2772],{},"Three patterns exist:",[40,2774,2775,2781,2787],{},[43,2776,2777,2780],{},[205,2778,2779],{},"{{resolve:ssm:parameter-name:version}}"," for a plaintext Parameter Store value.",[43,2782,2783,2786],{},[205,2784,2785],{},"{{resolve:ssm-secure:parameter-name:version}}"," for a SecureString parameter.",[43,2788,2789,2792],{},[205,2790,2791],{},"{{resolve:secretsmanager:secret-id:SecretString:json-key:version-stage:version-id}}"," for a Secrets Manager secret.",[25,2794,2795],{},"CloudFormation resolves the reference when it needs the value and never stores it. Rotate the secret and the next stack operation picks up the new value with no template change.",[25,2797,2798,2799,2802,2803,2806],{},"The limits are small but real: a template can hold up to 60 dynamic references, they are not supported in ",[205,2800,2801],{},"AWS::CloudFormation::Init"," metadata or in EC2 ",[205,2804,2805],{},"UserData",", and they are not resolved before a transform runs. A reference that ends in a backslash fails to resolve at all.",[32,2808,2810],{"id":2809},"resource-attributes-that-change-the-blast-radius","Resource attributes that change the blast radius",[25,2812,2813,2814,1537,2816,2818],{},"Resource attributes sit next to ",[205,2815,1190],{},[205,2817,1194],{},", and they change what CloudFormation does to a resource rather than what the resource is.",[25,2820,2821,2826],{},[47,2822,2823],{},[205,2824,2825],{},"DeletionPolicy"," decides what happens when the resource leaves the stack.",[100,2828,2829,2838],{},[103,2830,2831],{},[106,2832,2833,2835],{},[109,2834,2537],{},[109,2836,2837],{},"Effect",[118,2839,2840,2850,2860,2873],{},[106,2841,2842,2847],{},[123,2843,2844],{},[205,2845,2846],{},"Delete",[123,2848,2849],{},"Delete the resource. The default for nearly every type.",[106,2851,2852,2857],{},[123,2853,2854],{},[205,2855,2856],{},"Retain",[123,2858,2859],{},"Keep the resource, remove it from CloudFormation's scope. It keeps billing.",[106,2861,2862,2867],{},[123,2863,2864],{},[205,2865,2866],{},"RetainExceptOnCreate",[123,2868,2869,2870,2872],{},"Behaves like ",[205,2871,2856],{},", except that a resource created by an operation that then rolls back is deleted.",[106,2874,2875,2879],{},[123,2876,2877],{},[205,2878,919],{},[123,2880,2881],{},"Take a snapshot, then delete. Supported on EBS volumes, RDS and DocumentDB and Neptune clusters and instances, ElastiCache clusters and replication groups, and Redshift clusters.",[25,2883,2884,2885,2888,2889,2892,2893,2896,2897,2899,2900,2902],{},"The exception that catches people: ",[205,2886,2887],{},"AWS::RDS::DBCluster",", and any ",[205,2890,2891],{},"AWS::RDS::DBInstance"," that does not specify ",[205,2894,2895],{},"DBClusterIdentifier",", default to ",[205,2898,919],{},", not ",[205,2901,2846],{},". Delete such a stack and you get a surviving snapshot and a surviving bill.",[25,2904,2905,2910,2911,2913,2914,2916,2917,2920,2921,2924],{},[47,2906,2907],{},[205,2908,2909],{},"UpdateReplacePolicy"," does the same job for a different event. ",[205,2912,2825],{}," covers a resource being removed from the stack; ",[205,2915,2909],{}," covers a resource being replaced during an update, where CloudFormation creates a new physical resource and deletes the old one. Setting ",[205,2918,2919],{},"DeletionPolicy: Retain"," on a database and forgetting ",[205,2922,2923],{},"UpdateReplacePolicy: Retain"," leaves you protected against a stack delete and unprotected against the far more likely accidental replacement. Set both.",[326,2926,2928],{"className":328,"code":2927,"language":330,"meta":331,"style":331},"  AppDatabase:\n    Type: AWS::RDS::DBInstance\n    DeletionPolicy: Snapshot\n    UpdateReplacePolicy: Snapshot\n    Properties:\n      # ...\n",[205,2929,2930,2936,2944,2954,2963,2969],{"__ignoreMap":331},[335,2931,2932,2934],{"class":337,"line":338},[335,2933,2371],{"class":341},[335,2935,382],{"class":345},[335,2937,2938,2940,2942],{"class":337,"line":353},[335,2939,1094],{"class":341},[335,2941,346],{"class":345},[335,2943,2382],{"class":349},[335,2945,2946,2949,2951],{"class":337,"line":364},[335,2947,2948],{"class":341},"    DeletionPolicy",[335,2950,346],{"class":345},[335,2952,2953],{"class":349}," Snapshot\n",[335,2955,2956,2959,2961],{"class":337,"line":376},[335,2957,2958],{"class":341},"    UpdateReplacePolicy",[335,2960,346],{"class":345},[335,2962,2953],{"class":349},[335,2964,2965,2967],{"class":337,"line":385},[335,2966,1104],{"class":341},[335,2968,382],{"class":345},[335,2970,2971],{"class":337,"line":399},[335,2972,2362],{"class":1585},[25,2974,2975,2979],{},[47,2976,2977],{},[205,2978,1262],{}," attaches arbitrary data to a resource. It has one operational use worth remembering: CloudFormation does not treat a change to a deletion policy, update policy, condition, or output declaration as an update, so a template edit that touches only those produces \"No updates to be performed.\" Changing any metadata value gives CloudFormation something to see, and the update proceeds.",[25,2981,2982,1537,2985,2988],{},[205,2983,2984],{},"CreationPolicy",[205,2986,2987],{},"UpdatePolicy",", the two attributes that control waiting for signals and rolling Auto Scaling updates, belong with stack operations and appear in the next lesson.",[32,2990,847],{"id":846},[40,2992,2993,3005,3008,3015,3018,3027,3037,3043,3052,3058],{},[43,2994,2995,2997,2998,3000,3001,1670,3003,1673],{},[205,2996,1564],{}," returns the resource's primary identifier; ",[205,2999,1626],{}," returns any other attribute by name. If the stem needs an ARN and the type's ",[205,3002,1564],{},[205,3004,1666],{},[43,3006,3007],{},"\"The same template must work in any Region or account\" points at pseudo parameters and AWS-specific or SSM parameter types, and away from hardcoded AMI IDs and account numbers.",[43,3009,3010,3012,3013,1673],{},[205,3011,1795],{}," is same-account, same-Region only. A stem that mentions a second Region or a second account and asks for a stack output rules it out and points at ",[205,3014,1805],{},[43,3016,3017],{},"\"Cannot delete stack, export in use by another stack\" is expected behavior, not a bug. Remove the import first.",[43,3019,3020,3023,3024,3026],{},[205,3021,3022],{},"NoEcho"," masks describe output. Any answer that treats it as encryption, or as protection for values you copied into ",[205,3025,1235],{},", is wrong.",[43,3028,3029,3030,1461,3033,3036],{},"Sensitive values in a template means dynamic references (",[205,3031,3032],{},"ssm-secure",[205,3034,3035],{},"secretsmanager","), not parameters.",[43,3038,3039,3040,3042],{},"The RDS ",[205,3041,919],{}," default is a favorite. Read \"no DeletionPolicy specified\" plus \"RDS\" as a snapshot, and the same words plus \"S3 bucket\" as a delete.",[43,3044,3045,3046,3048,3049,3051],{},"Set ",[205,3047,2909],{}," alongside ",[205,3050,2825],{}," whenever data is involved. Questions about a database that vanished during a routine update are testing exactly this.",[43,3053,3054,3055,3057],{},"\"No updates to be performed\" after editing only a deletion policy, update policy, condition, or output is expected. The fix is to change a resource ",[205,3056,1262],{}," value.",[43,3059,3060,3062],{},[205,3061,2134],{}," is for ordering that no reference expresses. The internet gateway attachment and an Elastic IP is the canonical pair.",[25,3064,3065],{},"The idea to carry forward is that a template is a description of a desired end state plus a graph of relationships, and CloudFormation derives everything else from it: the order of creation, the order of deletion, what can run in parallel, and what has to change when you edit one line.",[25,3067,3068],{},"Which raises the question this lesson deliberately left open. You now have a template that creates a stack correctly the first time. The next lesson is about the second time and every time after: how to change a running stack without breaking it, how to see what an update will do before it does it, and what to do when someone has been editing your resources in the console.",[893,3070,3071],{},"html pre.shiki code .sQzsp, html code.shiki .sQzsp{--shiki-light:#E53935;--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":331,"searchDepth":364,"depth":364,"links":3073},[3074,3075,3076,3077,3078,3079,3080,3081,3082,3083],{"id":1046,"depth":353,"text":1047},{"id":1157,"depth":353,"text":1158},{"id":1313,"depth":353,"text":1314},{"id":1553,"depth":353,"text":1554},{"id":1911,"depth":353,"text":1912},{"id":2138,"depth":353,"text":2139},{"id":2468,"depth":353,"text":2469},{"id":2707,"depth":353,"text":2708},{"id":2809,"depth":353,"text":2810},{"id":846,"depth":353,"text":847},[3085],{"slug":2078,"concept":3086,"style":911,"aspectRatio":912,"labels":3087},"A directed graph showing how CloudFormation derives create order from references inside one template. Five resource nodes (VPC, internet gateway, gateway attachment, security group, EC2 instance) are arranged left to right in creation order, with solid arrows labelled by the function that created the edge (Ref or Fn::GetAtt) and one dashed arrow labelled DependsOn between two nodes that share no reference. A short band underneath marks which nodes CloudFormation can build in parallel because nothing connects them. The emphasis is the contrast between the solid implicit edges and the single dashed explicit one: references write the graph for you, and DependsOn exists only for the ordering a reference cannot express.",[3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098],"Create order comes from references, not from template order","VPC","InternetGateway","AttachGateway: Ref VPC, Ref InternetGateway","WebSecurityGroup: Ref VPC","WebInstance: Ref WebSecurityGroup, Fn::GetAtt for the subnet","Solid edge: implicit dependency created by Ref or Fn::GetAtt","Dashed edge: DependsOn, declared by hand because no reference exists","Built in parallel: VPC and InternetGateway have no edge between them","Delete runs the graph backwards","If two resources must be ordered but never reference each other, only DependsOn can say so.",[1027,1028,1029,1030,1031,1032,1033],{},"/courses/aws-certified-cloudops-engineer-associate/en/domains/03-deployment-provisioning-automation/02-infrastructure-as-code/01-cloudformation-fundamentals",{"passingScore":929,"questions":3103},[3104,3112,3119,3128,3136,3144,3148,3156,3164],{"question":3105,"type":933,"options":3106,"correctAnswer":3107,"explanation":3111},"A template declares an EC2 instance with the logical ID WebServer. After the stack is created, what does Ref return for that resource?",[3107,3108,3109,3110],"The instance ID, such as i-0abc123def456","The string WebServer","The private IP address of the instance","The ARN of the instance","Ref on a resource returns that resource type's primary identifier, which for AWS::EC2::Instance is the instance ID. The logical ID is only the name inside the template; the private IP and other attributes come from Fn::GetAtt, and each resource type documents exactly what Ref and GetAtt return.",{"question":3113,"type":933,"options":3114,"correctAnswer":1457,"explanation":3118},"A template must not launch a stack if the user types an instance type outside a short approved list. Which parameter setting enforces that before any resource is created?",[3115,3116,3117,1457],"NoEcho set to true","A Condition that compares the parameter to each approved value","A Rules section entry using Fn::Contains","AllowedValues restricts a parameter to an explicit list and is checked before provisioning starts, so a bad value never reaches a resource. NoEcho only masks a value in describe output, and while conditions and rules can express complex validation, a simple approved list is exactly what AllowedValues exists for.",{"question":3120,"type":942,"options":3121,"correctAnswers":3126,"explanation":3127},"Which statements about NoEcho are correct? (Choose 2.)",[3122,3123,3124,3125],"It masks the parameter value in describe-stacks and describe-stack-events output","It encrypts the parameter value at rest inside CloudFormation","It does not mask values placed in the Outputs or Metadata sections","It prevents the value from being used in resource properties",[3122,3124],"NoEcho is a display control: it replaces the value with asterisks in stack descriptions and events, and that is all. It does not encrypt anything, and anything you copy into Outputs, Metadata, or a resource Metadata attribute is shown in the clear, which is why real secrets belong in a dynamic reference instead.",{"question":3129,"type":933,"options":3130,"correctAnswer":3133,"explanation":3135},"A template creates an Elastic IP and a VPC with an internet gateway. The Elastic IP must not be created until the gateway attachment exists, but no property of the Elastic IP references the attachment. What should you do?",[3131,3132,3133,3134],"Move the Elastic IP declaration below the attachment in the Resources section","Wrap the Elastic IP in a Condition that tests the attachment","Add a DependsOn attribute on the Elastic IP naming the attachment","Add the attachment's logical ID to the Elastic IP's Metadata attribute","CloudFormation derives ordering from references, so two resources that never reference each other may be built in parallel or in any order. DependsOn is the only way to declare an ordering that no Ref or Fn::GetAtt already implies, and the position of a resource in the Resources section has no effect at all.",{"question":3137,"type":933,"options":3138,"correctAnswer":3139,"explanation":3143},"Which reference method lets a stack in us-east-1 read an output from a stack in eu-west-1?",[3139,3140,3141,3142],"Fn::GetStackOutput with the Region parameter set to eu-west-1","Fn::ImportValue against an export created in eu-west-1","A nested stack whose TemplateURL points at the eu-west-1 stack","Fn::FindInMap with a Region key","Fn::ImportValue only resolves exports in the same account and Region, which is the constraint most people trip on. Fn::GetStackOutput was added for exactly this gap: it reads any stack output by name, accepts a Region and a RoleArn for cross-account access, and needs no Export on the producing side.",{"question":3145,"type":933,"options":3146,"correctAnswer":1003,"explanation":3147},"True or False: a stack whose export is imported by another stack can be deleted as long as the importing stack is not currently updating.",[1002,1003],"An export consumed by Fn::ImportValue is a strong reference, and CloudFormation blocks deletion of the exporting stack while any stack imports the value. That referential integrity is the main reason to choose Fn::ImportValue over Fn::GetStackOutput, whose weak reference gives you no such protection.",{"question":3149,"type":933,"options":3150,"correctAnswer":3153,"explanation":3155},"An RDS DB instance is declared in a template with no DeletionPolicy attribute. The stack is deleted. What happens to the database?",[3151,3152,3153,3154],"It is deleted along with the rest of the stack","It is retained and removed from CloudFormation's scope","A snapshot is taken before it is deleted","The stack deletion fails because RDS resources require an explicit policy","The default DeletionPolicy is Delete for almost every resource type, but AWS::RDS::DBCluster and standalone AWS::RDS::DBInstance resources default to Snapshot instead. The exam likes this because the general rule and the exception point at different answers, and the snapshot keeps billing after the stack is gone.",{"question":3157,"type":933,"options":3158,"correctAnswer":3162,"explanation":3163},"A template needs the value of a database password stored in Secrets Manager, and the password must never appear in the template or in stack history. Which approach fits?",[3159,3160,3161,3162],"A String parameter with NoEcho set to true, filled in at stack creation","A Mappings entry keyed by environment","An AWS::SSM::Parameter::Value\u003CString> parameter type pointing at a SecureString","A secretsmanager dynamic reference in the resource property","A dynamic reference is resolved by CloudFormation at deploy time and the value is never stored in the template or the stack, which is precisely the requirement. A NoEcho parameter still carries the real value through the API call, mappings are plaintext in the file, and CloudFormation does not support SecureString as a template parameter type.",{"question":3165,"type":942,"options":3166,"correctAnswers":3171,"explanation":3172},"Which of the following are valid uses of a CloudFormation Mappings section? (Choose 2.)",[3167,3168,3169,3170],"Look up a Region-specific AMI ID with Fn::FindInMap","Store a database password keyed by environment name","Map an environment name to an instance type and a desired capacity","Retrieve the current value of a Parameter Store parameter",[3167,3169],"Mappings are a static lookup table inside the template, read with Fn::FindInMap, so they suit fixed per-Region or per-environment values. They are plain text in the file, which rules out secrets, and they cannot call out to another service, which is what dynamic references and SSM parameter types are for.",{"title":1023,"description":1024},"courses/aws-certified-cloudops-engineer-associate/en/domains/03-deployment-provisioning-automation/02-infrastructure-as-code/01-cloudformation-fundamentals","rJEYQ4PGxckzmumgCpLnWC9R-HvWvheALpmbsW2a35U"]