{"id":309,"date":"2019-09-04T11:43:16","date_gmt":"2019-09-04T18:43:16","guid":{"rendered":"http:\/\/blog.nillsf.com\/?p=309"},"modified":"2019-09-04T11:43:27","modified_gmt":"2019-09-04T18:43:27","slug":"creating-a-self-destructing-vm","status":"publish","type":"post","link":"https:\/\/nillsf.com\/index.php\/2019\/09\/04\/creating-a-self-destructing-vm\/","title":{"rendered":"Creating a self-destructing VM"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">A couple of weeks ago I sat in a meetup, where <a href=\"https:\/\/twitter.com\/davidstanke\">Dave Stanke <\/a>from Google mentioned he sometimes creates self-destructing VMs. I had never thought about self-destructing VMs, and decided to try this out with Azure.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What&#8217;s required for a self-destructing VM<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">First things first, we&#8217;ll need a way to create our VM. Through this creation, we&#8217;ll schedule a task in the OS to delete the VM itself. To allow the VM do this, we&#8217;ll need to give it an identity and a role binding to allow it to delete itself.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s think this through: a VM in Azure consists of a VirtualMachine object, but a NetworkInterface and Disk are also attached. That NetworkInterface exists within a VirtualNetwork &#8211; and will probably also have a PublicIP address. If we schedule the deletion in the VM itself &#8211; we won&#8217;t be able to delete the peripheral resources. Hence &#8211; I&#8217;ll be planning to create a brand new network in a brand new resource group &#8211; and instruct the VM the delete the resource group.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Second, how will we delete the VM? We could install the Azure CLI on the VM, but that takes a while to setup. So we&#8217;ll be doing a straight <a href=\"https:\/\/docs.microsoft.com\/en-us\/rest\/api\/resources\/ResourceGroups\/Delete\">REST API call.<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Third, how will we schedule the task to delete itself? There is a Linux utility called <code>at<\/code> that can schedule tasks, and even has a very &#8216;natural language&#8217; scheduling system. We could schedule our script to execute the following way: <code>at now + 15 minutes -f kill.sh<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, we need to consider the language we&#8217;ll use to create our resources. I&#8217;ve been warming up to Terraform lately, hence I&#8217;ll also execute this via Terraform. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Writing this out<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The code for this Terraform template can be found on my <a href=\"https:\/\/github.com\/NillsF\/azureScripts\/blob\/master\/self-destructing-vm.tf\">GitHub<\/a>. There&#8217;s two sections worth highlighting here:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the VM section you&#8217;ll see the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  os_profile {\n    computer_name  = \"killme\"\n    admin_username = \"nilfranadmin\"\n    custom_data = &lt;&lt;-EOF\n        #!\/bin\/bash\n        sudo apt-get install at -y\n        echo \"response=\\$(curl 'http:\/\/169.254.169.254\/metadata\/identity\/oauth2\/token?api-version=2018-02-01&amp;resource=https%3A%2F%2Fmanagement.azure.com%2F' -H Metadata:true -s)\" > killme.sh\n        echo \"access_token=\\$(echo \\$response | python -c 'import sys, json; print (json.load(sys.stdin)[\\\"access_token\\\"])')\" >> killme.sh\n        echo \"curl -X DELETE -H \\\"Authorization: Bearer \\$access_token\\\" -H \\\"Content-Type: application\/json\\\" https:\/\/management.azure.com\/${azurerm_resource_group.main.id}?api-version=2019-05-10\" >> killme.sh\n        at now + ${var.timeout} -f killme.sh\n        EOF\n  }<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The custom_data section is a script that will execute on the virtual machine at creation time. It took me some iterative development to get all the quotes and backslashes just right &#8211; just this one does the job. Essentially what this script does is it installs <code>at<\/code> &#8211; it creates a script that will get a oauth token and call the API to delete the resource group &#8211; and then schedule that script.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Another interesting section is here:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>resource \"azurerm_role_assignment\" \"test\" {\n  scope                = \"${azurerm_resource_group.main.id}\"\n  role_definition_name = \"Contributor\"\n  principal_id         = \"${lookup(azurerm_virtual_machine.main.identity[0], \"principal_id\")}\"\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This sections creates a role assignment, that gives our &#8216;virtual machine&#8217; system identity contributor access to our resource group. This enables the VM to delete itself. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion and considerations<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This template is a rather simple template that creates a VM that will delete itself. It creates it in it&#8217;s own network, and all the resources will deleted after creation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Thinking through this template after creation &#8211; I believe there are more elegant ways to solve this than have the VM delete itself. I started thinking through a mechanism using tags and an automation job (maybe a logic app) to do this in a more suitable way. More on that later, I hope you at least enjoyed this approach!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A couple of weeks ago I sat in a meetup, where Dave Stanke from Google mentioned he sometimes creates self-destructing VMs. I had never thought about self-destructing VMs, and decided to try this out with Azure. What&#8217;s required for a self-destructing VM First things first, we&#8217;ll need a way to create our VM. Through this [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[2,5],"tags":[25,8,24,16,15],"class_list":["post-309","post","type-post","status-publish","format-standard","hentry","category-azure","category-open-source","tag-automation","tag-azure","tag-iaas","tag-open-source","tag-terraform"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/309","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/comments?post=309"}],"version-history":[{"count":2,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/309\/revisions"}],"predecessor-version":[{"id":311,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/309\/revisions\/311"}],"wp:attachment":[{"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/media?parent=309"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/categories?post=309"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/tags?post=309"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}