@ibm-cloud/cd-tools 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -49,11 +49,15 @@ async function main(options) {
49
49
  for (let i = 0; i < getToolsRes.tools.length; i++) {
50
50
  const tool = getToolsRes.tools[i];
51
51
 
52
+ // Skip iff it's GitHub/GitLab/GRIT integration with OAuth
53
+ if (['githubconsolidated', 'github_integrated', 'gitlab', 'hostedgit'].includes(tool.tool_type_id) && (tool.parameters?.auth_type === '' || tool.parameters?.auth_type === 'oauth'))
54
+ continue;
55
+
52
56
  // Check tool integrations for any plain text secret values
53
57
  if (SECRET_KEYS_MAP[tool.tool_type_id]) {
54
58
  SECRET_KEYS_MAP[tool.tool_type_id].forEach((entry) => {
55
59
  const updateableSecretParam = entry.key;
56
- if (tool.parameters[updateableSecretParam] && !isSecretReference(tool.parameters[updateableSecretParam])) {
60
+ if (tool.parameters[updateableSecretParam] && !isSecretReference(tool.parameters[updateableSecretParam]) && tool.parameters[updateableSecretParam].length > 0) {
57
61
  toolResults.push({
58
62
  'Tool ID': tool.id,
59
63
  'Tool Type': tool.tool_type_id,
@@ -68,7 +72,7 @@ async function main(options) {
68
72
  const pipelineData = await getPipelineData(token, tool.id, region);
69
73
 
70
74
  pipelineData?.properties.forEach((prop) => {
71
- if (prop.type === 'secure' && !isSecretReference(prop.value)) {
75
+ if (prop.type === 'secure' && !isSecretReference(prop.value) && prop.value.length > 0) {
72
76
  pipelineResults.push({
73
77
  'Pipeline ID': pipelineData.id,
74
78
  'Trigger Name': '-',
@@ -79,7 +83,7 @@ async function main(options) {
79
83
 
80
84
  pipelineData?.triggers.forEach((trigger) => {
81
85
  trigger.properties?.forEach((prop) => {
82
- if (prop.type === 'secure' && !isSecretReference(prop.value)) {
86
+ if (prop.type === 'secure' && !isSecretReference(prop.value) && prop.value.length > 0) {
83
87
  pipelineResults.push({
84
88
  'Pipeline ID': pipelineData.id,
85
89
  'Trigger Name': trigger.name,
@@ -106,7 +106,7 @@ async function main(options) {
106
106
 
107
107
  // check for existing .tf files in output directory
108
108
  if (fs.existsSync(outputDir)) {
109
- let files = readdirSync(outputDir, { recursive: true });
109
+ let files = fs.readdirSync(outputDir, { recursive: true });
110
110
  files = files.filter((f) => f.endsWith('.tf'));
111
111
  if (files.length > 0) throw Error(`Output directory already has ${files.length} '.tf' files, please specify a different output directory`);
112
112
  }
@@ -249,7 +249,8 @@ async function main(options) {
249
249
  LOG_STAGES.import
250
250
  );
251
251
 
252
- if (nonSecretRefs.length > 0) logger.warn(`\nWarning! The following generated terraform resource contains a hashed secret, applying without changes may result in error(s):\n${nonSecretRefs.map((entry) => `- ${entry}\n`).join('')}`, '', true);
252
+ if (nonSecretRefs.length > 0) logger.warn(`\nWarning! The following generated terraform resource contains hashed secret(s) that cannot be migrated, applying without changes may result in error(s):`);
253
+ logger.table(nonSecretRefs);
253
254
 
254
255
  } catch (err) {
255
256
  if (err.message && err.stack) {
@@ -70,8 +70,15 @@ export async function importTerraform(token, apiKey, region, toolchainId, toolch
70
70
  if (isSecretReference(tool.parameters[key])) {
71
71
  additionalProps[block.name].push({ param: tfKey, value: tool.parameters[key] });
72
72
  } else {
73
- nonSecretRefs.push(block.name);
74
- if (required) additionalProps[block.name].push({ param: tfKey, value: `<${tfKey}>` });
73
+ const newFileName = SUPPORTED_TOOLS_MAP[tool.tool_type_id].split('ibm_')[1];
74
+ if (required) {
75
+ nonSecretRefs.push({
76
+ resource_name: block.name,
77
+ property_name: tfKey,
78
+ file_name: isCompact ? 'resources.tf' : `${newFileName}.tf`
79
+ });
80
+ additionalProps[block.name].push({ param: tfKey, value: `<${tfKey}>` });
81
+ }
75
82
  }
76
83
  });
77
84
  }
@@ -11,7 +11,7 @@ import { execSync } from 'child_process';
11
11
  import { logger, LOG_STAGES } from './logger.js'
12
12
  import { RESERVED_GRIT_PROJECT_NAMES, RESERVED_GRIT_GROUP_NAMES, RESERVED_GRIT_SUBGROUP_NAME, TERRAFORM_REQUIRED_VERSION, SECRET_KEYS_MAP } from '../../config.js';
13
13
  import { getToolchainsByName, getToolchainTools, getPipelineData, getAppConfigHealthcheck, getSecretsHealthcheck, getGitOAuth, getGritUserProject, getGritGroup, getGritGroupProject } from './requests.js';
14
- import { promptUserConfirmation, promptUserInput } from './utils.js';
14
+ import { promptUserConfirmation, promptUserInput, isSecretReference } from './utils.js';
15
15
 
16
16
 
17
17
  function validatePrereqsVersions() {
@@ -146,7 +146,6 @@ async function validateTools(token, tcId, region, skipPrompt) {
146
146
  const toolsWithHashedParams = [];
147
147
  const patTools = [];
148
148
  const classicPipelines = [];
149
- const secretPattern = /^hash:SHA3-512:[a-zA-Z0-9]{128}$/;
150
149
 
151
150
  for (const tool of allTools.tools) {
152
151
  const toolName = (tool.name || tool.parameters?.name || tool.parameters?.label || '').replace(/\s+/g, '+');
@@ -203,7 +202,7 @@ async function validateTools(token, tcId, region, skipPrompt) {
203
202
  url: toolUrl
204
203
  });
205
204
  }
206
- else if (['githubconsolidated', 'github_integrated', 'gitlab'].includes(tool.tool_type_id) && (tool.parameters?.auth_type === '' || tool.parameters?.auth_type === 'oauth')) { // Skip secret check iff it's GitHub/GitLab integration with OAuth
205
+ else if (['githubconsolidated', 'github_integrated', 'gitlab', 'hostedgit'].includes(tool.tool_type_id) && (tool.parameters?.auth_type === '' || tool.parameters?.auth_type === 'oauth')) { // Skip secret check iff it's GitHub/GitLab/GRIT integration with OAuth
207
206
  continue;
208
207
  }
209
208
  else {
@@ -212,20 +211,23 @@ async function validateTools(token, tcId, region, skipPrompt) {
212
211
  const pipelineData = await getPipelineData(token, tool.id, region);
213
212
 
214
213
  pipelineData.properties.forEach((prop) => {
215
- if (prop.type === 'secure' && secretPattern.test(prop.value)) secrets.push(['properties', prop.name].join('.').replace(/\s+/g, '+'));
214
+ if (prop.type === 'secure' && !isSecretReference(prop.value) && prop.value.length > 0)
215
+ secrets.push(['properties', prop.name].join('.').replace(/\s+/g, '+'));
216
216
  });
217
217
 
218
218
  pipelineData.triggers.forEach((trigger) => {
219
- if ((trigger?.secret?.type === 'token_matches' || trigger?.secret?.type === 'digest_matches') && secretPattern.test(trigger.secret.value)) secrets.push([trigger.name, trigger.secret.key_name].join('.').replace(/\s+/g, '+'));
219
+ if ((trigger?.secret?.type === 'token_matches' || trigger?.secret?.type === 'digest_matches') && !isSecretReference(trigger.secret.value) && trigger.secret.value.length > 0)
220
+ secrets.push([trigger.name, trigger.secret.key_name].join('.').replace(/\s+/g, '+'));
220
221
  trigger.properties.forEach((prop) => {
221
- if (prop.type === 'secure' && secretPattern.test(prop.value)) secrets.push([trigger.name, 'properties', prop.name].join('.').replace(/\s+/g, '+'));
222
+ if (prop.type === 'secure' && !isSecretReference(prop.value) && prop.value.length > 0)
223
+ secrets.push([trigger.name, 'properties', prop.name].join('.').replace(/\s+/g, '+'));
222
224
  });
223
225
  });
224
226
  }
225
227
  else {
226
228
  const secretsToCheck = (SECRET_KEYS_MAP[tool.tool_type_id] || []).map((entry) => entry.key); // Check for secrets in the rest of the tools
227
229
  Object.entries(tool.parameters).forEach(([key, value]) => {
228
- if (secretPattern.test(value) && secretsToCheck.includes(key)) secrets.push(key);
230
+ if (!isSecretReference(value) && value.length > 0 && secretsToCheck.includes(key)) secrets.push(key);
229
231
  });
230
232
  }
231
233
  if (secrets.length > 0) {
@@ -260,7 +262,7 @@ async function validateTools(token, tcId, region, skipPrompt) {
260
262
  }
261
263
 
262
264
  if (toolsWithHashedParams.length > 0) {
263
- logger.warn('Warning! The following tools contain secrets that cannot be migrated, please use the \'check-secret\' command to export the secrets: \n', LOG_STAGES.setup, true);
265
+ logger.warn('Warning! The following tools contain secrets that cannot be migrated, please use the \'check-secrets\' command to export the secrets: \n', LOG_STAGES.setup, true);
264
266
  logger.table(toolsWithHashedParams);
265
267
  }
266
268
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ibm-cloud/cd-tools",
3
- "version": "1.2.2",
3
+ "version": "1.2.3",
4
4
  "description": "Tools and utilities for the IBM Cloud Continuous Delivery service and resources",
5
5
  "repository": {
6
6
  "type": "git",