Skip to content

Commit

Permalink
Dynamic Folder Samples
Browse files Browse the repository at this point in the history
  • Loading branch information
lemonmojo committed Aug 14, 2018
1 parent cbc1389 commit 1ce1a94
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 0 deletions.
@@ -0,0 +1 @@
{"Name":"Dynamic Folder Export","Objects":[{"Type":"DynamicFolder","Name":"Pleasant Password","Notes":"<h2><strong>Dynamic Folder sample for Pleasant Password&nbsp;Server</strong></h2>\n\n<p>This Dynamic Folder sample for Pleasant Password&nbsp;Server supports Dynamic Credentials and Multi-Factor-Authentication (MFA).</p>\n\n<h3><strong>Setup</strong></h3>\n\n<ul>\n\t<li>Enter your &quot;Server URL&quot; in the &quot;Custom Properties&quot; section.</li>\n\t<li>Enter or assign your Pleasant Password&nbsp;Server&nbsp;credentials.</li>\n</ul>\n","CustomProperties":[{"Name":"Server URL","Type":"URL","Value":"TODO"}],"ScriptInterpreter":"python","DynamicCredentialScriptInterpreter":"python","DynamicCredentialScript":"import json\nimport requests\nimport urllib3\nfrom Tkinter import *\n\nclass TakeInput(object):\n def __init__(self, request_message):\n self.root = Tk()\n\n self.root.title('')\n self.string = ''\n\n self.frame = Frame(self.root)\n self.frame.pack()\n\n self.acceptInput(request_message)\n\n def acceptInput(self, request_message):\n r = self.frame\n\n k = Label(r, text=request_message)\n k.pack(side='left')\n self.e = Entry(r, text='Name')\n self.e.pack(side='left')\n self.e.focus_set()\n b = Button(r, text='OK', command=self.gettext)\n b.pack(side='right')\n\n def gettext(self):\n self.string = self.e.get()\n self.root.destroy()\n\n def getString(self):\n return self.string\n\n def waitForInput(self):\n self.root.lift()\n self.root.attributes('-topmost', True)\n self.root.after_idle(self.root.attributes, '-topmost', False)\n\n self.root.mainloop()\n\n\ndef show_prompt(request_message):\n msg_box = TakeInput(request_message)\n\n # loop until the user makes a decision and the window is destroyed\n\n msg_box.waitForInput()\n\n return msg_box.getString()\n\n\ndef call_token_endpoint(url, body, otp_headers):\n token_json = requests.post(url + \"/OAuth2/Token\", data=body, verify=False, headers=otp_headers)\n\n return token_json\n\n\ndef get_dynamic_credential(url, username, password, credential_id):\n urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)\n\n token_params = {\n \"grant_type\": \"password\",\n \"username\": username,\n \"password\": password\n }\n\n token_json = call_token_endpoint(url, token_params, None)\n\n if not token_json.ok:\n if \"X-Pleasant-OTP\" in token_json.headers and token_json.headers[\"X-Pleasant-OTP\"] == \"required\":\n otp_provider = token_json.headers[\"X-Pleasant-OTP-Provider\"]\n\n otp_token = show_prompt(\"Enter your OTP for MFA (\" + otp_provider + \"):\")\n\n if not otp_token:\n print >> sys.stderr, \"No token for MFA provided\"\n return \"\"\n\n otp_headers = {\n \"X-Pleasant-OTP-Provider\": otp_provider,\n \"X-Pleasant-OTP\": otp_token\n }\n\n token_json = call_token_endpoint(url, token_params, otp_headers)\n else:\n print >> sys.stderr, \"An unknown error occurred\"\n return \"\"\n\n token = json.loads(token_json.content)[\"access_token\"]\n\n headers = {\n \"Accept\": \"application/json\",\n \"Authorization\": token\n }\n\n credential_password_json = requests.get(url + \"/api/v4/rest/credential/\" + credential_id + \"/password\", headers=headers, verify=False)\n credential_password = json.loads(credential_password_json.content)\n\n credential = {\n \"Password\": credential_password\n }\n\n credential_json = json.dumps(credential)\n\n return credential_json\n \n\nprint(get_dynamic_credential(\"$CustomProperty.ServerURL$\", \"$EffectiveUsername$\", \"$EffectivePassword$\", \"$DynamicCredential.EffectiveID$\"))","Script":"import json\nimport requests\nimport urllib3\nfrom Tkinter import *\n\nclass TakeInput(object):\n def __init__(self, request_message):\n self.root = Tk()\n\n self.root.title('')\n self.string = ''\n\n self.frame = Frame(self.root)\n self.frame.pack()\n\n self.acceptInput(request_message)\n\n def acceptInput(self, request_message):\n r = self.frame\n\n k = Label(r, text=request_message)\n k.pack(side='left')\n self.e = Entry(r, text='Name')\n self.e.pack(side='left')\n self.e.focus_set()\n b = Button(r, text='OK', command=self.gettext)\n b.pack(side='right')\n\n def gettext(self):\n self.string = self.e.get()\n self.root.destroy()\n\n def getString(self):\n return self.string\n\n def waitForInput(self):\n self.root.lift()\n self.root.attributes('-topmost', True)\n self.root.after_idle(self.root.attributes, '-topmost', False)\n\n self.root.mainloop()\n\n\ndef show_prompt(request_message):\n msg_box = TakeInput(request_message)\n\n # loop until the user makes a decision and the window is destroyed\n\n msg_box.waitForInput()\n\n return msg_box.getString()\n\n\ndef convert_notes_to_html(notes):\n if notes is None:\n return \"\"\n else:\n return notes.replace(\"\\r\\n\", \"<br />\").replace(\"\\r\", \"<br />\").replace(\"\\n\", \"<br />\")\n\n\ndef create_credential(url, headers, credential):\n credential_id = credential[\"Id\"]\n credential_name = credential[\"Name\"]\n credential_url = credential[\"Url\"]\n credential_username = credential[\"Username\"]\n credential_notes = convert_notes_to_html(credential[\"Notes\"])\n credential_custom_properties = credential[\"CustomUserFields\"]\n credential_color = \"\"\n\n credential_custom_app_fields = credential.get(\"CustomApplicationFields\", None)\n\n if credential_custom_app_fields is not None:\n credential_color = credential_custom_app_fields.get(\"ForegroundColor\", \"\")\n\n credential_description = \"\"\n\n for tag in credential[\"Tags\"]:\n tag_name = tag[\"Name\"]\n credential_description += tag_name + \", \"\n\n if credential_description.endswith(\", \"):\n credential_description = credential_description[:len(credential_description) - 2]\n\n credential = {\n \"Type\": \"DynamicCredential\",\n \"ID\": credential_id,\n \"Name\": credential_name,\n \"Color\": credential_color,\n \"URL\": credential_url,\n \"Username\": credential_username,\n \"Notes\": credential_notes,\n \"Description\": credential_description,\n \"CustomProperties\": credential_custom_properties\n }\n\n return credential\n\n\ndef create_credential_group(url, headers, credential_group):\n folder_id = credential_group[\"Id\"]\n folder_name = credential_group[\"Name\"]\n folder_notes = convert_notes_to_html(credential_group[\"Notes\"])\n\n folder_objects = []\n\n for sub_credential_group in credential_group[\"Children\"]:\n folder_object = create_credential_group(url, headers, sub_credential_group)\n folder_objects.append(folder_object)\n\n for credential in credential_group[\"Credentials\"]:\n credential_object = create_credential(url, headers, credential)\n folder_objects.append(credential_object)\n\n folder = {\n \"Type\": \"Folder\",\n \"ID\": folder_id,\n \"Name\": folder_name,\n \"Notes\": folder_notes,\n \"Objects\": folder_objects\n }\n\n # No need to create the root folder\n if credential_group[\"ParentId\"] == \"00000000-0000-0000-0000-000000000000\" and folder_name == \"Root\":\n return folder_objects\n\n return folder\n\n\ndef call_token_endpoint(url, body, otp_headers):\n token_json = requests.post(url + \"/OAuth2/Token\", data=body, verify=False, headers=otp_headers)\n\n return token_json\n\n\ndef get_entries(url, username, password):\n urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)\n\n token_params = {\n \"grant_type\": \"password\",\n \"username\": username,\n \"password\": password\n }\n\n token_json = call_token_endpoint(url, token_params, None)\n\n if not token_json.ok:\n if \"X-Pleasant-OTP\" in token_json.headers and token_json.headers[\"X-Pleasant-OTP\"] == \"required\":\n otp_provider = token_json.headers[\"X-Pleasant-OTP-Provider\"]\n\n otp_token = show_prompt(\"Enter your OTP for MFA (\" + otp_provider + \"):\")\n\n if not otp_token:\n print >> sys.stderr, \"No token for MFA provided\"\n return \"\"\n\n otp_headers = {\n \"X-Pleasant-OTP-Provider\": otp_provider,\n \"X-Pleasant-OTP\": otp_token\n }\n\n token_json = call_token_endpoint(url, token_params, otp_headers)\n else:\n print >> sys.stderr, \"An unknown error occurred\"\n return \"\"\n\n token = json.loads(token_json.content)[\"access_token\"]\n\n headers = {\n \"Accept\": \"application/json\",\n \"Authorization\": token\n }\n\n credential_groups_json = requests.get(url + \"/api/v4/rest/credentialgroup\", headers=headers, verify=False)\n credential_groups = json.loads(credential_groups_json.content)\n\n store_objects = []\n\n if credential_groups is not list:\n credential_groups = [credential_groups]\n\n for credentialGroup in credential_groups:\n folder = create_credential_group(url, headers, credentialGroup)\n store_objects.extend(folder)\n\n store = {\n \"Objects\": store_objects\n }\n\n store_json = json.dumps(store)\n\n return store_json\n \n\nprint(get_entries(\"$CustomProperty.ServerURL$\", \"$EffectiveUsername$\", \"$EffectivePassword$\"))"}]}
@@ -0,0 +1 @@
{"Name":"Dynamic Folder Export","Objects":[{"Type":"DynamicFolder","Name":"Thycotic Secret Server","Description":"Dynamic Folder Sample for Secret Server","Notes":"<h2><strong>Dynamic Folder sample for Secret Server</strong></h2>\n\n<p>This Dynamic Folder sample for Thycotic Secret Server supports Dynamic Credentials and Multi-Factor-Authentication (MFA).</p>\n\n<h3><strong>Setup</strong></h3>\n\n<ul>\n\t<li>Enter your &quot;Server URL&quot; in the &quot;Custom Properties&quot; section.</li>\n\t<li>Enter or assign your Secret Server&nbsp;credentials.</li>\n\t<li>If MFA is required by your server/user, enable it by setting &quot;<span style=\"font-family:courier new,courier,monospace;\">-requiresMFA</span>&quot; to &quot;<span style=\"font-family:courier new,courier,monospace;\">$true</span>&quot; instead of &quot;<span style=\"font-family:courier new,courier,monospace;\">$false</span>&quot; in the&nbsp;last line of both scripts.</li>\n</ul>\n","CustomProperties":[{"Name":"Server URL","Type":"URL","Value":"TODO"}],"ScriptInterpreter":"powershell","DynamicCredentialScriptInterpreter":"powershell","DynamicCredentialScript":"$ErrorActionPreference = \"Stop\"\n\nfunction Is-MacOS() {\n [String]$os = $PSVersionTable.OS\n\n return $os.StartsWith(\"darwin\", [System.StringComparison]::CurrentCultureIgnoreCase)\n}\n\nfunction Run-Native([String] $command, [Array] $commandArgs) {\n $env:commandlineargumentstring=($commandArgs | %{'\"'+ ($_ -replace '(\\\\*)\"','$1$1\\\"' -replace '(\\\\*)$','$1$1') + '\"'}) -join ' ';\n return & $command --% %commandlineargumentstring%\n}\n\nfunction Show-Prompt-Mac([String] $prompt, [String] $defaultValue) {\n $command = \"/usr/bin/osascript\"\n $script = \"set resp to text returned of (display dialog \"\"$prompt\"\" default answer \"\"$defaultValue\"\" buttons {\"\"Cancel\"\", \"\"OK\"\"} default button \"\"OK\"\")\"\n $commandArgs = @( \"-e\", $script )\n\n $ret = Run-Native -command $command -commandArgs @( \"-e\", $script )\n\n return $ret\n}\n\nfunction Show-Prompt-Windows([String] $prompt, [String] $defaultValue) {\n [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null\n $ret = [Microsoft.VisualBasic.Interaction]::InputBox($prompt, \"\", $defaultValue)\n\n return $ret\n}\n\nfunction Show-Prompt([String] $prompt, [String] $defaultValue) {\n if (Is-MacOS) {\n return Show-Prompt-Mac -prompt $prompt -defaultValue $defaultValue\n } else {\n return Show-Prompt-Windows -prompt $prompt -defaultValue $defaultValue\n }\n}\n\nfunction Convert-Notes-To-HTML ($notes) {\n $notes -Replace \"\\r\\n\", \"<br />\" -Replace \"\\r\", \"<br />\" -Replace \"\\n\", \"<br />\"\n}\n\n$SLUGS_USERNAME = ( \"username\", \"licensed-to\" );\n$SLUGS_DOMAIN = ( \"domain\" );\n$SLUGS_PASSWORD = ( \"password\", \"pin-code\", \"combination\", \"license-key\", \"pin\" );\n$SLUGS_PASSPHRASE = ( \"private-key-passphrase\", \"passphrase\" );\n\nfunction Create-Credential ($restricted) {\n $restrictedItems = $restricted.items\n\n $credentialUsername = \"\"\n $credentialPassword = \"\"\n $credentialPassphrase = \"\"\n \n ForEach ($restrictedItem in $restrictedItems) {\n $restrictedItemValue = $restrictedItem.itemValue\n\n if (!$restrictedItemValue) {\n continue\n }\n\n $slug = $restrictedItem.slug\n \n if ($SLUGS_USERNAME.Contains($slug)) {\n $credentialUsername = $restrictedItemValue\n } elseif ($SLUGS_DOMAIN.Contains($slug)) {\n $credentialDomain = $restrictedItemValue\n } elseif ($SLUGS_PASSWORD.Contains($slug)) {\n $credentialPassword = $restrictedItemValue\n } elseif ($SLUGS_PASSPHRASE.Contains($slug)) {\n $credentialPassphrase = $restrictedItemValue\n }\n }\n\n if ($credentialDomain -and $credentialUsername) {\n $credentialUsername = \"$credentialDomain\\$credentialUsername\"\n }\n \n $credential = New-Object pscustomobject -Property @{\n \"Username\" = $credentialUsername;\n \"Password\" = $credentialPassword;\n \"Passphrase\" = $credentialPassphrase;\n }\n\n return $credential\n}\n\nfunction Get-Credential($url, $username, $password, $requiresMFA, $secretID) {\n $api = \"$url/api/v1\"\n $tokenRoute = \"$url/oauth2/token\";\n\n $tokenParams = @{\n grant_type = \"password\";\n username = $username;\n password = $password;\n }\n\n $headers = $null\n\n If ($requiresMFA) {\n $headers = @{\n \"OTP\" = Show-Prompt -prompt \"Enter your OTP for MFA:\"\n }\n }\n\n $tokenJSON = Invoke-WebRequest -SkipCertificateCheck -Uri $tokenRoute -Method POST -Body $tokenParams -Headers $headers\n $token = (ConvertFrom-Json $tokenJSON.Content).access_token\n\n $headers = @{\n \"Authorization\" = \"Bearer $token\"\n }\n\n $restrictedJSON = Invoke-WebRequest -SkipCertificateCheck -Uri \"$api/secrets/$secretID/restricted\" -Headers $headers -Method POST\n $restricted = (ConvertFrom-Json $restrictedJSON.Content)\n\n $credential = Create-Credential -restricted $restricted\n\n $credentialJSON = (ConvertTo-Json -InputObject $credential -Depth 100)\n \n $credentialJSON\n}\n\nGet-Credential -url \"$CustomProperty.ServerURL$\" -username \"$EffectiveUsername$\" -password \"$EffectivePassword$\" -secretID \"$DynamicCredential.EffectiveID$\" -requiresMFA $false","Script":"$ErrorActionPreference = \"Stop\"\n\nfunction Is-MacOS() {\n [String]$os = $PSVersionTable.OS\n\n return $os.StartsWith(\"darwin\", [System.StringComparison]::CurrentCultureIgnoreCase)\n}\n\nfunction Run-Native([String] $command, [Array] $commandArgs) {\n $env:commandlineargumentstring=($commandArgs | %{'\"'+ ($_ -replace '(\\\\*)\"','$1$1\\\"' -replace '(\\\\*)$','$1$1') + '\"'}) -join ' ';\n return & $command --% %commandlineargumentstring%\n}\n\nfunction Show-Prompt-Mac([String] $prompt, [String] $defaultValue) {\n $command = \"/usr/bin/osascript\"\n $script = \"set resp to text returned of (display dialog \"\"$prompt\"\" default answer \"\"$defaultValue\"\" buttons {\"\"Cancel\"\", \"\"OK\"\"} default button \"\"OK\"\")\"\n $commandArgs = @( \"-e\", $script )\n\n $ret = Run-Native -command $command -commandArgs @( \"-e\", $script )\n\n return $ret\n}\n\nfunction Show-Prompt-Windows([String] $prompt, [String] $defaultValue) {\n [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null\n $ret = [Microsoft.VisualBasic.Interaction]::InputBox($prompt, \"\", $defaultValue)\n\n return $ret\n}\n\nfunction Show-Prompt([String] $prompt, [String] $defaultValue) {\n if (Is-MacOS) {\n return Show-Prompt-Mac -prompt $prompt -defaultValue $defaultValue\n } else {\n return Show-Prompt-Windows -prompt $prompt -defaultValue $defaultValue\n }\n}\n\nfunction Convert-Notes-To-HTML ($notes) {\n $notes -Replace \"\\r\\n\", \"<br />\" -Replace \"\\r\", \"<br />\" -Replace \"\\n\", \"<br />\"\n}\n\nfunction Create-Credential ($apiURL, $secret, $folderDict) {\n $credentialID = $secret.id\n $credentialName = $secret.name\n\n $folderPath = \"\"\n \n if ($secret.folderId -and $folderDict.ContainsKey($secret.folderId)) {\n $folderPath = $folderDict[$secret.folderId]\n }\n \n $credential = New-Object pscustomobject -Property @{\n \"Type\" = \"DynamicCredential\";\n \"ID\" = $credentialID;\n \"Name\" = $credentialName;\n \"Path\" = $folderPath;\n }\n\n return $credential\n}\n\nfunction Get-Entries($url, $username, $password, $requiresMFA) {\n $api = \"$url/api/v1\"\n $tokenRoute = \"$url/oauth2/token\";\n\n $tokenParams = @{\n grant_type = \"password\";\n username = $username;\n password = $password;\n }\n\n $headers = $null\n\n If ($requiresMFA) {\n $headers = @{\n \"OTP\" = Show-Prompt -prompt \"Enter your OTP for MFA:\"\n }\n }\n\n $tokenJSON = Invoke-WebRequest -SkipCertificateCheck -Uri $tokenRoute -Method POST -Body $tokenParams -Headers $headers\n $token = (ConvertFrom-Json $tokenJSON.Content).access_token\n\n $headers = @{\n \"Authorization\" = \"Bearer $token\"\n }\n\n $foldersRequestBody = @{\n \"paging.take\" = 1000;\n }\n\n $foldersJSON = Invoke-WebRequest -SkipCertificateCheck -Uri \"$api/folders\" -Headers $headers -Body $foldersRequestBody\n $folders = (ConvertFrom-Json $foldersJSON.Content)\n\n $folderDict = @{}\n\n ForEach ($folder in $folders.records) {\n $folderDict.Add($folder.id, $folder.folderPath)\n }\n\n $secretsRequestBody = @{\n \"paging.take\" = 1000;\n }\n\n $secretsJSON = Invoke-WebRequest -SkipCertificateCheck -Uri \"$api/secrets\" -Headers $headers -Body $secretsRequestBody\n $secrets = (ConvertFrom-Json $secretsJSON.Content)\n\n $storeObjects = @()\n\n ForEach ($secret in $secrets.records) {\n $credential = Create-Credential -apiURL $api -secret $secret -folderDict $folderDict\n \n $storeObjects += $credential\n }\n\n $store = New-Object pscustomobject -Property @{\n \"Objects\" = $storeObjects;\n }\n\n $storeJSON = (ConvertTo-Json -InputObject $store -Depth 100)\n \n $storeJSON\n}\n\nGet-Entries -url \"$CustomProperty.ServerURL$\" -username \"$EffectiveUsername$\" -password \"$EffectivePassword$\" -requiresMFA $false"}]}

0 comments on commit 1ce1a94

Please sign in to comment.