diff --git a/build_job.ps1 b/build_job.ps1 index 819336e..ce24066 100644 --- a/build_job.ps1 +++ b/build_job.ps1 @@ -88,20 +88,8 @@ Foreach ($subProject in $subProjects){ Write-Error "[ERROR] $($_.Exception.Message)" exit } - - # Copy common functions - $excludeFolders = ("dist/tool_create_file") - if($currentProjectName -NotIn $excludeFolders){ - if(Test-Path $subCommunFolderPath){ - Remove-Item -Path "$subCommunFolderPath" -Recurse | Out-Null - } - Copy-Item -Path "$pathCommon" -Destination "$subProjectPath" -Recurse -Force - } } -# Delete common folder -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 diff --git a/dist/kv_read/task.json b/dist/kv_read/task.json index 02b1a0f..5f64a2f 100644 --- a/dist/kv_read/task.json +++ b/dist/kv_read/task.json @@ -1,315 +1,334 @@ { - "id": "807A85D5-8AC9-4B8C-A0FC-1B233BB2BCC6", - "name": "VaultReadKV", - "friendlyName": "Vault - Read KV secrets", - "description": "This extension provide the ability to read KV secrets from HashiCorp Vault and load them into variables.", - "helpMarkDown": "", - "category": "Utility", - "visibility": [ - "Build", - "Release" - ], - "author": "Fizcko", - "version": { - "Major": 4, - "Minor": 0, - "Patch": 1 - }, - "instanceNameFormat": "Vault - Read KV secrets", - "groups": [ - { - "name": "grpServer", - "displayName": "Vault Server", - "isExpanded": true - }, - { - "name": "grpAuth", - "displayName": "Authentication method", - "isExpanded": true - }, - { - "name": "grpKVSettings", - "displayName": "KV Settings", - "isExpanded": true - } - ], - "inputs": [ - { - "name": "strUrl", - "type": "string", - "label": "Vault URL", - "defaultValue": "https://myurl", - "required": true, - "helpMarkDown": "Specifies the url of the Vault server (http or https).", - "groupName": "grpServer" - }, - { - "name": "ignoreCertificateChecks", - "type": "boolean", - "label": "Ignore certificate checks", - "defaultValue": "false", - "required": true, - "helpMarkDown": "Ignore errors from certificate checks.", - "groupName": "grpServer" - }, - { - "name": "useProxy", - "type": "radio", - "label": "Use proxy", - "defaultValue": "none", - "required": true, - "options": { - "none": "none", - "http": "http", - "https": "https" - }, - "helpMarkDown": "Specifies is the requests have to use a proxy.", - "groupName": "grpServer" - }, - { - "name": "strProxyHost", - "type": "string", - "label": "Host", - "defaultValue": "", - "required": true, - "helpMarkDown": "Hostname or IP address of the proxy.", - "groupName": "grpServer", - "visibleRule": "useProxy = http || useProxy = https" - }, - { - "name": "strProxyPort", - "type": "string", - "label": "Port", - "defaultValue": "", - "required": true, - "helpMarkDown": "Port of the proxy.", - "groupName": "grpServer", - "visibleRule": "useProxy = http || useProxy = https" - }, - { - "name": "strNamespaces", - "type": "string", - "label": "Namespaces", - "required": false, - "helpMarkDown": "The name of the namespaces to request.", - "groupName": "grpServer" - }, - { - "name": "strRequestTimeout", - "type": "string", - "label": "Request timeout", - "defaultValue": "", - "required": false, - "helpMarkDown": "A number specifying the socket timeout in milliseconds. This will set the timeout before the socket is connected.", - "groupName": "grpServer" - }, - { - "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", - "userpass": "Username \u0026 Password" - }, - "groupName": "grpAuth" - }, - { - "name": "strAuthPath", - "type": "string", - "label": "Path", - "defaultValue": "", - "required": false, - "helpMarkDown": "Change default path of the chosen Authentication Method.", - "groupName": "grpAuth", - "visibleRule": "strAuthType = approle || strAuthType = azure || strAuthType = ldap || strAuthType = radius" - }, - { - "name": "strToken", - "type": "string", - "label": "Client Token", - "defaultValue": "", - "required": true, - "helpMarkDown": "Client Token for authentication.", - "groupName": "grpAuth", - "visibleRule": "strAuthType = clientToken" - }, - { - "name": "strUsername", - "type": "string", - "label": "Username", - "required": true, - "helpMarkDown": "Username for authentication.", - "groupName": "grpAuth", - "visibleRule": "strAuthType = ldap || strAuthType = radius || strAuthType = userpass" - }, - { - "name": "strPassword", - "type": "string", - "label": "Password", - "required": true, - "helpMarkDown": "Password for authentication.", - "groupName": "grpAuth", - "visibleRule": "strAuthType = ldap || strAuthType = radius || strAuthType = userpass" - }, - { - "name": "strRoleID", - "type": "string", - "label": "Role ID", - "required": true, - "helpMarkDown": "Role ID for AppRole authentication.", - "groupName": "grpAuth", - "visibleRule": "strAuthType = approle" - }, - { - "name": "strSecretID", - "type": "string", - "label": "Secret ID", - "required": true, - "helpMarkDown": "Secret ID for AppRole authentication.", - "groupName": "grpAuth", - "visibleRule": "strAuthType = approle" - }, - { - "name": "strRole", - "type": "string", - "label": "Role", - "required": true, - "helpMarkDown": "Name of the role against which the login is being attempted.", - "groupName": "grpAuth", - "visibleRule": "strAuthType = azure" - }, - { - "name": "strJWT", - "type": "string", - "label": "JWT", - "required": true, - "helpMarkDown": "Signed JSON Web Token (JWT) from Azure MSI.", - "groupName": "grpAuth", - "visibleRule": "strAuthType = azure" - }, - { - "name": "strSubscriptionID", - "type": "string", - "label": "Subscription ID", - "required": false, - "helpMarkDown": "The subscription ID for the machine that generated the MSI token. This information can be obtained through instance metadata.", - "groupName": "grpAuth", - "visibleRule": "strAuthType = azure" - }, - { - "name": "strResourceGroupName", - "type": "string", - "label": "Resource group name", - "required": false, - "helpMarkDown": "The resource group for the machine that generated the MSI token. This information can be obtained through instance metadata.", - "groupName": "grpAuth", - "visibleRule": "strAuthType = azure" - }, - { - "name": "strVmName", - "type": "string", - "label": "VM name", - "required": false, - "helpMarkDown": "The virtual machine name for the machine that generated the MSI token. This information can be obtained through instance metadata. If \u0027VMSS name\u0027 is provided, this value is ignored.", - "groupName": "grpAuth", - "visibleRule": "strAuthType = azure" - }, - { - "name": "strVmssName", - "type": "string", - "label": "VMSS name", - "required": false, - "helpMarkDown": "The virtual machine scale set name for the machine that generated the MSI token. This information can be obtained through instance metadata.", - "groupName": "grpAuth", - "visibleRule": "strAuthType = azure" - }, - { - "name": "strKVEnginePath", - "type": "string", - "label": "KV engine path", - "defaultValue": "secret", - "required": true, - "helpMarkDown": "Specifies the path of the KV engine.", - "groupName": "grpKVSettings" - }, - { - "name": "kvVersion", - "type": "radio", - "label": "KV version", - "defaultValue": "v2", - "required": true, - "options": { - "v1": "v1", - "v2": "v2" - }, - "helpMarkDown": "Specifies the version of the KV secrets engine.", - "groupName": "grpKVSettings" - }, - { - "name": "strSecretPath", - "type": "string", - "label": "Secret path", - "defaultValue": "/", - "required": false, - "helpMarkDown": "Specifies the path of the secrets to read. For a folder exploration add a \u0027/\u0027 at the end of the path.", - "groupName": "grpKVSettings" - }, - { - "name": "strPrefixType", - "type": "pickList", - "label": "Prefix type", - "defaultValue": "custom", - "required": true, - "helpMarkDown": "Specifies prefix type of the variables. Variables will be named PREFIX_VariableName.", - "options": { - "none": "None", - "custom": "Custom", - "folder": "Folder path" - }, - "groupName": "grpKVSettings" - }, - { - "name": "strVariablePrefix", - "type": "string", - "label": "Variable prefix", - "defaultValue": "", - "required": false, - "helpMarkDown": "Specifies prefix of the variables. Variables will be named PREFIX_VariableName.", - "groupName": "grpKVSettings", - "visibleRule": "strPrefixType = custom" - }, - { - "name": "replaceCR", - "type": "boolean", - "label": "Replace carriage return by a token", - "defaultValue": "false", - "required": true, - "helpMarkDown": "For secrets with multilines you have to replace the carriage return by a token because Azure Devops do not manage multiline secrets", - "groupName": "grpKVSettings" - }, - { - "name": "strCRPrefix", - "type": "string", - "label": "Carriage return token", - "defaultValue": "", - "required": true, - "helpMarkDown": "For secrets with multilines you have to replace the carriage return by a token because Azure Devops do not manage multiline secrets", - "groupName": "grpKVSettings", - "visibleRule": "replaceCR = true" - } - ], - "execution": { - "Node10": { - "target": "kv_read.js", - "argumentFormat": "", - "workingDirectory": "" - } - } -} + "id": "807A85D5-8AC9-4B8C-A0FC-1B233BB2BCC6", + "name": "VaultReadKV", + "friendlyName": "Vault - Read KV secrets", + "description": "This extension provide the ability to read KV secrets from HashiCorp Vault and load them into variables.", + "helpMarkDown": "", + "category": "Utility", + "visibility": [ + "Build", + "Release" + ], + "author": "Fizcko", + "version": { + "Major": 4, + "Minor": 0, + "Patch": 1 + }, + "instanceNameFormat": "Vault - Read KV secrets", + "groups": [ + { + "name": "grpServer", + "displayName": "Vault Server", + "isExpanded": true + }, + { + "name": "grpAuth", + "displayName": "Authentication method", + "isExpanded": true + }, + { + "name": "grpKVSettings", + "displayName": "KV Settings", + "isExpanded": true + } + ], + "inputs": [ + { + "name": "strUrl", + "type": "string", + "label": "Vault URL", + "defaultValue": "https://myurl", + "required": true, + "helpMarkDown": "Specifies the url of the Vault server (http or https).", + "groupName": "grpServer" + }, + { + "name": "ignoreCertificateChecks", + "type": "boolean", + "label": "Ignore certificate checks", + "defaultValue": "false", + "required": true, + "helpMarkDown": "Ignore errors from certificate checks.", + "groupName": "grpServer" + }, + { + "name": "useProxy", + "type": "radio", + "label": "Use proxy", + "defaultValue": "none", + "required": true, + "options": { + "none": "none", + "http": "http", + "https": "https" + }, + "helpMarkDown": "Specifies is the requests have to use a proxy.", + "groupName": "grpServer" + }, + { + "name": "strProxyHost", + "type": "string", + "label": "Host", + "defaultValue": "", + "required": true, + "helpMarkDown": "Hostname or IP address of the proxy.", + "groupName": "grpServer", + "visibleRule": "useProxy = http || useProxy = https" + }, + { + "name": "strProxyPort", + "type": "string", + "label": "Port", + "defaultValue": "", + "required": true, + "helpMarkDown": "Port of the proxy.", + "groupName": "grpServer", + "visibleRule": "useProxy = http || useProxy = https" + }, + { + "name": "strNamespaces", + "type": "string", + "label": "Namespaces", + "required": false, + "helpMarkDown": "The name of the namespaces to request.", + "groupName": "grpServer" + }, + { + "name": "strRequestTimeout", + "type": "string", + "label": "Request timeout", + "defaultValue": "", + "required": false, + "helpMarkDown": "A number specifying the socket timeout in milliseconds. This will set the timeout before the socket is connected.", + "groupName": "grpServer" + }, + { + "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", + "userpass": "Username \u0026 Password" + }, + "groupName": "grpAuth" + }, + { + "name": "strAuthPath", + "type": "string", + "label": "Path", + "defaultValue": "", + "required": false, + "helpMarkDown": "Change default path of the chosen Authentication Method.", + "groupName": "grpAuth", + "visibleRule": "strAuthType = approle || strAuthType = azure || strAuthType = ldap || strAuthType = radius" + }, + { + "name": "strToken", + "type": "string", + "label": "Client Token", + "defaultValue": "", + "required": true, + "helpMarkDown": "Client Token for authentication.", + "groupName": "grpAuth", + "visibleRule": "strAuthType = clientToken" + }, + { + "name": "strUsername", + "type": "string", + "label": "Username", + "required": true, + "helpMarkDown": "Username for authentication.", + "groupName": "grpAuth", + "visibleRule": "strAuthType = ldap || strAuthType = radius || strAuthType = userpass" + }, + { + "name": "strPassword", + "type": "string", + "label": "Password", + "required": true, + "helpMarkDown": "Password for authentication.", + "groupName": "grpAuth", + "visibleRule": "strAuthType = ldap || strAuthType = radius || strAuthType = userpass" + }, + { + "name": "strRoleID", + "type": "string", + "label": "Role ID", + "required": true, + "helpMarkDown": "Role ID for AppRole authentication.", + "groupName": "grpAuth", + "visibleRule": "strAuthType = approle" + }, + { + "name": "strSecretID", + "type": "string", + "label": "Secret ID", + "required": true, + "helpMarkDown": "Secret ID for AppRole authentication.", + "groupName": "grpAuth", + "visibleRule": "strAuthType = approle" + }, + { + "name": "strRole", + "type": "string", + "label": "Role", + "required": true, + "helpMarkDown": "Name of the role against which the login is being attempted.", + "groupName": "grpAuth", + "visibleRule": "strAuthType = azure" + }, + { + "name": "strJWT", + "type": "string", + "label": "JWT", + "required": true, + "helpMarkDown": "Signed JSON Web Token (JWT) from Azure MSI.", + "groupName": "grpAuth", + "visibleRule": "strAuthType = azure" + }, + { + "name": "strSubscriptionID", + "type": "string", + "label": "Subscription ID", + "required": false, + "helpMarkDown": "The subscription ID for the machine that generated the MSI token. This information can be obtained through instance metadata.", + "groupName": "grpAuth", + "visibleRule": "strAuthType = azure" + }, + { + "name": "strResourceGroupName", + "type": "string", + "label": "Resource group name", + "required": false, + "helpMarkDown": "The resource group for the machine that generated the MSI token. This information can be obtained through instance metadata.", + "groupName": "grpAuth", + "visibleRule": "strAuthType = azure" + }, + { + "name": "strVmName", + "type": "string", + "label": "VM name", + "required": false, + "helpMarkDown": "The virtual machine name for the machine that generated the MSI token. This information can be obtained through instance metadata. If \u0027VMSS name\u0027 is provided, this value is ignored.", + "groupName": "grpAuth", + "visibleRule": "strAuthType = azure" + }, + { + "name": "strVmssName", + "type": "string", + "label": "VMSS name", + "required": false, + "helpMarkDown": "The virtual machine scale set name for the machine that generated the MSI token. This information can be obtained through instance metadata.", + "groupName": "grpAuth", + "visibleRule": "strAuthType = azure" + }, + { + "name": "strKVEnginePath", + "type": "string", + "label": "KV engine path", + "defaultValue": "secret", + "required": true, + "helpMarkDown": "Specifies the path of the KV engine.", + "groupName": "grpKVSettings" + }, + { + "name": "kvVersion", + "type": "radio", + "label": "KV version", + "defaultValue": "v2", + "required": true, + "options": { + "v1": "v1", + "v2": "v2" + }, + "helpMarkDown": "Specifies the version of the KV secrets engine.", + "groupName": "grpKVSettings" + }, + { + "name": "strSecretPath", + "type": "string", + "label": "Secret path", + "defaultValue": "/", + "required": false, + "helpMarkDown": "Specifies the path of the secrets to read. For a folder exploration add a \u0027/\u0027 at the end of the path.", + "groupName": "grpKVSettings" + }, + { + "name": "strPrefixType", + "type": "pickList", + "label": "Prefix type", + "defaultValue": "custom", + "required": true, + "helpMarkDown": "Specifies prefix type of the variables. Variables will be named PREFIX_VariableName.", + "options": { + "none": "None", + "custom": "Custom", + "folder": "Folder path" + }, + "groupName": "grpKVSettings" + }, + { + "name": "strVariablePrefix", + "type": "string", + "label": "Variable prefix", + "defaultValue": "", + "required": false, + "helpMarkDown": "Specifies prefix of the variables. Variables will be named PREFIX_VariableName.", + "groupName": "grpKVSettings", + "visibleRule": "strPrefixType = custom" + }, + { + "name": "replaceCR", + "type": "boolean", + "label": "Replace carriage return by a token", + "defaultValue": "false", + "required": true, + "helpMarkDown": "For secrets with multilines you have to replace the carriage return by a token because Azure Devops do not manage multiline secrets", + "groupName": "grpKVSettings" + }, + { + "name": "strCRPrefix", + "type": "string", + "label": "Carriage return token", + "defaultValue": "", + "required": true, + "helpMarkDown": "For secrets with multilines you have to replace the carriage return by a token because Azure Devops do not manage multiline secrets", + "groupName": "grpKVSettings", + "visibleRule": "replaceCR = true" + }, + { + "name": "objectSplit", + "type": "boolean", + "label": "Split Arrays/Dict", + "defaultValue": true, + "required": true, + "helpMarkDown": "For secrets stored as a array or dict, this will seperate them via .0 notation OR key.key notation", + "groupName": "grpKVSettings" + }, + { + "name": "objectSeperator", + "type": "string", + "label": "For secrets within a embedded dictionary, this will be used to join the parts together", + "defaultValue": ".", + "required": true, + "helpMarkDown": "For secrets within a embedded dictionary, this will be used to join the parts together using the symbol key.0.test", + "groupName": "grpKVSettings", + "visibleRule": "objectSplit = true" + } + ], + "execution": { + "Node10": { + "target": "kv_read.js", + "argumentFormat": "", + "workingDirectory": "" + } + } +} \ No newline at end of file diff --git a/dist/tool_create_file/task.json b/dist/tool_create_file/task.json index 31010e6..ad33af5 100644 --- a/dist/tool_create_file/task.json +++ b/dist/tool_create_file/task.json @@ -1,118 +1,118 @@ -{ - "id": "81152B68-7A9D-4471-8579-4CDA672AC509", - "name": "ToolCreateFile", - "friendlyName": "Tool - Create a File", - "description": "Provide the ability to create a file and perform an action on his content.", - "helpMarkDown": "", - "category": "Utility", - "visibility": [ - "Build", - "Release" - ], - "author": "Fizcko", - "version": { - "Major": 4, - "Minor": 0, - "Patch": 1 - }, - "instanceNameFormat": "Tool - Create a File", - "groups": [ - { - "name": "groupSettings", - "displayName": "Settings", - "isExpanded": true - } - ], - "inputs": [ - { - "name": "targetDirectory", - "type": "filePath", - "label": "Target directory", - "defaultValue": "$(System.DefaultWorkingDirectory)", - "required": true, - "helpMarkDown": "Directory to save the file.", - "groupName": "groupSettings" - }, - { - "name": "targetName", - "type": "string", - "label": "File name", - "defaultValue": "myCert.pem", - "required": true, - "helpMarkDown": "Enter the file name with the extension.", - "groupName": "groupSettings" - }, - { - "name": "fileContent", - "type": "multiLine", - "label": "File Content", - "defaultValue": "", - "required": true, - "helpMarkDown": "Enter the content of the file.", - "groupName": "groupSettings" - }, - { - "name": "fileEncoding", - "type": "pickList", - "label": "Encoding", - "defaultValue": "utf8", - "required": true, - "helpMarkDown": "Specifies the file encoding. More defails in NodeJS documentation (Buffers and Character Encodings).", - "groupName": "groupSettings", - "options": { - "ascii": "ASCII", - "utf8": "UTF8", - "utf16le": "BigEndianUTF32", - "ucs2": "UCS-2 (Alias of UTF-16LE)", - "base64": "Base64 encoding", - "latin1": "Latin-1", - "binary": "Binary (Latin-1)", - "hex": "HEX" - } - }, - { - "name": "actionType", - "type": "pickList", - "label": "Action to perform", - "defaultValue": "none", - "required": true, - "helpMarkDown": "Choose an action to perform on the file content.", - "groupName": "groupSettings", - "options": { - "none": "No action", - "replaceToken": "Replace token by a new line", - "decodeBase64": "Decode from base64" - } - }, - { - "name": "actionToken", - "type": "string", - "label": "Token to replace", - "defaultValue": "", - "required": true, - "helpMarkDown": "Enter the token to replace by a new line.", - "groupName": "groupSettings", - "visibleRule": "actionType = replaceToken" - }, - { - "name": "actionNewLineType", - "type": "pickList", - "label": "New line type", - "defaultValue": "crlf", - "required": true, - "helpMarkDown": "Choose the new line type", - "groupName": "groupSettings", - "options": { - "cr": "Carriage Return (CR, \\r)", - "lf": "Line Feed (LF, \\n)", - "crlf": "CR followed by LF (CRLF, \\r\\n)" - }, - "visibleRule": "actionType = replaceToken" - } - ], - "execution": { - "Node10": { - "target": "tool_create_file.js" - } - } -} +{ + "id": "81152B68-7A9D-4471-8579-4CDA672AC509", + "name": "ToolCreateFile", + "friendlyName": "Tool - Create a File", + "description": "Provide the ability to create a file and perform an action on his content.", + "helpMarkDown": "", + "category": "Utility", + "visibility": [ + "Build", + "Release" + ], + "author": "Fizcko", + "version": { + "Major": 4, + "Minor": 0, + "Patch": 1 + }, + "instanceNameFormat": "Tool - Create a File", + "groups": [ + { + "name": "groupSettings", + "displayName": "Settings", + "isExpanded": true + } + ], + "inputs": [ + { + "name": "targetDirectory", + "type": "filePath", + "label": "Target directory", + "defaultValue": "$(System.DefaultWorkingDirectory)", + "required": true, + "helpMarkDown": "Directory to save the file.", + "groupName": "groupSettings" + }, + { + "name": "targetName", + "type": "string", + "label": "File name", + "defaultValue": "myCert.pem", + "required": true, + "helpMarkDown": "Enter the file name with the extension.", + "groupName": "groupSettings" + }, + { + "name": "fileContent", + "type": "multiLine", + "label": "File Content", + "defaultValue": "", + "required": true, + "helpMarkDown": "Enter the content of the file.", + "groupName": "groupSettings" + }, + { + "name": "fileEncoding", + "type": "pickList", + "label": "Encoding", + "defaultValue": "utf8", + "required": true, + "helpMarkDown": "Specifies the file encoding. More defails in NodeJS documentation (Buffers and Character Encodings).", + "groupName": "groupSettings", + "options": { + "ascii": "ASCII", + "utf8": "UTF8", + "utf16le": "BigEndianUTF32", + "ucs2": "UCS-2 (Alias of UTF-16LE)", + "base64": "Base64 encoding", + "latin1": "Latin-1", + "binary": "Binary (Latin-1)", + "hex": "HEX" + } + }, + { + "name": "actionType", + "type": "pickList", + "label": "Action to perform", + "defaultValue": "none", + "required": true, + "helpMarkDown": "Choose an action to perform on the file content.", + "groupName": "groupSettings", + "options": { + "none": "No action", + "replaceToken": "Replace token by a new line", + "decodeBase64": "Decode from base64" + } + }, + { + "name": "actionToken", + "type": "string", + "label": "Token to replace", + "defaultValue": "", + "required": true, + "helpMarkDown": "Enter the token to replace by a new line.", + "groupName": "groupSettings", + "visibleRule": "actionType = replaceToken" + }, + { + "name": "actionNewLineType", + "type": "pickList", + "label": "New line type", + "defaultValue": "crlf", + "required": true, + "helpMarkDown": "Choose the new line type", + "groupName": "groupSettings", + "options": { + "cr": "Carriage Return (CR, \\r)", + "lf": "Line Feed (LF, \\n)", + "crlf": "CR followed by LF (CRLF, \\r\\n)" + }, + "visibleRule": "actionType = replaceToken" + } + ], + "execution": { + "Node10": { + "target": "tool_create_file.js" + } + } +} \ No newline at end of file diff --git a/src/common/utils.ts b/src/common/utils.ts deleted file mode 100644 index eff59d2..0000000 --- a/src/common/utils.ts +++ /dev/null @@ -1,54 +0,0 @@ -import tl = require('azure-pipelines-task-lib/task'); - -export function exportJSONValues(obj: any, prefix: string, replaceCR: boolean, strCRPrefix: string): Promise { - - // Source https://raw.githubusercontent.com/geeklearningio/gl-vsts-tasks-variables/master/Common/Node/expandJObject.ts - return new Promise(async (resolve, reject) => { - - try{ - - var typeArray: string[] =["string", "number", "boolean"]; - - if (obj instanceof Array) { - if(prefix != ""){ - prefix = prefix + "_"; - } - else{ - prefix = ""; - } - for (var i = 0; i < obj.length; i++) { - var element = obj[i]; - await exportJSONValues(element, prefix + i.toString(), replaceCR, strCRPrefix); - } - } - else if (typeArray.indexOf(typeof obj) > -1){ - var objValue = typeArray.indexOf(typeof obj)>0 ? obj.toString() : obj; - if(replaceCR){ - objValue = objValue.replace(/(?:\r\n|[\r\n])/g,strCRPrefix); - } - tl.setVariable(prefix, objValue, true); - console.log("[INFO] Injecting variable : " + prefix + ", value : " + objValue); - } - else{ - if(prefix != ""){ - prefix = prefix + "_"; - } - else{ - prefix = ""; - } - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - var element = obj[key]; - await exportJSONValues(element, prefix + key, replaceCR, strCRPrefix); - } - } - } - - resolve(true); - - } catch (err) { - reject("Error when exporting values. " + err); - } - - }); -} \ No newline at end of file diff --git a/src/common/request.ts b/src/kv_read/common/request.ts similarity index 100% rename from src/common/request.ts rename to src/kv_read/common/request.ts diff --git a/src/kv_read/common/utils.ts b/src/kv_read/common/utils.ts new file mode 100644 index 0000000..9bb48f4 --- /dev/null +++ b/src/kv_read/common/utils.ts @@ -0,0 +1,83 @@ +import tl = require('azure-pipelines-task-lib/task'); + +// export function exportJSONValues(obj: any, prefix: string, replaceCR: boolean, strCRPrefix: string): Promise { +export function exportJSONValues(obj: any, prefix: string, keyName: string, replaceCR: boolean, strCRPrefix: string, objectSplit: boolean, objectSeperator: string): Promise { + + // Source https://raw.githubusercontent.com/geeklearningio/gl-vsts-tasks-variables/master/Common/Node/expandJObject.ts + return new Promise(async (resolve, reject) => { + + try{ + + var typeArray: string[] =["string", "number", "boolean"]; + + if (obj instanceof Array && objectSplit) { + for (var i = 0; i < obj.length; i++) { + var element = obj[i]; + if (keyName == null || keyName == ""){ + await exportJSONValues(element, prefix,i.toString(), replaceCR, strCRPrefix, objectSplit, objectSeperator); + } else { + await exportJSONValues(element, prefix,[keyName,i.toString()].join(objectSeperator), replaceCR, strCRPrefix, objectSplit, objectSeperator); + } + } + } + //If object split is false, treat array as a full object to support full array subsitution + else if (obj instanceof Array && !objectSplit) { + // add prefix to keyName on start if prefix is not null + if(prefix != ""){ + keyName = prefix + "_" + keyName; + } + var jsonObjectValue = JSON.stringify(obj); + if(replaceCR){ + objValue = jsonObjectValue.replace(/(?:\r\n|[\r\n])/g,strCRPrefix); + } + tl.setVariable(keyName, jsonObjectValue, true); + console.log("[INFO] Injecting variable : " + keyName + ", value : " + jsonObjectValue); + } + else if (typeArray.indexOf(typeof obj) > -1){ + // add prefix to keyName on start if prefix is not null + if(prefix != ""){ + keyName = prefix + "_" + keyName; + } + var objValue = typeArray.indexOf(typeof obj)>0 ? obj.toString() : obj; + if(replaceCR){ + objValue = objValue.replace(/(?:\r\n|[\r\n])/g,strCRPrefix); + } + tl.setVariable(keyName, objValue, true); + console.log("[INFO] Injecting variable : " + keyName + ", value : " + objValue); + } + else{ + if ((keyName != null && keyName != "") && !objectSplit ){ + // add prefix to keyName on start if prefix is not null + if(prefix != ""){ + keyName = prefix + "_" + keyName; + } + var jsonObjectValue = JSON.stringify(obj); + if(replaceCR){ + objValue = jsonObjectValue.replace(/(?:\r\n|[\r\n])/g,strCRPrefix); + } + tl.setVariable(keyName, jsonObjectValue, true); + console.log("[INFO] Injecting variable : " + keyName + ", value : " + jsonObjectValue); + + } + else { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + var element = obj[key]; + if (keyName == null || keyName == ""){ + await exportJSONValues(element, prefix,key, replaceCR, strCRPrefix, objectSplit, objectSeperator); + } else { + await exportJSONValues(element, prefix,[keyName,key].join(objectSeperator), replaceCR, strCRPrefix, objectSplit, objectSeperator); + } + } + } + } + } + + resolve(true); + + } catch (err) { + reject("Error when exporting values. " + err); + } + + }); +} \ No newline at end of file diff --git a/src/kv_read/kv_read.ts b/src/kv_read/kv_read.ts index f27713c..2474162 100644 --- a/src/kv_read/kv_read.ts +++ b/src/kv_read/kv_read.ts @@ -22,6 +22,8 @@ async function run() { var strVariablePrefix = tl.getInput('strVariablePrefix', false); var replaceCR = tl.getBoolInput('replaceCR', true); var strNamespaces = tl.getInput('strNamespaces', false); + var objectSplit = tl.getBoolInput('objectSplit', true); + var objectSeperator = tl.getInput('objectSeperator', false); if(replaceCR){ var strCRPrefix = tl.getInput('strCRPrefix', true); @@ -42,6 +44,9 @@ async function run() { if(!strNamespaces){ strNamespaces = ""; } + if(!objectSeperator){ + objectSeperator = "."; + } if(isNaN(Number(strRequestTimeout))){ throw new Error("The field 'Request timeout' is not a number."); } @@ -61,13 +66,15 @@ async function run() { console.log("[INFO] KV version : '" + kvVersion + "'"); console.log("[INFO] Secret path : '" + strSecretPath + "'"); console.log("[INFO] Variable prefix : '" + strVariablePrefix + "'"); + console.log("[INFO] Variable Object Split : '" + objectSplit + "'"); + console.log("[INFO] Variable Object Seperator : '" + objectSeperator + "'"); if(replaceCR){ console.log("[INFO] All carriage return will be replaced by: '" + strCRPrefix + "'"); } console.log(" "); if(strSecretPath.match(/.*\/$/)){ - browseEngineAndGetSecrets(kvVersion, strUrl, ignoreCertificateChecks, strRequestTimeout, token, strKVEnginePath, strSecretPath, strPrefixType, strVariablePrefix, replaceCR, strCRPrefix).then(function(result) { + browseEngineAndGetSecrets(kvVersion, strUrl, ignoreCertificateChecks, strRequestTimeout, token, strKVEnginePath, strSecretPath, strPrefixType, strVariablePrefix, replaceCR, strCRPrefix, objectSplit, objectSeperator).then(function(result) { tl.setResult(tl.TaskResult.Succeeded, "Wrapping successfull."); }).catch(function(err) { tl.setResult(tl.TaskResult.Failed, err); @@ -75,7 +82,7 @@ async function run() { }); } else{ - getSecrets(kvVersion, strUrl, ignoreCertificateChecks, strRequestTimeout, token, strKVEnginePath, strSecretPath, strPrefixType, strVariablePrefix, replaceCR, strCRPrefix).then(function(result) { + getSecrets(kvVersion, strUrl, ignoreCertificateChecks, strRequestTimeout, token, strKVEnginePath, strSecretPath, strPrefixType, strVariablePrefix, replaceCR, strCRPrefix, objectSplit, objectSeperator).then(function(result) { tl.setResult(tl.TaskResult.Succeeded, "Wrapping successfull."); }).catch(function(err) { tl.setResult(tl.TaskResult.Failed, err); @@ -94,7 +101,7 @@ async function run() { } -async function browseEngineAndGetSecrets(kvVersion, strUrl, ignoreCertificateChecks, strRequestTimeout, token, strKVEnginePath, strSecretPath, strPrefixType, strVariablePrefix, replaceCR, strCRPrefix){ +async function browseEngineAndGetSecrets(kvVersion, strUrl, ignoreCertificateChecks, strRequestTimeout, token, strKVEnginePath, strSecretPath, strPrefixType, strVariablePrefix, replaceCR, strCRPrefix, objectSplit, objectSeperator){ return new Promise(async (resolve, reject) => { @@ -134,10 +141,10 @@ async function browseEngineAndGetSecrets(kvVersion, strUrl, ignoreCertificateChe if(resultJSON.data.keys[i].match(/.*\/$/)){ - await browseEngineAndGetSecrets(kvVersion, strUrl, ignoreCertificateChecks, strRequestTimeout, token, strKVEnginePath, newStrSecretPath, strPrefixType, strVariablePrefix, replaceCR, strCRPrefix); + await browseEngineAndGetSecrets(kvVersion, strUrl, ignoreCertificateChecks, strRequestTimeout, token, strKVEnginePath, newStrSecretPath, strPrefixType, strVariablePrefix, replaceCR, strCRPrefix, objectSplit, objectSeperator); } else{ - await getSecrets(kvVersion, strUrl, ignoreCertificateChecks, strRequestTimeout, token, strKVEnginePath, newStrSecretPath, strPrefixType, strVariablePrefix, replaceCR, strCRPrefix); + await getSecrets(kvVersion, strUrl, ignoreCertificateChecks, strRequestTimeout, token, strKVEnginePath, newStrSecretPath, strPrefixType, strVariablePrefix, replaceCR, strCRPrefix, objectSplit, objectSeperator); } } catch(err){ @@ -154,7 +161,7 @@ async function browseEngineAndGetSecrets(kvVersion, strUrl, ignoreCertificateChe } -async function getSecrets(kvVersion, strUrl, ignoreCertificateChecks, strRequestTimeout, token, strKVEnginePath, strSecretPath, strPrefixType, strVariablePrefix, replaceCR, strCRPrefix){ +async function getSecrets(kvVersion, strUrl, ignoreCertificateChecks, strRequestTimeout, token, strKVEnginePath, strSecretPath, strPrefixType, strVariablePrefix, replaceCR, strCRPrefix, objectSplit, objectSeperator){ var getURL = null; @@ -192,12 +199,12 @@ async function getSecrets(kvVersion, strUrl, ignoreCertificateChecks, strRequest try{ switch(kvVersion){ case "v1": - await exportJSONValues(resultJSON.data, strVariablePrefix, replaceCR, strCRPrefix); + await exportJSONValues(resultJSON.data, strVariablePrefix, null, replaceCR, strCRPrefix, objectSplit, objectSeperator); break; case "v2": console.log("[INFO] Secret version : '" + resultJSON.data.metadata.version + "'"); console.log("[INFO] Secret creation time : '" + resultJSON.data.metadata.created_time + "'"); - await exportJSONValues(resultJSON.data.data, strVariablePrefix, replaceCR, strCRPrefix); + await exportJSONValues(resultJSON.data.data, strVariablePrefix,null, replaceCR, strCRPrefix, objectSplit, objectSeperator); break; default: throw new Error("KV version not supported. v1 or v2 are supported."); diff --git a/src/test_json_pull/test_json_pull.ts b/src/test_json_pull/test_json_pull.ts new file mode 100644 index 0000000..64311cb --- /dev/null +++ b/src/test_json_pull/test_json_pull.ts @@ -0,0 +1,38 @@ +import tl = require('azure-pipelines-task-lib/task'); +const url = require('url'); +const path = require('path'); +// import {getToken,requestVault} from './common/request'; +import {exportJSONValues} from '../kv_read/common/utils'; +import * as fs from 'fs'; + +async function run() { + + try { + var jsonFilePath = tl.getInput('jsonFilePath', true); + var strVariablePrefix = tl.getInput('strVariablePrefix', false); + var replaceCR = tl.getBoolInput('replaceCR', true); + var objectSplit = tl.getBoolInput('objectSplit', true); + var objectSeperator = tl.getInput('objectSeperator', false); + + if(replaceCR){ + var strCRPrefix = tl.getInput('strCRPrefix', true); + } + if(!strVariablePrefix){ + strVariablePrefix = ""; + } + if(!objectSeperator){ + objectSeperator = "."; + } + + var obj = JSON.parse(fs.readFileSync(jsonFilePath,'utf8')); + exportJSONValues(obj, strVariablePrefix,"", replaceCR, strCRPrefix, objectSplit, objectSeperator).then(function(result) { + tl.setResult(tl.TaskResult.Succeeded, "Wrapping successfull."); + }).catch(function(err) { + tl.setResult(tl.TaskResult.Failed, err); + throw new Error(err); + }); + } catch (err) { + tl.setResult(tl.TaskResult.Failed, err); + } +} +run() \ No newline at end of file diff --git a/test/conf.json b/test/conf.json index a8af7fb..521ddb1 100644 --- a/test/conf.json +++ b/test/conf.json @@ -45,7 +45,9 @@ "strPrefixType": "folder", "strVariablePrefix": "xxx", "replaceCR": true, - "strCRPrefix": "#{rn}#" + "strCRPrefix": "#{rn}#", + "objectSplit": false, + "objectSeperator": "." }, "tool_create_file": { "targetDirectory": ".", diff --git a/test/export_json_array_nosplit.js b/test/export_json_array_nosplit.js new file mode 100644 index 0000000..ab2345a --- /dev/null +++ b/test/export_json_array_nosplit.js @@ -0,0 +1,15 @@ +const tmrm = require('azure-pipelines-task-lib/mock-run'); +const path = require('path'); + +var taskPath = path.join(__dirname, '..', 'dist/test_json_pull/test_json_pull.js'); +var conf = require(path.join(__dirname, 'conf.json')); + +var tr = new tmrm.TaskMockRunner(taskPath); +tr.setInput("jsonFilePath", "test/vault_json/array.json"); +tr.setInput("strVariablePrefix", conf.kv_read.strVariablePrefix ? conf.kv_read.strVariablePrefix : ""); +tr.setInput("replaceCR", conf.kv_read.replaceCR ? conf.kv_read.replaceCR : false); +tr.setInput("strCRPrefix", conf.kv_read.strCRPrefix ? conf.kv_read.strCRPrefix : ""); +tr.setInput("objectSplit", false); +tr.setInput("objectSeperator", ","); +tr.registerMock('azure-pipelines-task-lib/toolrunner', require('azure-pipelines-task-lib/mock-toolrunner')); +tr.run() \ No newline at end of file diff --git a/test/export_json_array_split.js b/test/export_json_array_split.js new file mode 100644 index 0000000..13703c4 --- /dev/null +++ b/test/export_json_array_split.js @@ -0,0 +1,15 @@ +const tmrm = require('azure-pipelines-task-lib/mock-run'); +const path = require('path'); + +var taskPath = path.join(__dirname, '..', 'dist/test_json_pull/test_json_pull.js'); +var conf = require(path.join(__dirname, 'conf.json')); + +var tr = new tmrm.TaskMockRunner(taskPath); +tr.setInput("jsonFilePath", "test/vault_json/array.json"); +tr.setInput("strVariablePrefix", conf.kv_read.strVariablePrefix ? conf.kv_read.strVariablePrefix : ""); +tr.setInput("replaceCR", conf.kv_read.replaceCR ? conf.kv_read.replaceCR : false); +tr.setInput("strCRPrefix", conf.kv_read.strCRPrefix ? conf.kv_read.strCRPrefix : ""); +tr.setInput("objectSplit", true); +tr.setInput("objectSeperator", ","); +tr.registerMock('azure-pipelines-task-lib/toolrunner', require('azure-pipelines-task-lib/mock-toolrunner')); +tr.run() \ No newline at end of file diff --git a/test/export_json_boolean.js b/test/export_json_boolean.js new file mode 100644 index 0000000..9037700 --- /dev/null +++ b/test/export_json_boolean.js @@ -0,0 +1,15 @@ +const tmrm = require('azure-pipelines-task-lib/mock-run'); +const path = require('path'); + +var taskPath = path.join(__dirname, '..', 'dist/test_json_pull/test_json_pull.js'); +var conf = require(path.join(__dirname, 'conf.json')); + +var tr = new tmrm.TaskMockRunner(taskPath); +tr.setInput("jsonFilePath", "test/vault_json/boolean.json"); +tr.setInput("strVariablePrefix", conf.kv_read.strVariablePrefix ? conf.kv_read.strVariablePrefix : ""); +tr.setInput("replaceCR", conf.kv_read.replaceCR ? conf.kv_read.replaceCR : false); +tr.setInput("strCRPrefix", conf.kv_read.strCRPrefix ? conf.kv_read.strCRPrefix : ""); +tr.setInput("objectSplit", conf.kv_read.objectSplit ? conf.kv_read.objectSplit : false); +tr.setInput("objectSeperator", conf.kv_read.objectSeperator ? conf.kv_read.objectSeperator : ""); +tr.registerMock('azure-pipelines-task-lib/toolrunner', require('azure-pipelines-task-lib/mock-toolrunner')); +tr.run() \ No newline at end of file diff --git a/test/export_json_dict_nosplit.js b/test/export_json_dict_nosplit.js new file mode 100644 index 0000000..58659fe --- /dev/null +++ b/test/export_json_dict_nosplit.js @@ -0,0 +1,15 @@ +const tmrm = require('azure-pipelines-task-lib/mock-run'); +const path = require('path'); + +var taskPath = path.join(__dirname, '..', 'dist/test_json_pull/test_json_pull.js'); +var conf = require(path.join(__dirname, 'conf.json')); + +var tr = new tmrm.TaskMockRunner(taskPath); +tr.setInput("jsonFilePath", "test/vault_json/dict.json"); +tr.setInput("strVariablePrefix", ""); +tr.setInput("replaceCR", false); +tr.setInput("strCRPrefix", ""); +tr.setInput("objectSplit", false); +tr.setInput("objectSeperator", "."); +tr.registerMock('azure-pipelines-task-lib/toolrunner', require('azure-pipelines-task-lib/mock-toolrunner')); +tr.run() \ No newline at end of file diff --git a/test/export_json_dict_split.js b/test/export_json_dict_split.js new file mode 100644 index 0000000..d72542a --- /dev/null +++ b/test/export_json_dict_split.js @@ -0,0 +1,15 @@ +const tmrm = require('azure-pipelines-task-lib/mock-run'); +const path = require('path'); + +var taskPath = path.join(__dirname, '..', 'dist/test_json_pull/test_json_pull.js'); +var conf = require(path.join(__dirname, 'conf.json')); + +var tr = new tmrm.TaskMockRunner(taskPath); +tr.setInput("jsonFilePath", "test/vault_json/dict.json"); +tr.setInput("strVariablePrefix", ""); +tr.setInput("replaceCR", false); +tr.setInput("strCRPrefix", ""); +tr.setInput("objectSplit", true); +tr.setInput("objectSeperator", "."); +tr.registerMock('azure-pipelines-task-lib/toolrunner', require('azure-pipelines-task-lib/mock-toolrunner')); +tr.run() \ No newline at end of file diff --git a/test/export_json_number.js b/test/export_json_number.js new file mode 100644 index 0000000..94ebd4b --- /dev/null +++ b/test/export_json_number.js @@ -0,0 +1,15 @@ +const tmrm = require('azure-pipelines-task-lib/mock-run'); +const path = require('path'); + +var taskPath = path.join(__dirname, '..', 'dist/test_json_pull/test_json_pull.js'); +var conf = require(path.join(__dirname, 'conf.json')); + +var tr = new tmrm.TaskMockRunner(taskPath); +tr.setInput("jsonFilePath", "test/vault_json/number.json"); +tr.setInput("strVariablePrefix", conf.kv_read.strVariablePrefix ? conf.kv_read.strVariablePrefix : ""); +tr.setInput("replaceCR", conf.kv_read.replaceCR ? conf.kv_read.replaceCR : false); +tr.setInput("strCRPrefix", conf.kv_read.strCRPrefix ? conf.kv_read.strCRPrefix : ""); +tr.setInput("objectSplit", conf.kv_read.objectSplit ? conf.kv_read.objectSplit : false); +tr.setInput("objectSeperator", conf.kv_read.objectSeperator ? conf.kv_read.objectSeperator : ""); +tr.registerMock('azure-pipelines-task-lib/toolrunner', require('azure-pipelines-task-lib/mock-toolrunner')); +tr.run() \ No newline at end of file diff --git a/test/export_json_string.js b/test/export_json_string.js new file mode 100644 index 0000000..21b449e --- /dev/null +++ b/test/export_json_string.js @@ -0,0 +1,15 @@ +const tmrm = require('azure-pipelines-task-lib/mock-run'); +const path = require('path'); + +var taskPath = path.join(__dirname, '..', 'dist/test_json_pull/test_json_pull.js'); +var conf = require(path.join(__dirname, 'conf.json')); + +var tr = new tmrm.TaskMockRunner(taskPath); +tr.setInput("jsonFilePath", "test/vault_json/string.json"); +tr.setInput("strVariablePrefix", conf.kv_read.strVariablePrefix ? conf.kv_read.strVariablePrefix : ""); +tr.setInput("replaceCR", conf.kv_read.replaceCR ? conf.kv_read.replaceCR : false); +tr.setInput("strCRPrefix", conf.kv_read.strCRPrefix ? conf.kv_read.strCRPrefix : ""); +tr.setInput("objectSplit", conf.kv_read.objectSplit ? conf.kv_read.objectSplit : false); +tr.setInput("objectSeperator", conf.kv_read.objectSeperator ? conf.kv_read.objectSeperator : ""); +tr.registerMock('azure-pipelines-task-lib/toolrunner', require('azure-pipelines-task-lib/mock-toolrunner')); +tr.run() \ No newline at end of file diff --git a/test/kv_read.js b/test/kv_read.js index c08aa80..e97f794 100644 --- a/test/kv_read.js +++ b/test/kv_read.js @@ -60,6 +60,8 @@ tr.setInput("strPrefixType", conf.kv_read.strPrefixType); tr.setInput("strSecretPath", conf.kv_read.strSecretPath ? conf.kv_read.strSecretPath : ""); tr.setInput("replaceCR", conf.kv_read.replaceCR ? conf.kv_read.replaceCR : false); tr.setInput("strCRPrefix", conf.kv_read.strCRPrefix ? conf.kv_read.strCRPrefix : ""); +tr.setInput("objectSplit", conf.kv_read.objectSplit ? conf.kv_read.objectSplit : false); +tr.setInput("objectSeperator", conf.kv_read.objectSeperator ? conf.kv_read.objectSeperator : ""); tr.registerMock('azure-pipelines-task-lib/toolrunner', require('azure-pipelines-task-lib/mock-toolrunner')); tr.run(); \ No newline at end of file diff --git a/test/run_all.js b/test/run_all.js index 48fd2b4..a22d925 100644 --- a/test/run_all.js +++ b/test/run_all.js @@ -44,4 +44,176 @@ describe('azure-devops-vault-interaction', function () { done(error); } }).timeout(10000); + + it("export_json_string", (done) => { + + var tp = path.join(__dirname, "export_json_string.js"); + var tr = new ttm.MockTestRunner(tp); + + tr.run(); + console.log(tr.failed); + + try { + assert(tr.succeeded, "Should have succeeded"); + assert(tr.stdOutContained("task.setvariable variable=xxx_test;isOutput=false;issecret=true;]test_value")) + assert(tr.stdOutContained("task.setvariable variable=xxx_test2;isOutput=false;issecret=true;]test_value2")) + console.log("STDOUT", tr.stdout); + done(); + } + catch (error) { + console.log("STDERR", tr.stderr); + console.log("STDOUT", tr.stdout); + done(error); + } + }).timeout(10000); + it("export_json_number", (done) => { + + var tp = path.join(__dirname, "export_json_number.js"); + var tr = new ttm.MockTestRunner(tp); + + tr.run(); + console.log(tr.failed); + + try { + assert(tr.succeeded, "Should have succeeded"); + assert(tr.stdOutContained("task.setvariable variable=xxx_test;isOutput=false;issecret=true;]1")) + assert(tr.stdOutContained("task.setvariable variable=xxx_test2;isOutput=false;issecret=true;]3")) + console.log("STDOUT", tr.stdout); + done(); + } + catch (error) { + console.log("STDERR", tr.stderr); + console.log("STDOUT", tr.stdout); + done(error); + } + }).timeout(10000); + it("export_json_boolean", (done) => { + + var tp = path.join(__dirname, "export_json_boolean.js"); + var tr = new ttm.MockTestRunner(tp); + + tr.run(); + console.log(tr.failed); + + try { + assert(tr.succeeded, "Should have succeeded"); + assert(tr.stdOutContained("task.setvariable variable=xxx_test;isOutput=false;issecret=true;]true")) + assert(tr.stdOutContained("task.setvariable variable=xxx_test2;isOutput=false;issecret=true;]false")) + console.log("STDOUT", tr.stdout); + done(); + } + catch (error) { + console.log("STDERR", tr.stderr); + console.log("STDOUT", tr.stdout); + done(error); + } + }).timeout(10000); + it("export_json_array_nosplit", (done) => { + + var tp = path.join(__dirname, "export_json_array_nosplit.js"); + var tr = new ttm.MockTestRunner(tp); + + tr.run(); + console.log(tr.failed); + + try { + assert(tr.succeeded, "Should have succeeded"); + console.log("STDOUT", tr.stdout); + assert(tr.stdOutContained("task.setvariable variable=xxx_test;isOutput=false;issecret=true;][\"test value\",1,2,3,4]")) + assert(tr.stdOutContained("task.setvariable variable=xxx_test2;isOutput=false;issecret=true;][\"tree\"]")) + assert(tr.stdOutContained("task.setvariable variable=xxx_embedded;isOutput=false;issecret=true;][[0,2],[1,2]]")) + assert(tr.stdOutContained("task.setvariable variable=xxx_embeddedDict;isOutput=false;issecret=true;][{\"foo\":\"bar\",\"one\":2}]")) + done(); + } + catch (error) { + console.log("STDERR", tr.stderr); + console.log("STDOUT", tr.stdout); + done(error); + } + }).timeout(10000); + it("export_json_array_split", (done) => { + + var tp = path.join(__dirname, "export_json_array_split.js"); + var tr = new ttm.MockTestRunner(tp); + + tr.run(); + console.log(tr.failed); + + try { + assert(tr.succeeded, "Should have succeeded"); + console.log("STDOUT", tr.stdout); + assert(tr.stdOutContained("task.setvariable variable=xxx_test,0;isOutput=false;issecret=true;]test value")) + assert(tr.stdOutContained("task.setvariable variable=xxx_test,1;isOutput=false;issecret=true;]1")) + assert(tr.stdOutContained("task.setvariable variable=xxx_test,2;isOutput=false;issecret=true;]2")) + assert(tr.stdOutContained("task.setvariable variable=xxx_test,3;isOutput=false;issecret=true;]3")) + assert(tr.stdOutContained("task.setvariable variable=xxx_test,4;isOutput=false;issecret=true;]4")) + assert(tr.stdOutContained("task.setvariable variable=xxx_test2,0;isOutput=false;issecret=true;]tree")) + assert(tr.stdOutContained("task.setvariable variable=xxx_embedded,0,0;isOutput=false;issecret=true;]0")) + assert(tr.stdOutContained("task.setvariable variable=xxx_embedded,0,1;isOutput=false;issecret=true;]2")) + assert(tr.stdOutContained("task.setvariable variable=xxx_embedded,1,0;isOutput=false;issecret=true;]1")) + assert(tr.stdOutContained("task.setvariable variable=xxx_embedded,1,1;isOutput=false;issecret=true;]2")) + assert(tr.stdOutContained("task.setvariable variable=xxx_embeddedDict,0,foo;isOutput=false;issecret=true;]bar")) + assert(tr.stdOutContained("task.setvariable variable=xxx_embeddedDict,0,one;isOutput=false;issecret=true;]2")) + done(); + } + catch (error) { + console.log("STDERR", tr.stderr); + console.log("STDOUT", tr.stdout); + done(error); + } + }).timeout(10000); + it("export_json_dict_split", (done) => { + + var tp = path.join(__dirname, "export_json_dict_split.js"); + var tr = new ttm.MockTestRunner(tp); + + tr.run(); + console.log(tr.failed); + + try { + assert(tr.succeeded, "Should have succeeded"); + console.log("STDOUT", tr.stdout); + assert(tr.stdOutContained("task.setvariable variable=test.test;isOutput=false;issecret=true;]key")) + assert(tr.stdOutContained("task.setvariable variable=test.num;isOutput=false;issecret=true;]1")) + assert(tr.stdOutContained("task.setvariable variable=test.boolean;isOutput=false;issecret=true;]true")) + assert(tr.stdOutContained("task.setvariable variable=embeddedDict.test.foo;isOutput=false;issecret=true;]bar")) + assert(tr.stdOutContained("task.setvariable variable=embeddedDict.test.one;isOutput=false;issecret=true;]2")) + assert(tr.stdOutContained("task.setvariable variable=embeddedDict.hi;isOutput=false;issecret=true;]hello")) + assert(tr.stdOutContained("task.setvariable variable=embeddedArray.test.0;isOutput=false;issecret=true;]1")) + assert(tr.stdOutContained("task.setvariable variable=embeddedArray.test.1;isOutput=false;issecret=true;]test")) + assert(tr.stdOutContained("task.setvariable variable=embeddedArray.test.2;isOutput=false;issecret=true;]false")) + assert(tr.stdOutContained("task.setvariable variable=embeddedArray.hi.test.0;isOutput=false;issecret=true;]1")) + assert(tr.stdOutContained("task.setvariable variable=embeddedArray.hi.test.1;isOutput=false;issecret=true;]3")) + assert(tr.stdOutContained("task.setvariable variable=embeddedArray.hi.test.2;isOutput=false;issecret=true;]2")) + assert(tr.stdOutContained("task.setvariable variable=embeddedArray.hi.test.3;isOutput=false;issecret=true;]4")) + done(); + } + catch (error) { + console.log("STDERR", tr.stderr); + console.log("STDOUT", tr.stdout); + done(error); + } + }).timeout(10000); + it("export_json_dict_nosplit", (done) => { + + var tp = path.join(__dirname, "export_json_dict_nosplit.js"); + var tr = new ttm.MockTestRunner(tp); + + tr.run(); + console.log(tr.failed); + + try { + assert(tr.succeeded, "Should have succeeded"); + console.log("STDOUT", tr.stdout); + assert(tr.stdOutContained("task.setvariable variable=test;isOutput=false;issecret=true;]{\"test\":\"key\",\"num\":1,\"boolean\":true}")) + assert(tr.stdOutContained("task.setvariable variable=embeddedDict;isOutput=false;issecret=true;]{\"test\":{\"foo\":\"bar\",\"one\":2},\"hi\":\"hello\"}")) + assert(tr.stdOutContained("task.setvariable variable=embeddedArray;isOutput=false;issecret=true;]{\"test\":[1,\"test\",false],\"hi\":{\"test\":[1,3,2,4]}}")) + done(); + } + catch (error) { + console.log("STDERR", tr.stderr); + console.log("STDOUT", tr.stdout); + done(error); + } + }).timeout(10000); }); diff --git a/test/vault_json/array.json b/test/vault_json/array.json new file mode 100644 index 0000000..ee32c8e --- /dev/null +++ b/test/vault_json/array.json @@ -0,0 +1,28 @@ +{ + "test": [ + "test value", + 1, + 2, + 3, + 4 + ], + "test2": [ + "tree" + ], + "embedded": [ + [ + 0, + 2 + ], + [ + 1, + 2 + ] + ], + "embeddedDict": [ + { + "foo": "bar", + "one": 2 + } + ] +} \ No newline at end of file diff --git a/test/vault_json/boolean.json b/test/vault_json/boolean.json new file mode 100644 index 0000000..f1d8b96 --- /dev/null +++ b/test/vault_json/boolean.json @@ -0,0 +1,4 @@ +{ + "test":true, + "test2":false +} \ No newline at end of file diff --git a/test/vault_json/dict.json b/test/vault_json/dict.json new file mode 100644 index 0000000..3ae857f --- /dev/null +++ b/test/vault_json/dict.json @@ -0,0 +1,18 @@ +{ + "test": { + "test": "key", + "num": 1, + "boolean": true + }, + "embeddedDict": { + "test": { + "foo": "bar", + "one": 2 + }, + "hi": "hello" + }, + "embeddedArray": { + "test": [1,"test",false], + "hi": {"test":[1,3,2,4]} + } +} \ No newline at end of file diff --git a/test/vault_json/number.json b/test/vault_json/number.json new file mode 100644 index 0000000..b1eb8ae --- /dev/null +++ b/test/vault_json/number.json @@ -0,0 +1,4 @@ +{ + "test":1, + "test2":3 +} \ No newline at end of file diff --git a/test/vault_json/string.json b/test/vault_json/string.json new file mode 100644 index 0000000..ac7248b --- /dev/null +++ b/test/vault_json/string.json @@ -0,0 +1,4 @@ +{ + "test":"test_value", + "test2":"test_value2" +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 8d17974..994f635 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,6 +8,7 @@ "outDir": "dist" }, "include": [ + "src/test_json_pull/*", "src/kv_read/*", "src/tool_create_file/*", "src/common/*" diff --git a/vss-extension.json b/vss-extension.json index d5ad62b..0e8d1d8 100644 --- a/vss-extension.json +++ b/vss-extension.json @@ -1,80 +1,80 @@ { - "manifestVersion": 1, - "id": "azure-devops-vault-interaction", - "name": "Vault Interaction", - "version": "4.0.1", - "publisher": "Fizcko", - "public": true, - "targets": [ - { - "id": "Microsoft.VisualStudio.Services" - } - ], - "description": "This extension provide the ability to interact with HashiCorp Vault.", - "categories": [ - "Azure Pipelines" - ], - "icons": { - "default": "images/extension-icon.png" - }, - "content": { - "details": { - "path": "overview.md" - } - }, - "links": { - "license": { - "uri": "https://github.com/Fizcko/Azure_DevOps_Vault_Interaction/blob/master/LICENSE" - }, - "repository": { - "uri": "https://github.com/Fizcko/Azure_DevOps_Vault_Interaction" - }, - "support": { - "uri": "https://github.com/Fizcko/Azure_DevOps_Vault_Interaction/issues" - } - }, - "tags": [ - "HashiCorp", - "vault", - "password", - "secrets" - ], - "repository": { - "type": "git", - "uri": "https://github.com/Fizcko/Azure_DevOps_Vault_Interaction" - }, - "files": [ - { - "path": "dist/kv_read" - }, - { - "path": "dist/tool_create_file" - }, - { - "path": "screenshots", - "addressable": true - } - ], - "contributions": [ - { - "id": "azure.devops.vault-interaction.kv.read", - "type": "ms.vss-distributed-task.task", - "targets": [ - "ms.vss-distributed-task.tasks" - ], - "properties": { - "name": "dist/kv_read" - } - }, - { - "id": "azure.devops.vault-interaction.create.file", - "type": "ms.vss-distributed-task.task", - "targets": [ - "ms.vss-distributed-task.tasks" - ], - "properties": { - "name": "dist/tool_create_file" - } - } - ] -} + "manifestVersion": 1, + "id": "azure-devops-vault-interaction", + "name": "Vault Interaction", + "version": "4.0.1", + "publisher": "Fizcko", + "public": true, + "targets": [ + { + "id": "Microsoft.VisualStudio.Services" + } + ], + "description": "This extension provide the ability to interact with HashiCorp Vault.", + "categories": [ + "Azure Pipelines" + ], + "icons": { + "default": "images/extension-icon.png" + }, + "content": { + "details": { + "path": "overview.md" + } + }, + "links": { + "license": { + "uri": "https://github.com/Fizcko/Azure_DevOps_Vault_Interaction/blob/master/LICENSE" + }, + "repository": { + "uri": "https://github.com/Fizcko/Azure_DevOps_Vault_Interaction" + }, + "support": { + "uri": "https://github.com/Fizcko/Azure_DevOps_Vault_Interaction/issues" + } + }, + "tags": [ + "HashiCorp", + "vault", + "password", + "secrets" + ], + "repository": { + "type": "git", + "uri": "https://github.com/Fizcko/Azure_DevOps_Vault_Interaction" + }, + "files": [ + { + "path": "dist/kv_read" + }, + { + "path": "dist/tool_create_file" + }, + { + "path": "screenshots", + "addressable": true + } + ], + "contributions": [ + { + "id": "azure.devops.vault-interaction.kv.read", + "type": "ms.vss-distributed-task.task", + "targets": [ + "ms.vss-distributed-task.tasks" + ], + "properties": { + "name": "dist/kv_read" + } + }, + { + "id": "azure.devops.vault-interaction.create.file", + "type": "ms.vss-distributed-task.task", + "targets": [ + "ms.vss-distributed-task.tasks" + ], + "properties": { + "name": "dist/tool_create_file" + } + } + ] +} \ No newline at end of file