{"id":120,"date":"2023-04-20T18:53:41","date_gmt":"2023-04-21T02:53:41","guid":{"rendered":"https:\/\/www.dumpsterfirecomputing.com\/?p=120"},"modified":"2023-04-20T18:53:42","modified_gmt":"2023-04-21T02:53:42","slug":"automagical-backups-with-azure-policy","status":"publish","type":"post","link":"https:\/\/www.dumpsterfirecomputing.com\/?p=120","title":{"rendered":"Automagical Backups with Azure Policy"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">This is a bit of a hasty post.  Been a shortened week for me, and I&#8217;m heading out of town tomorrow for my brother&#8217;s wedding.  But in conversation late today, a question was raised: &#8220;Can you add VMs to a Recovery Service Vault&#8217;s backup policy dynamically using Azure Policy and a naming pattern?&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The answer?  Sure!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s set the stage.  I have the following Recovery Services Vault, with all the default backup policies:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"75\" src=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-13-1024x75.png\" alt=\"\" class=\"wp-image-121\" srcset=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-13-1024x75.png 1024w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-13-300x22.png 300w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-13-768x56.png 768w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-13.png 1048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">I also have the following 3 VM&#8217;s:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"825\" height=\"137\" src=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-14.png\" alt=\"\" class=\"wp-image-122\" srcset=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-14.png 825w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-14-300x50.png 300w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-14-768x128.png 768w\" sizes=\"auto, (max-width: 825px) 100vw, 825px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The goal is to build an Azure Policy such that all the servers that start with AZM**** are automatically backed up to the RSV-MANAGEMENT vault using the built-in policy (ignoring that third AZS*** server).  It must remediate existing servers <em>and <\/em>capture newly built machines and add them to the vault as well.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To start, we need to locate an Azure Policy that we can use as a template for tinkering.  From the list of built-in Azure Policies, I filtered by the word &#8216;backup&#8217; and got quite a list.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"343\" src=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-15-1024x343.png\" alt=\"\" class=\"wp-image-124\" srcset=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-15-1024x343.png 1024w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-15-300x101.png 300w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-15-768x257.png 768w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-15.png 1137w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Don&#8217;t ask me why, but I used the marked policy above as my base.  It will work just fine, but the first one in the list is a simpler, cleaner policy.  Again, both of these will work (and I&#8217;m too lazy to tear it all down and rebuild it at this point).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Start by duplicating the definition &#8211; never edit a built-in policy definition (I&#8217;m not <em>that <\/em>lazy).  In the definition for the newly copied policy, we simply want to add a filter which will include servers that match a pattern.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Since coding Azure Policy isn&#8217;t something I do on a regular basis, I needed to ask Bing how to format it properly.  I stumbled on the official Microsoft documentation for the <a rel=\"noreferrer noopener\" href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/governance\/policy\/concepts\/definition-structure\" target=\"_blank\">policy Definition structure<\/a>, and that led me to the following two blocks:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"890\" height=\"779\" src=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-16.png\" alt=\"\" class=\"wp-image-125\" srcset=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-16.png 890w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-16-300x263.png 300w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-16-768x672.png 768w\" sizes=\"auto, (max-width: 890px) 100vw, 890px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">I need a way to match the pattern AZM***, and I don&#8217;t know exactly how long the server name will be (could be AZMFOO01, could be AZMFOOBAR01), so using <code>like<\/code> with the wildcard <code>*<\/code> seems to be the way to go.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"888\" height=\"403\" src=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-17.png\" alt=\"\" class=\"wp-image-126\" srcset=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-17.png 888w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-17-300x136.png 300w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-17-768x349.png 768w\" sizes=\"auto, (max-width: 888px) 100vw, 888px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This one was simple &#8211; I can just use the <code>name<\/code> properly of the resource.  So now I can put the condition and field together to come up with my pattern:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"470\" height=\"233\" src=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-18.png\" alt=\"\" class=\"wp-image-127\" srcset=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-18.png 470w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-18-300x149.png 300w\" sizes=\"auto, (max-width: 470px) 100vw, 470px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In my policy definition, notice that I added it as the first check, above the built-in condition that it must be a virtual machine.  For me, this is just easier to read &#8211; you do what works best for you.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once the definition is created, now it needs to be assigned.  I assigned my policy to the subscription (to capture any VMs built anywhere in the sub that matches the name pattern), and I also allowed the creation of a managed identity for remediation.  This created a system assigned MI and apply the appropriate permissions at the desired scope so that the policy can be enforced:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"992\" height=\"461\" src=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-19.png\" alt=\"\" class=\"wp-image-128\" srcset=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-19.png 992w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-19-300x139.png 300w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-19-768x357.png 768w\" sizes=\"auto, (max-width: 992px) 100vw, 992px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The parameters for this particular policy assignment want <code>location<\/code> and <code>backup policy<\/code> :<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"880\" height=\"314\" src=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-20.png\" alt=\"\" class=\"wp-image-129\" srcset=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-20.png 880w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-20-300x107.png 300w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-20-768x274.png 768w\" sizes=\"auto, (max-width: 880px) 100vw, 880px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This says that it will check for VM&#8217;s in <code>West US 2<\/code> only, and the properties of the <code>Backup Policy<\/code> show the built-in <code>EnhancedPolicy<\/code> in the vault I chose:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"400\" height=\"327\" src=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-21.png\" alt=\"\" class=\"wp-image-130\" srcset=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-21.png 400w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-21-300x245.png 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">With the assignment complete, I let it run a remediation task for existing VM&#8217;s that match the pattern.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"868\" height=\"787\" src=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-22.png\" alt=\"\" class=\"wp-image-131\" srcset=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-22.png 868w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-22-300x272.png 300w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-22-768x696.png 768w\" sizes=\"auto, (max-width: 868px) 100vw, 868px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In this case it found the two existing VMs that were there, and it successfully added them both to the Recovery Vault.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The last test was to build a brand new machine, named <code>AZMFOO03<\/code> and see if the policy automatically added it to the vault.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"517\" height=\"260\" src=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-23.png\" alt=\"\" class=\"wp-image-132\" srcset=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-23.png 517w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-23-300x151.png 300w\" sizes=\"auto, (max-width: 517px) 100vw, 517px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Click-Ops&#8217;d my way to getting a third VM built, waited about 10 minutes or so after the VM was built, and I now have all three of these VM&#8217;s in the Recovery Services Vault:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"667\" height=\"419\" src=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-24.png\" alt=\"\" class=\"wp-image-133\" srcset=\"https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-24.png 667w, https:\/\/www.dumpsterfirecomputing.com\/wp-content\/uploads\/2023\/04\/image-24-300x188.png 300w\" sizes=\"auto, (max-width: 667px) 100vw, 667px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Pretty slick, and pretty easy.  The hardest part, really, is just deciding which of the pattern statements to use.  If your environment has a server naming convention that segregates servers by [insert method], then this could be a way of segregating the backup vaults as well.  And by incorporating Azure Policy with a Managed Identity, we&#8217;ve now achieved an automated way of ensuring all current and future servers deployed get backed up properly.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a bit of a hasty post. Been a shortened week for me, and I&#8217;m heading out of town tomorrow for my brother&#8217;s wedding. But in conversation late today, [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,30,29],"tags":[10,32,31],"class_list":["post-120","post","type-post","status-publish","format-standard","hentry","category-azure","category-backup","category-policy","tag-azure","tag-backup","tag-policy"],"_links":{"self":[{"href":"https:\/\/www.dumpsterfirecomputing.com\/index.php?rest_route=\/wp\/v2\/posts\/120","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dumpsterfirecomputing.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dumpsterfirecomputing.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dumpsterfirecomputing.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dumpsterfirecomputing.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=120"}],"version-history":[{"count":3,"href":"https:\/\/www.dumpsterfirecomputing.com\/index.php?rest_route=\/wp\/v2\/posts\/120\/revisions"}],"predecessor-version":[{"id":135,"href":"https:\/\/www.dumpsterfirecomputing.com\/index.php?rest_route=\/wp\/v2\/posts\/120\/revisions\/135"}],"wp:attachment":[{"href":"https:\/\/www.dumpsterfirecomputing.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=120"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dumpsterfirecomputing.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=120"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dumpsterfirecomputing.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=120"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}