From d505f67318016d384481b4d9fea40bf0def648a8 Mon Sep 17 00:00:00 2001 From: Fizcko <20943860+Fizcko@users.noreply.github.com> Date: Fri, 19 Jan 2024 14:06:36 +0100 Subject: [PATCH] =?UTF-8?q?Add=20service=20connection=20=C2=AB=20Vault=20I?= =?UTF-8?q?nteraction=20=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build_job.ps1 | 7 ++- dist/kv_read/task.json | 42 +++++++++------- dist/tool_create_file/task.json | 4 +- overview.md | 20 +++++--- package.json | 3 +- src/common/request.ts | 84 ++++++++++++++++++++++++++++---- src/kv_read/kv_read.ts | 11 ++++- vss-extension.json | 85 ++++++++++++++++++++++++++++++++- 8 files changed, 217 insertions(+), 39 deletions(-) diff --git a/build_job.ps1 b/build_job.ps1 index 819336e..1ce0501 100644 --- a/build_job.ps1 +++ b/build_job.ps1 @@ -36,6 +36,11 @@ catch{ $subProjects = $jsonVssConfigFile.contributions Foreach ($subProject in $subProjects){ $currentProjectName = $subProject.properties.name + + if ($currentProjectName -eq "VaultInteractionEndpoint") { + continue + } + $subProjectPath = Join-Path -Path $rootPath -ChildPath $subProject.properties.name $subCommunFolderPath = Join-Path -Path $subProjectPath -ChildPath $commonFolderName $pathTaskConfigFile = Join-Path -Path $subProjectPath -ChildPath "task.json" @@ -104,4 +109,4 @@ Remove-Item -Path "$pathCommon" -Recurse -Force # Start build Set-Location $rootPath -tfx extension create --manifest-globs vss-extension.json \ No newline at end of file +npx tfx extension create --manifest-globs vss-extension.json \ No newline at end of file diff --git a/dist/kv_read/task.json b/dist/kv_read/task.json index 76ad79a..4865148 100644 --- a/dist/kv_read/task.json +++ b/dist/kv_read/task.json @@ -11,9 +11,9 @@ ], "author": "Fizcko", "version": { - "Major": 4, + "Major": 5, "Minor": 0, - "Patch": 2 + "Patch": 0 }, "instanceNameFormat": "Vault - Read KV secrets", "groups": [ @@ -34,6 +34,24 @@ } ], "inputs": [ + { + "name": "strAuthType", + "type": "pickList", + "label": "Authentication Method", + "defaultValue": "clientToken", + "required": true, + "helpMarkDown": "Specifies the authentication method.", + "options": { + "approle": "AppRole", + "azure": "Azure", + "clientToken": "Client Token", + "ldap": "LDAP", + "radius": "Radius", + "serviceConnection": "Service connection", + "userpass": "Username \u0026 Password" + }, + "groupName": "grpServer" + }, { "name": "strUrl", "type": "string", @@ -41,6 +59,7 @@ "defaultValue": "https://myurl", "required": true, "helpMarkDown": "Specifies the url of the Vault server (http or https).", + "visibleRule": "strAuthType != serviceConnection", "groupName": "grpServer" }, { @@ -104,21 +123,12 @@ "groupName": "grpServer" }, { - "name": "strAuthType", - "type": "pickList", - "label": "Authentication Method", - "defaultValue": "clientToken", + "name": "serviceConnectionName", + "type": "connectedService:VaultInteractionEndpoint", + "label": "Vault Interaction Service Connection", "required": true, - "helpMarkDown": "Specifies the authentication method.", - "options": { - "approle": "AppRole", - "azure": "Azure", - "clientToken": "Client Token", - "ldap": "LDAP", - "radius": "Radius", - "userpass": "Username \u0026 Password" - }, - "groupName": "grpAuth" + "groupName": "grpAuth", + "visibleRule": "strAuthType = serviceConnection" }, { "name": "strAuthPath", diff --git a/dist/tool_create_file/task.json b/dist/tool_create_file/task.json index df1273a..5009b4a 100644 --- a/dist/tool_create_file/task.json +++ b/dist/tool_create_file/task.json @@ -11,9 +11,9 @@ ], "author": "Fizcko", "version": { - "Major": 4, + "Major": 5, "Minor": 0, - "Patch": 2 + "Patch": 0 }, "instanceNameFormat": "Tool - Create a File", "groups": [ diff --git a/overview.md b/overview.md index 7281908..39f41d8 100644 --- a/overview.md +++ b/overview.md @@ -3,12 +3,14 @@ ## Authentication methods available - - AppRole + - AppRole * - Azure - - Client Token - - LDAP - - Radius - - Username & Password + - Client Token * + - LDAP * + - Radius * + - Username & Password * + +\* Available to setup in a service connection ## Utilities @@ -96,11 +98,15 @@ Parameters : ## Release note +### v5.0.0 +- Add service connection « Vault Interaction » + This allows you to set the Vault URL and Authentication methods (AppRole, Client Token, LDAP, Radius, Username & Password) directly in a service connection. + ### v4.0.2 -- Remove secret value from output log +- Remove secret value from output log. ### v4.0.1 -- Disable proxy when useProxy is none +- Disable proxy when useProxy is none. ### v4.0.0 - Upgrading tasks to Node 10 diff --git a/package.json b/package.json index 2947fe4..2386c52 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "devDependencies": { "@types/node": "10.17.39", "@types/q": "^1.5.1", - "mocha": "^6.1.4" + "mocha": "^6.1.4", + "tfx-cli": "0.8.1" } } diff --git a/src/common/request.ts b/src/common/request.ts index 493f388..c6bb70e 100644 --- a/src/common/request.ts +++ b/src/common/request.ts @@ -128,8 +128,22 @@ export function requestVault(requestedUrl: string, ignoreCertificateChecks: bool export function getToken(strRequestTimeout): Promise { return new Promise((resolve, reject) => { - var strUrl = tl.getInput('strUrl', true); + var strUrl; + var serverEndpointAuth; + var overloadFromServiceConnection = false; + var strAuthType = tl.getInput('strAuthType', true); + + if(strAuthType == "serviceConnection"){ + var serviceConnectionValues = tl.getInput('serviceConnectionName',true); + strUrl = tl.getEndpointUrl(serviceConnectionValues, false); + serverEndpointAuth = tl.getEndpointAuthorization(serviceConnectionValues, false); + strAuthType = serverEndpointAuth["parameters"]["authType"]; + overloadFromServiceConnection = true; + } + else{ + strUrl = tl.getInput('strUrl', true); + } var ignoreCertificateChecks = tl.getBoolInput('ignoreCertificateChecks', true); var authUrl = null; @@ -145,8 +159,17 @@ export function getToken(strRequestTimeout): Promise { apiURL = "/v1/auth/" + strAuthPath + "/login"; } - var strRoleID = tl.getInput('strRoleID', true); - var strSecretID = tl.getInput('strSecretID', true); + var strRoleID; + var strSecretID; + + if(overloadFromServiceConnection){ + strRoleID = serverEndpointAuth["parameters"]["username"]; + strSecretID = serverEndpointAuth["parameters"]["password"]; + } + else{ + strRoleID = tl.getInput('strRoleID', true); + strSecretID = tl.getInput('strSecretID', true); + } authUrl = url.resolve(strUrl,apiURL); bodyData = JSON.stringify({ @@ -190,7 +213,15 @@ export function getToken(strRequestTimeout): Promise { break; case "clientToken": console.log("[INFO] Authentication Method : 'Client Token'"); - var strToken = tl.getInput('strToken', true); + + var strToken; + + if(overloadFromServiceConnection){ + strToken = serverEndpointAuth["parameters"]["password"]; + } + else{ + strToken = tl.getInput('strToken', true); + } resolve(strToken); break; case "ldap": @@ -200,8 +231,19 @@ export function getToken(strRequestTimeout): Promise { if(strAuthPath){ apiURL = "/v1/auth/" + strAuthPath + "/login/"; } - var strUsername = tl.getInput('strUsername', true); - var strPassword = tl.getInput('strPassword', true); + + var strUsername; + var strPassword; + + if(overloadFromServiceConnection){ + strUsername = serverEndpointAuth["parameters"]["username"]; + strPassword = serverEndpointAuth["parameters"]["password"]; + } + else{ + strUsername = tl.getInput('strUsername', true); + strPassword = tl.getInput('strPassword', true); + } + authUrl = url.resolve(strUrl,apiURL + strUsername); bodyData = JSON.stringify({ password: strPassword @@ -214,8 +256,19 @@ export function getToken(strRequestTimeout): Promise { if(strAuthPath){ apiURL = "/v1/auth/" + strAuthPath + "/login/"; } - var strUsername = tl.getInput('strUsername', true); - var strPassword = tl.getInput('strPassword', true); + + var strUsername; + var strPassword; + + if(overloadFromServiceConnection){ + strUsername = serverEndpointAuth["parameters"]["username"]; + strPassword = serverEndpointAuth["parameters"]["password"]; + } + else{ + strUsername = tl.getInput('strUsername', true); + strPassword = tl.getInput('strPassword', true); + } + authUrl = url.resolve(strUrl,apiURL + strUsername); bodyData = JSON.stringify({ password: strPassword @@ -228,8 +281,19 @@ export function getToken(strRequestTimeout): Promise { if(strAuthPath){ apiURL = "/v1/auth/" + strAuthPath + "/login/"; } - var strUsername = tl.getInput('strUsername', true); - var strPassword = tl.getInput('strPassword', true); + + var strUsername; + var strPassword; + + if(overloadFromServiceConnection){ + strUsername = serverEndpointAuth["parameters"]["username"]; + strPassword = serverEndpointAuth["parameters"]["password"]; + } + else{ + strUsername = tl.getInput('strUsername', true); + strPassword = tl.getInput('strPassword', true); + } + authUrl = url.resolve(strUrl,apiURL + strUsername); bodyData = JSON.stringify({ password: strPassword diff --git a/src/kv_read/kv_read.ts b/src/kv_read/kv_read.ts index f27713c..93a0b1a 100644 --- a/src/kv_read/kv_read.ts +++ b/src/kv_read/kv_read.ts @@ -10,7 +10,16 @@ async function run() { tl.setResourcePath(path.join(__dirname, 'task.json')); - var strUrl = tl.getInput('strUrl', true); + var strUrl; + var strAuthType = tl.getInput('strAuthType', true); + if(strAuthType == "serviceConnection"){ + var serviceConnectionValues = tl.getInput('serviceConnectionName',true); + strUrl = tl.getEndpointUrl(serviceConnectionValues, false); + } + else{ + strUrl = tl.getInput('strUrl', true); + } + var ignoreCertificateChecks = tl.getBoolInput('ignoreCertificateChecks', true); var useProxy = tl.getInput('useProxy', true); var strRequestTimeout = tl.getInput('strRequestTimeout', false); diff --git a/vss-extension.json b/vss-extension.json index 54f85fe..e649b43 100644 --- a/vss-extension.json +++ b/vss-extension.json @@ -2,7 +2,7 @@ "manifestVersion": 1, "id": "azure-devops-vault-interaction", "name": "Vault Interaction", - "version": "4.0.2", + "version": "5.0.0", "publisher": "Fizcko", "public": true, "targets": [ @@ -75,6 +75,89 @@ "properties": { "name": "dist/tool_create_file" } + }, + { + "id": "80369ded-37c8-4ffb-a38c-1df62356736a", + "description": "Service Connection for Vault Interaction", + "type": "ms.vss-endpoint.service-endpoint-type", + "targets": [ + "ms.vss-endpoint.endpoint-types" + ], + "properties": { + "name": "VaultInteractionEndpoint", + "displayName": "Vault Interaction", + "url": { + "displayName": "Vault URL", + "value": "https://127.0.0.1:8002", + "helpText": "Enter the location of your Vault Server (e.q https://127.0.0.1:8002)." + }, + "authenticationSchemes": [ + { + "type": "ms.vss-endpoint.endpoint-auth-scheme-basic", + "inputDescriptors": [ + { + "id": "authType", + "name": "Authentication Method", + "description": "Specifies the authentication method.", + "inputMode": "combo", + "isConfidential": false, + "validation": { + "isRequired": true, + "dataType": "string" + }, + "values": { + "inputId": "authTypeValues", + "defaultValue": "userpass", + "possibleValues": [ + { + "value": "approle", + "displayValue": "AppRole" + }, + { + "value": "clientToken", + "displayValue": "Client Token" + }, + { + "value": "LDAP", + "displayValue": "LDAP" + }, + { + "value": "radius", + "displayValue": "Radius" + }, + { + "value": "userpass", + "displayValue": "Username \u0026 Password" + } + ] + } + }, + { + "id": "username", + "name": "Username/Role ID", + "description": "Enter username (LDAP, Radius, Username \u0026 Password auth) or Role ID (AppRole auth). For Client Token authentication enter a random value.", + "inputMode": "textbox", + "isConfidential": false, + "validation": { + "isRequired": true, + "dataType": "string" + } + }, + { + "id": "password", + "name": "Password/Token/SecretID", + "description": "Enter password (LDAP, Radius, Username \u0026 Password auth), Client Token (Client Token auth) or Secret ID (AppRole auth)", + "inputMode": "passwordbox", + "isConfidential": true, + "validation": { + "isRequired": true, + "dataType": "string" + } + } + ] + } + ] + } } ] }