{"id":1595,"date":"2020-06-13T07:29:37","date_gmt":"2020-06-13T06:29:37","guid":{"rendered":"http:\/\/www.myfatblog.co.uk\/?p=1595"},"modified":"2020-06-13T07:29:37","modified_gmt":"2020-06-13T06:29:37","slug":"the-problem-of-storing-app-credentials-in-azure-runbooks","status":"publish","type":"post","link":"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/","title":{"rendered":"The problem of storing App credentials in Azure Runbooks"},"content":{"rendered":"<h1>The problem of storing App Credentials in Azure Runbooks<\/h1>\n<p>Back when SharePoint on-premises was all the rage, there was always a need to provide a way of automating script actions for a number of reasons. Invariably this would mean that an automation server would be configured running Windows Scheduled tasks out of hours to access and process SharePoint data under the identity of a Service Account. This need has not gone away with SharePoint Online and if anything, with the advent of the Microsoft Graph the possibilities have increased tenfold along with the options for automating using App Credentials.<\/p>\n<p>For me the simplest automation in recent times has been to use Azure Runbooks, we can use PowerShell, it has a simple to use Modules library for popular modules like PNP PowerShell,we can upload our own Modules for code re-use and we can run scripts for up to 3 hours without problems. It also integrates heavily with other services such as the Azure KeyVault for credential storage. The only problem with KeyVault is that it\u2019s an additional cost and can be a little complex to setup and use, requiring Service Principals and Certificates. If we look back at how we ran our old on-premises Task Scheduler it was generally accepted that IDs and Passwords in Script files was not a good thing and the majority of people would use Windows Credential Manager to encode the credentials into safe storage against the logged on account. Luckily, we can do just such a thing with Windows Automation accounts, enabling us to share service credentials between a number of scripts\/authors.<\/p>\n<p>For the purpose of this article I\u2019m going to assume two things, both of which are well documented on the Internet, so there\u2019s no point me re-hashing them here:<\/p>\n<ol>\n<li>You have an Automation Account configured in Azure that is configured to allow a limited number of people access using Access Control.<\/li>\n<li>You have some App Credentials configured in Azure AD (A Client\/Secret pair) that you wish to call the Microsoft Graph with. These must have been granted API Permissions to the Graph. (<a href=\"https:\/\/docs.microsoft.com\/en-us\/graph\/auth-v2-service\" target=\"_blank\" rel=\"noopener noreferrer\">Section 2 in this Doc from Microsoft<\/a>)<\/li>\n<\/ol>\n<h2>Storing the App Credentials in readiness for reuse.<\/h2>\n<p>When you open your Automation Account pane in the Azure Portal, there are a number of resources down the left hand side that you\u2019ll be using, The section that we\u2019re interested in for this post is under Shared Resources. This is the section where we publish Schedules for our scripts, make modules available, and more importantly let us store and share credentials and variables between our Runbooks.<\/p>\n<p><a href=\"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9e97664.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"SNAGHTML9e97664\" src=\"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9e97664_thumb.png\" alt=\"SNAGHTML9e97664\" width=\"194\" height=\"240\" border=\"0\" \/><\/a><\/p>\n<p>When I first looked at Runbooks, I immediately jumped on Credentials and started trying to use these for my scripts, storing the App Credentials as if they were a UserName and Password. The big problem with this is that the Password is encrypted and it is very difficult to pass this into our automation calls without writing an overly complex script. The much simpler approach is to use Automation Variables instead.<\/p>\n<p>\u201cHow is that secure\u201d&#8221;?\u201d you may well ask. Well the answer to that lies in how the Automation accounts let\u2019s you declare a Variable as an Encrypted variable, for which the value is not shown in the interface once it\u2019s been committed. Whilst an author with the correct rights can obtain the value (which is kind of the point as we need to be able to pass a string to the Graph), it reduces the amount of visibility to a casual observer.<\/p>\n<p><a href=\"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9ef631d.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"SNAGHTML9ef631d\" src=\"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9ef631d_thumb.png\" alt=\"SNAGHTML9ef631d\" width=\"727\" height=\"167\" border=\"0\" \/><\/a><\/p>\n<p>To add these, simply click on the \u201c+ Add a variable\u201d at the top of the screen and first add your ClientID as a string and hit Create, then do exactly the same for your Client Secret, but this time, click on the Encrypted toggle at the bottom of the pane, then hit Create.<\/p>\n<p><a href=\"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9f31b05.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;\" title=\"SNAGHTML9f31b05\" src=\"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9f31b05_thumb.png\" alt=\"SNAGHTML9f31b05\" width=\"629\" height=\"624\" border=\"0\" \/><\/a><\/p>\n<p>You\u2019ll notice that the boxes turn purple and when you return to the Credentials screen, you can only see the ID of the ClientID and not the Secret. With those saved, we can now turn our attention to using them in the Runbook itself.<\/p>\n<h2>Consuming our Automation Variables in a Runbook<\/h2>\n<p>This really is the simple part as we use a single Azure Cmdlet to obtain our values in readiness to plug them into the Rest call to the Graph to create our token.<\/p>\n<blockquote><p><strong><em>Get-AutomationVariable<\/em><\/strong><\/p><\/blockquote>\n<pre class=\"brush: ps;\">$ClientID = get-automationvariable  -name \"OurNewClientID\"\r\n$clientSecret = get-automationvariable -name \"OurNewClientSecret\"<\/pre>\n<p>&nbsp;<\/p>\n<p>That call handles all of the decryption that we need and gives us simple string variables to inject into the Rest call to the graph (<a href=\"https:\/\/docs.microsoft.com\/en-us\/graph\/auth-v2-service#4-get-an-access-token\" target=\"_blank\" rel=\"noopener noreferrer\">detailed in section 4 of this MIcrosoft doc<\/a>) and for simplicity, in this function that I use in most of my scripts.<\/p>\n<pre class=\"brush: ps;\">function get-oAuthAccessToken()\r\n{\r\n    Param(\r\n        [Parameter(Mandatory=$true)] [String] $resource,\r\n        [Parameter(Mandatory=$true)] [String] $clientID,\r\n        [Parameter(Mandatory=$true)] [String] $clientSecret,\r\n        [Parameter(Mandatory=$true)] [String] $loginURL,\r\n        [Parameter(Mandatory=$true)] [String] $tenantDomain\r\n    )   \r\n\r\n    # Retrieve Oauth 2 access token\r\n    $body = @{grant_type=\"client_credentials\";resource=$resource;client_id=$clientID;client_secret=$clientSecret}\r\n    $oauthToken = Invoke-RestMethod -Method Post -Uri $loginURL\/$tenantdomain\/oauth2\/token?api-version=1.0 -Body $body\r\n\r\n    return $oauthToken\r\n}<\/pre>\n<p>Call this using your new ClientID and ClientSecret values, along with the following EndPoints:<\/p>\n<pre class=\"brush: ps;\">#oAuth Token Endpoints.\r\n$resourceAPI = \"https:\/\/graph.microsoft.com\"\r\n$loginURL = \"https:\/\/login.windows.net\"\r\n$apiPrefix = \"https:\/\/graph.microsoft.com\/v1.0\/\"\r\n$tenantDomain = \"&lt;&lt;yourdomain&gt;&gt;.onmicrosoft.com\"<\/pre>\n<p>&nbsp;<\/p>\n<p>I hope this proves useful.<\/p>\n<p>Paul.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The problem of storing App Credentials in Azure Runbooks Back when SharePoint on-premises was all the rage, there was always a need to provide a way of automating script actions for a number of reasons. Invariably this would mean that an automation server would be configured running Windows Scheduled tasks out of hours to access &hellip; <\/p>\n<p><a class=\"more-link btn\" href=\"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/\">Continue reading<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"footnotes":""},"categories":[16],"tags":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>The problem of storing App credentials in Azure Runbooks - Blog of an overweight SharePoint addict<\/title>\n<meta name=\"description\" content=\"Back when SharePoint on-premises was all the rage, storing script passwords was always an issue. Luckily Azure Runbooks makes storing App Credentials easy\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"The problem of storing App credentials in Azure Runbooks - Blog of an overweight SharePoint addict\" \/>\n<meta property=\"og:description\" content=\"Back when SharePoint on-premises was all the rage, storing script passwords was always an issue. Luckily Azure Runbooks makes storing App Credentials easy\" \/>\n<meta property=\"og:url\" content=\"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog of an overweight SharePoint addict\" \/>\n<meta property=\"article:published_time\" content=\"2020-06-13T06:29:37+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9e97664_thumb.png\" \/>\n<meta name=\"author\" content=\"Cimares\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@cimares\" \/>\n<meta name=\"twitter:site\" content=\"@cimares\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Cimares\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/\",\"url\":\"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/\",\"name\":\"The problem of storing App credentials in Azure Runbooks - Blog of an overweight SharePoint addict\",\"isPartOf\":{\"@id\":\"http:\/\/www.myfatblog.co.uk\/#website\"},\"primaryImageOfPage\":{\"@id\":\"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/#primaryimage\"},\"image\":{\"@id\":\"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/#primaryimage\"},\"thumbnailUrl\":\"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9e97664_thumb.png\",\"datePublished\":\"2020-06-13T06:29:37+00:00\",\"dateModified\":\"2020-06-13T06:29:37+00:00\",\"author\":{\"@id\":\"http:\/\/www.myfatblog.co.uk\/#\/schema\/person\/55ae8f6885bb5b8390dad001f3da83c6\"},\"description\":\"Back when SharePoint on-premises was all the rage, storing script passwords was always an issue. Luckily Azure Runbooks makes storing App Credentials easy\",\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/#primaryimage\",\"url\":\"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9e97664_thumb.png\",\"contentUrl\":\"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9e97664_thumb.png\",\"width\":194,\"height\":240},{\"@type\":\"WebSite\",\"@id\":\"http:\/\/www.myfatblog.co.uk\/#website\",\"url\":\"http:\/\/www.myfatblog.co.uk\/\",\"name\":\"Blog of an overweight SharePoint addict\",\"description\":\"The rantings of a (not so) food obsessed IT consultant!\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"http:\/\/www.myfatblog.co.uk\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"http:\/\/www.myfatblog.co.uk\/#\/schema\/person\/55ae8f6885bb5b8390dad001f3da83c6\",\"name\":\"Cimares\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"http:\/\/www.myfatblog.co.uk\/#\/schema\/person\/image\/\",\"url\":\"http:\/\/www.myfatblog.co.uk\/images\/BlogImages\/About_D057\/TopOfTheWorld.jpg\",\"contentUrl\":\"http:\/\/www.myfatblog.co.uk\/images\/BlogImages\/About_D057\/TopOfTheWorld.jpg\",\"caption\":\"Cimares\"},\"sameAs\":[\"http:\/\/www.myfatblog.co.uk\"],\"url\":\"http:\/\/www.myfatblog.co.uk\/index.php\/author\/reginald\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"The problem of storing App credentials in Azure Runbooks - Blog of an overweight SharePoint addict","description":"Back when SharePoint on-premises was all the rage, storing script passwords was always an issue. Luckily Azure Runbooks makes storing App Credentials easy","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/","og_locale":"en_US","og_type":"article","og_title":"The problem of storing App credentials in Azure Runbooks - Blog of an overweight SharePoint addict","og_description":"Back when SharePoint on-premises was all the rage, storing script passwords was always an issue. Luckily Azure Runbooks makes storing App Credentials easy","og_url":"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/","og_site_name":"Blog of an overweight SharePoint addict","article_published_time":"2020-06-13T06:29:37+00:00","og_image":[{"url":"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9e97664_thumb.png"}],"author":"Cimares","twitter_card":"summary_large_image","twitter_creator":"@cimares","twitter_site":"@cimares","twitter_misc":{"Written by":"Cimares","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/","url":"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/","name":"The problem of storing App credentials in Azure Runbooks - Blog of an overweight SharePoint addict","isPartOf":{"@id":"http:\/\/www.myfatblog.co.uk\/#website"},"primaryImageOfPage":{"@id":"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/#primaryimage"},"image":{"@id":"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/#primaryimage"},"thumbnailUrl":"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9e97664_thumb.png","datePublished":"2020-06-13T06:29:37+00:00","dateModified":"2020-06-13T06:29:37+00:00","author":{"@id":"http:\/\/www.myfatblog.co.uk\/#\/schema\/person\/55ae8f6885bb5b8390dad001f3da83c6"},"description":"Back when SharePoint on-premises was all the rage, storing script passwords was always an issue. Luckily Azure Runbooks makes storing App Credentials easy","inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"http:\/\/www.myfatblog.co.uk\/index.php\/2020\/06\/the-problem-of-storing-app-credentials-in-azure-runbooks\/#primaryimage","url":"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9e97664_thumb.png","contentUrl":"http:\/\/www.myfatblog.co.uk\/wp-content\/uploads\/2020\/06\/SNAGHTML9e97664_thumb.png","width":194,"height":240},{"@type":"WebSite","@id":"http:\/\/www.myfatblog.co.uk\/#website","url":"http:\/\/www.myfatblog.co.uk\/","name":"Blog of an overweight SharePoint addict","description":"The rantings of a (not so) food obsessed IT consultant!","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"http:\/\/www.myfatblog.co.uk\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"http:\/\/www.myfatblog.co.uk\/#\/schema\/person\/55ae8f6885bb5b8390dad001f3da83c6","name":"Cimares","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"http:\/\/www.myfatblog.co.uk\/#\/schema\/person\/image\/","url":"http:\/\/www.myfatblog.co.uk\/images\/BlogImages\/About_D057\/TopOfTheWorld.jpg","contentUrl":"http:\/\/www.myfatblog.co.uk\/images\/BlogImages\/About_D057\/TopOfTheWorld.jpg","caption":"Cimares"},"sameAs":["http:\/\/www.myfatblog.co.uk"],"url":"http:\/\/www.myfatblog.co.uk\/index.php\/author\/reginald\/"}]}},"_links":{"self":[{"href":"http:\/\/www.myfatblog.co.uk\/index.php\/wp-json\/wp\/v2\/posts\/1595"}],"collection":[{"href":"http:\/\/www.myfatblog.co.uk\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.myfatblog.co.uk\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.myfatblog.co.uk\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/www.myfatblog.co.uk\/index.php\/wp-json\/wp\/v2\/comments?post=1595"}],"version-history":[{"count":2,"href":"http:\/\/www.myfatblog.co.uk\/index.php\/wp-json\/wp\/v2\/posts\/1595\/revisions"}],"predecessor-version":[{"id":1597,"href":"http:\/\/www.myfatblog.co.uk\/index.php\/wp-json\/wp\/v2\/posts\/1595\/revisions\/1597"}],"wp:attachment":[{"href":"http:\/\/www.myfatblog.co.uk\/index.php\/wp-json\/wp\/v2\/media?parent=1595"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.myfatblog.co.uk\/index.php\/wp-json\/wp\/v2\/categories?post=1595"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.myfatblog.co.uk\/index.php\/wp-json\/wp\/v2\/tags?post=1595"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}