Forked from SQLDBAWithABeard/Secrets_Management_with_PowerShell.ipynb
Created
February 17, 2024 01:57
-
-
Save jimbrig/f544893422f641442ccbc6abc81a3308 to your computer and use it in GitHub Desktop.
Using Secrets Management
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "metadata": { | |
| "kernelspec": { | |
| "name": ".net-powershell", | |
| "display_name": ".NET (PowerShell)" | |
| }, | |
| "language_info": { | |
| "name": "PowerShell", | |
| "version": "7.0", | |
| "mimetype": "text/x-powershell", | |
| "file_extension": ".ps1", | |
| "pygments_lexer": "powershell" | |
| } | |
| }, | |
| "nbformat_minor": 2, | |
| "nbformat": 4, | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "# Secrets Management with PowerShell\r\n", | |
| "\r\n", | |
| "You can use the `Microsoft.PowerShell.SecretManagement` module introduced [here](https://devblogs.microsoft.com/powershell/secrets-management-development-release/) to store and retrieve secrets with PowerShell.\r\n", | |
| "\r\n", | |
| "## Installation\r\n", | |
| "\r\n", | |
| "You install it from the PowerShell Gallery using" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "8b771475-0092-4e02-97be-5f08e558a584" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "Install-Module Microsoft.PowerShell.SecretManagement -AllowPrerelease" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "f2570663-c521-4af5-acdc-075b77901879" | |
| }, | |
| "outputs": [], | |
| "execution_count": null | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "You need to use the `-PreRelease` flag at the moment as it is in preview. \r\n", | |
| "\r\n", | |
| "## Local Vault\r\n", | |
| "\r\n", | |
| "It will come with a built in local key vault for you to use. You can see this with `Get-SecretVault`" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "c13bb6ab-3ee2-41db-a22d-f5b8a0a23443" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "Get-SecretVault" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "021b34e8-b115-4042-8f6e-b5790e2ac1e4" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "display_data", | |
| "data": { | |
| "text/html": "\r\n<div>\r\n <div id='dotnet-interactive-this-cell-47344.572a81723abb42f59f29d82c009aa537' style='display: none'>\r\n The below script needs to be able to find the current output cell; this is an easy method to get it.\r\n </div>\r\n <script type='text/javascript'>\r\n// ensure `require` is available globally\r\nif (typeof require !== typeof Function || typeof require.config !== typeof Function) {\r\n let require_script = document.createElement('script');\r\n require_script.setAttribute('src', 'https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js');\r\n require_script.setAttribute('type', 'text/javascript');\r\n require_script.onload = function () {\r\n loadDotnetInteractiveApi();\r\n };\r\n\r\n document.getElementsByTagName('head')[0].appendChild(require_script);\r\n}\r\nelse {\r\n loadDotnetInteractiveApi();\r\n}\r\n\r\nasync function probeAddresses(probingAddresses) {\r\n function timeout(ms, promise) {\r\n return new Promise(function (resolve, reject) {\r\n setTimeout(function () {\r\n reject(new Error('timeout'))\r\n }, ms)\r\n promise.then(resolve, reject)\r\n })\r\n }\r\n\r\n if (Array.isArray(probingAddresses)) {\r\n for (let i = 0; i < probingAddresses.length; i++) {\r\n\r\n let rootUrl = probingAddresses[i];\r\n\r\n if (!rootUrl.endsWith('/')) {\r\n rootUrl = `${rootUrl}/`;\r\n }\r\n\r\n try {\r\n let response = await timeout(1000, fetch(`${rootUrl}discovery`, {\r\n method: 'POST',\r\n cache: 'no-cache',\r\n mode: 'cors',\r\n timeout: 1000,\r\n headers: {\r\n 'Content-Type': 'text/plain'\r\n },\r\n body: probingAddresses[i]\r\n }));\r\n\r\n if (response.status == 200) {\r\n return rootUrl;\r\n }\r\n }\r\n catch (e) { }\r\n }\r\n }\r\n}\r\n\r\nfunction loadDotnetInteractiveApi() {\r\n probeAddresses([\"http://172.28.176.1:1003/\", \"http://172.29.48.1:1003/\", \"http://192.168.1.69:1003/\", \"http://127.0.0.1:1003/\"])\r\n .then((root) => {\r\n // use probing to find host url and api resources\r\n // load interactive helpers and language services\r\n let dotnet_require = require.config({\r\n context: '47344.572a81723abb42f59f29d82c009aa537',\r\n paths: {\r\n 'dotnet-interactive': `${root}resources`\r\n }\r\n }) || require;\r\n if (!window.dotnet_require) {\r\n window.dotnet_require = dotnet_require;\r\n }\r\n \r\n dotnet_require([\r\n 'dotnet-interactive/dotnet-interactive'\r\n ],\r\n function (dotnet) {\r\n dotnet.init(window);\r\n },\r\n function (error) {\r\n console.log(error);\r\n }\r\n );\r\n })\r\n .catch(error => {console.log(error);});\r\n }\r\n </script>\r\n</div>" | |
| }, | |
| "metadata": {} | |
| }, | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "\r\n" | |
| }, | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "Name ModuleName ImplementingType\r\n" | |
| }, | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "---- ---------- ----------------\r\n" | |
| }, | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "BuiltInLocalVault \r\n" | |
| }, | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "\r\n" | |
| } | |
| ], | |
| "execution_count": 1 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "## Adding Secrets\r\n", | |
| "\r\n", | |
| "You can add a secret to the vault with `Set-Secret` It does not give any output" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "76441636-a0f4-4d42-a62d-f144876e54c6" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "Set-Secret -Name MyAwesomeSecret -Secret 'BeardsAreAwesome'" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "07f92208-f1c9-413f-9d94-31db17a9e440" | |
| }, | |
| "outputs": [], | |
| "execution_count": 5 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "If you dont want to have your secret in the code (A recommended practice! Otherwise, why would need a key vault) You can prompt for user input with `Read-Host`" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "45961345-4c04-49b0-b7fd-40433b88c5cc" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "$Secret = Read-Host \"tell me your secret\" -AsSecureString\r\n", | |
| "Set-Secret -Name ASecretFromMe -SecureStringSecret $Secret" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "2c3ecd6e-14f4-43a2-8093-f941e13d7224" | |
| }, | |
| "outputs": [], | |
| "execution_count": 8 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "or with `Get-Credential`" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "969eb143-687e-4e82-ba7b-d14a77bc4e83" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "$Secret = Get-Credential\r\n", | |
| "Set-Secret -Name $Secret.UserName -SecureStringSecret $Secret.Password" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "76b9f0c5-9296-4fb6-9393-78b9bba4c817" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "\r\n" | |
| }, | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "\u001b[95mPowerShell credential request\u001b[0m\r\n" | |
| }, | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "Enter your credentials.\r\n" | |
| }, | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "\r\n" | |
| } | |
| ], | |
| "execution_count": 9 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "## Retrieving Secrets\r\n", | |
| "\r\n", | |
| "You can retrieve secrets with `Get-Secret`" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "b0cd5642-8611-4408-9bdb-d5be5287be22" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "Get-Secret -Name MyAwesomeSecret" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "76cee814-f78d-4e7f-b0e9-dd3855baae52" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "System.Security.SecureString\r\n" | |
| } | |
| ], | |
| "execution_count": 6 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "This returns a SecureString which you can use in your code.\r\n", | |
| "\r\n", | |
| "You can return the value in plain text with the `-AsPlainText` switch. (Please be careful doing this and understand where this may be logged)" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "075fb2ba-5a46-46b9-8ab3-9b9dbc7943dd" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "Get-Secret -Name ASecretFromMe -AsPlainText\r\n", | |
| "" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "5b9bbb26-0713-4ae4-b3cd-90f812be7efe" | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "text": "I_got_my_first_tattoo_in_my_30s\r\n", | |
| "output_type": "stream" | |
| } | |
| ], | |
| "execution_count": 1 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "You can create PsCredentialObjects using the secrets" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "0c89e3d6-2ba2-4eae-a42b-96b8256109f5" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "$secretName = 'ASurprisingFact'\r\n", | |
| "$Secret = Get-Secret -Name $secretName\r\n", | |
| "$credential = New-Object System.Management.Automation.PSCredential ($secretName, $secret)\r\n", | |
| "$credential" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "737267bc-43c2-462f-8546-30734db6b4a6" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "\r\n" | |
| }, | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "UserName Password\r\n" | |
| }, | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "-------- --------\r\n" | |
| }, | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "ASurprisingFact System.Security.SecureString\r\n" | |
| }, | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "\r\n" | |
| } | |
| ], | |
| "execution_count": 14 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "You can always reveal the password in a PSCredential object with" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "aaf43927-e380-42be-a39b-adf3ea5f08af" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "$credential.GetNetworkCredential().Password" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "f2cc774b-5893-4d4f-ad10-61c444893363" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "Isaac_Newton_invented_the_cat_door\r\n" | |
| } | |
| ], | |
| "execution_count": 16 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "## Updating Secrets\r\n", | |
| "\r\n", | |
| "You update secrets using `Set-Secret`" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "bfd433d8-8605-4fc6-abea-9d5e9c09151e" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "Set-Secret -Name ASurprisingFact -Secret 'A house cat can reach speeds of up to 30mph'\r\n", | |
| "\r\n", | |
| "$secretName = 'ASurprisingFact'\r\n", | |
| "$Secret = Get-Secret -Name $secretName\r\n", | |
| "$credential = New-Object System.Management.Automation.PSCredential ($secretName, $secret)\r\n", | |
| "$credential.GetNetworkCredential().Password" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "a8af74a8-ae74-4060-ad70-e865a1a7a3df" | |
| }, | |
| "outputs": [ | |
| { | |
| "output_type": "stream", | |
| "name": "stdout", | |
| "text": "A house cat can reach speeds of up to 30mph\r\n" | |
| } | |
| ], | |
| "execution_count": 20 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "## Listing Secrets\r\n", | |
| "\r\n", | |
| "You can list the secrets in the vault with `Get-SecretInfo` You can see the type of secret and the secrets int he vault that the user has access to." | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "68902267-5dc1-4b3f-852b-6ab8d1f4ede2" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "Get-SecretInfo" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "a543de1d-f0f9-42f3-8c15-408cbe27e601" | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "text": "\r\n", | |
| "output_type": "stream" | |
| }, | |
| { | |
| "name": "stdout", | |
| "text": "Name Type VaultName\r\n", | |
| "output_type": "stream" | |
| }, | |
| { | |
| "name": "stdout", | |
| "text": "---- ---- ---------\r\n", | |
| "output_type": "stream" | |
| }, | |
| { | |
| "name": "stdout", | |
| "text": "ASecretFromMe SecureString BuiltInLocalVault\r\n", | |
| "output_type": "stream" | |
| }, | |
| { | |
| "name": "stdout", | |
| "text": "ASurpringFact String BuiltInLocalVault\r\n", | |
| "output_type": "stream" | |
| }, | |
| { | |
| "name": "stdout", | |
| "text": "ASurprisingFact String BuiltInLocalVault\r\n", | |
| "output_type": "stream" | |
| }, | |
| { | |
| "name": "stdout", | |
| "text": "MyAwesomeSecret String BuiltInLocalVault\r\n", | |
| "output_type": "stream" | |
| }, | |
| { | |
| "name": "stdout", | |
| "text": "\r\n", | |
| "output_type": "stream" | |
| } | |
| ], | |
| "execution_count": 2 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "## Removing Secrets\r\n", | |
| "\r\n", | |
| "You can remove secrets with `Remove-Secret` As you can see above, I mistyped when creating this notebook and created a secret called `ASurpringFact` Lets remove that one, you have to specify the vaultname\r\n", | |
| "\r\n", | |
| "" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "6813da34-10d8-4be3-8204-ab5a95856255" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "Remove-Secret ASurpringFact -Vault BuiltInLocalVault " | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "5f60b601-0420-47b3-a7eb-6bfad5c78e5a" | |
| }, | |
| "outputs": [], | |
| "execution_count": 3 | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "source": [ | |
| "and when we check it is gone" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "b25cea41-1969-4fae-8f35-00695e36c0a8" | |
| } | |
| }, | |
| { | |
| "cell_type": "code", | |
| "source": [ | |
| "Get-SecretInfo" | |
| ], | |
| "metadata": { | |
| "azdata_cell_guid": "1bc4d3b9-0309-47ba-9ea0-ba62522b1415" | |
| }, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "text": "\r\n", | |
| "output_type": "stream" | |
| }, | |
| { | |
| "name": "stdout", | |
| "text": "Name Type VaultName\r\n", | |
| "output_type": "stream" | |
| }, | |
| { | |
| "name": "stdout", | |
| "text": "---- ---- ---------\r\n", | |
| "output_type": "stream" | |
| }, | |
| { | |
| "name": "stdout", | |
| "text": "ASecretFromMe SecureString BuiltInLocalVault\r\n", | |
| "output_type": "stream" | |
| }, | |
| { | |
| "name": "stdout", | |
| "text": "ASurprisingFact String BuiltInLocalVault\r\n", | |
| "output_type": "stream" | |
| }, | |
| { | |
| "name": "stdout", | |
| "text": "MyAwesomeSecret String BuiltInLocalVault\r\n", | |
| "output_type": "stream" | |
| }, | |
| { | |
| "name": "stdout", | |
| "text": "\r\n", | |
| "output_type": "stream" | |
| } | |
| ], | |
| "execution_count": 4 | |
| } | |
| ] | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment