From ce638b5a4b79c57dd1afbe507c857953f948271f Mon Sep 17 00:00:00 2001 From: jvallexm Date: Mon, 4 Mar 2024 14:29:45 -0500 Subject: [PATCH 01/16] Issue 1601: Outputs (#1602) * feat: power vs v2 enhancements * button * fdeat: subnet * feat: display on v2 * feat: display on v2 * feat: subnet display and title button * feat: crud ops * feat: all caps project names * feat: all caps project names * fix: vpc save * fix: vpc save * fix: vpc save * fix: vpc save * fix: vpc save * fix: vpc save * fix: vpc save * feat: expanded vpc module outputs * feat: outputs * feat: config to files * feat: outputs * merge --- CHANGELOG.md | 15 + client/src/components/pages/vpc/Vpc.js | 3 +- client/src/lib/docs/release-notes.json | 11 + client/src/lib/index.js | 2 + .../lib/json-to-iac/config-to-files-json.js | 2 + client/src/lib/json-to-iac/index.js | 3 + client/src/lib/json-to-iac/outputs.js | 65 ++ client/src/lib/json-to-iac/vpc.js | 14 +- unit-tests/api/craig-api.test.js | 8 +- unit-tests/craig-to-cdktf.test.js | 74 ++- .../modules-slz-network-files.json | 2 +- unit-tests/forms/wizard.test.js | 24 +- unit-tests/json-to-iac/outputs.test.js | 586 ++++++++++++++++++ unit-tests/json-to-iac/vpc.test.js | 8 +- 14 files changed, 774 insertions(+), 43 deletions(-) create mode 100644 client/src/lib/json-to-iac/outputs.js create mode 100644 unit-tests/json-to-iac/outputs.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index a532488e..4b17eb09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ All notable changes to this project will be documented in this file. +## 1.12.2 + +### Upgrade Notes + + +### Features + +- A new file `outputs.tf` is now added to each CRAIG Terraform template +- VPC names, IDs, and CRNs are exported as outputs +- Subnet names, IDs, and CRNS are exported as outputs +- VPC Security Group names, and IDs are exported as outputs + +### Fixes + + ## 1.12.1 ### Upgrade Notes diff --git a/client/src/components/pages/vpc/Vpc.js b/client/src/components/pages/vpc/Vpc.js index 13a7d4d3..f4e3f538 100644 --- a/client/src/components/pages/vpc/Vpc.js +++ b/client/src/components/pages/vpc/Vpc.js @@ -224,8 +224,7 @@ class VpcDiagramPage extends React.Component { ? craig.store.json.vpcs[this.state.vpcIndex].name : ""; let vpcFormData = craigForms(craig).vpcs; - // need to - // - add function to open import subnet form in scroll form on click + return ( <> {this.state.showSubnetModal ? ( diff --git a/client/src/lib/docs/release-notes.json b/client/src/lib/docs/release-notes.json index 735721bf..808f4e42 100644 --- a/client/src/lib/docs/release-notes.json +++ b/client/src/lib/docs/release-notes.json @@ -1,4 +1,15 @@ [ + { + "version": "1.12.2", + "features": [ + "A new file `outputs.tf` is now added to each CRAIG Terraform template", + "VPC names, IDs, and CRNs are exported as outputs", + "Subnet names, IDs, and CRNS are exported as outputs", + "VPC Security Group names, and IDs are exported as outputs" + ], + "fixes": [], + "upgrade_notes": [] + }, { "version": "1.12.1", "features": [ diff --git a/client/src/lib/index.js b/client/src/lib/index.js index 47aa8cc1..d3b56664 100644 --- a/client/src/lib/index.js +++ b/client/src/lib/index.js @@ -106,6 +106,7 @@ const { formatClassicSshKey, formatClassicNetworkVlan, classicInfraTf, + outputsTf, } = require("./json-to-iac"); const releaseNotes = require("./docs/release-notes.json"); const docs = require("./docs/docs.json"); @@ -114,6 +115,7 @@ const { invalidForms } = require("./invalid-forms"); const { allDocText, filterDocs } = require("./docs"); module.exports = { + outputsTf, allDocText, filterDocs, shouldDisplayService, diff --git a/client/src/lib/json-to-iac/config-to-files-json.js b/client/src/lib/json-to-iac/config-to-files-json.js index 92d6eae9..5e075539 100644 --- a/client/src/lib/json-to-iac/config-to-files-json.js +++ b/client/src/lib/json-to-iac/config-to-files-json.js @@ -34,6 +34,7 @@ const { cisTf } = require("./cis"); const { cisGlbTf } = require("./cis-glb"); const { scc2Tf } = require("./scc-v2"); const { fortigateTf } = require("./fortigate"); +const { outputsTf } = require("./outputs"); const apacheLicense = ` Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -310,6 +311,7 @@ function configToFilesJson(config, apiMode, templateTarMode) { "cis_global_load_balancers.tf": cisGlbTf(config), "scc_v2.tf": scc2Tf(config), "fortigate_vnf.tf": fortigateTf(config), + "outputs.tf": outputsTf(config), }; vpcModuleTf(files, config); return files; diff --git a/client/src/lib/json-to-iac/index.js b/client/src/lib/json-to-iac/index.js index 1b11114c..b4167d67 100644 --- a/client/src/lib/json-to-iac/index.js +++ b/client/src/lib/json-to-iac/index.js @@ -186,7 +186,10 @@ const { formatClassicNetworkVlan, classicInfraTf, } = require("./classic"); +const { outputsTf } = require("./outputs"); + module.exports = { + outputsTf, formatClassicSshKey, formatClassicNetworkVlan, classicInfraTf, diff --git a/client/src/lib/json-to-iac/outputs.js b/client/src/lib/json-to-iac/outputs.js new file mode 100644 index 00000000..920fe641 --- /dev/null +++ b/client/src/lib/json-to-iac/outputs.js @@ -0,0 +1,65 @@ +const { jsonToTf } = require("json-to-tf"); +const { tfBlock } = require("./utils"); +const { snakeCase } = require("lazy-z"); + +/** + * outputs + * @param {*} config + * @returns {string} terraform output file + */ +function outputsTf(config) { + let tf = ""; + config.vpcs.forEach((vpc) => { + let outputs = {}; + + // vpc outputs + ["name", "id", "crn"].forEach((field) => { + outputs[snakeCase(vpc.name) + "_vpc_" + field] = { + value: `\${module.${snakeCase(vpc.name + " vpc")}.${field}}`, + }; + }); + + // subnet outputs + vpc.subnets.forEach((subnet) => { + ["name", "id", "crn"].forEach((field) => { + outputs[ + snakeCase(vpc.name + " vpc subnet " + subnet.name + " " + field) + ] = { + value: `\${module.${snakeCase(vpc.name + " vpc")}.${snakeCase( + subnet.name + " " + field + )}}`, + }; + }); + }); + + config.security_groups.forEach((sg) => { + ["name", "id"].forEach((field) => { + if (sg.vpc === vpc.name) { + outputs[ + snakeCase(vpc.name + " vpc security group " + sg.name + " " + field) + ] = { + value: `\${module.${snakeCase(vpc.name + " vpc")}.${snakeCase( + sg.name + )}_${field}}`, + }; + } + }); + }); + + tf += tfBlock( + vpc.name + " VPC outputs", + "\n" + + jsonToTf( + JSON.stringify({ + output: outputs, + }) + ) + + "\n" + ); + }); + return tf; +} + +module.exports = { + outputsTf, +}; diff --git a/client/src/lib/json-to-iac/vpc.js b/client/src/lib/json-to-iac/vpc.js index 19d31ad6..720827ae 100644 --- a/client/src/lib/json-to-iac/vpc.js +++ b/client/src/lib/json-to-iac/vpc.js @@ -534,7 +534,7 @@ function vpcModuleJson(vpc, rgs, config) { */ function vpcModuleOutputs(vpc, securityGroups) { let outputs = {}; - ["id", "crn"].forEach((field) => { + ["name", "id", "crn"].forEach((field) => { outputs[field] = { value: `\${${vpc.use_data ? "data." : ""}ibm_is_vpc.${snakeCase( vpc.name + "-vpc" @@ -542,6 +542,11 @@ function vpcModuleOutputs(vpc, securityGroups) { }; }); vpc.subnets.forEach((subnet) => { + outputs[snakeCase(subnet.name) + `_name`] = { + value: `\${${subnet.use_data ? "data." : ""}ibm_is_subnet.${snakeCase( + `${subnet.vpc}-${subnet.name}` + )}.name}`, + }; outputs[snakeCase(subnet.name) + `_id`] = { value: `\${${subnet.use_data ? "data." : ""}ibm_is_subnet.${snakeCase( `${subnet.vpc}-${subnet.name}` @@ -555,6 +560,13 @@ function vpcModuleOutputs(vpc, securityGroups) { }); securityGroups.forEach((sg) => { if (sg.vpc === vpc.name) { + outputs[snakeCase(`${sg.name}_name`)] = { + value: `\${${ + sg.use_data ? "data." : "" + }ibm_is_security_group.${snakeCase( + `${sg.vpc} vpc ${sg.name} sg` + )}.name}`, + }; outputs[snakeCase(`${sg.name}_id`)] = { value: `\${${ sg.use_data ? "data." : "" diff --git a/unit-tests/api/craig-api.test.js b/unit-tests/api/craig-api.test.js index 6222f7c9..6f3ede81 100644 --- a/unit-tests/api/craig-api.test.js +++ b/unit-tests/api/craig-api.test.js @@ -101,6 +101,10 @@ describe("craig api", () => { data: ' Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n"License" shall mean the terms and conditions for use, reproduction,\nand distribution as defined by Sections 1 through 9 of this document.\n\n"Licensor" shall mean the copyright owner or entity authorized by\nthe copyright owner that is granting the License.\n\n"Legal Entity" shall mean the union of the acting entity and all\nother entities that control, are controlled by, or are under common\ncontrol with that entity. For the purposes of this definition,\n"control" means (i) the power, direct or indirect, to cause the\ndirection or management of such entity, whether by contract or\notherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n"You" (or "Your") shall mean an individual or Legal Entity\nexercising permissions granted by this License.\n\n"Source" form shall mean the preferred form for making modifications,\nincluding but not limited to software source code, documentation\nsource, and configuration files.\n\n"Object" form shall mean any form resulting from mechanical\ntransformation or translation of a Source form, including but\nnot limited to compiled object code, generated documentation,\nand conversions to other media types.\n\n"Work" shall mean the work of authorship, whether in Source or\nObject form, made available under the License, as indicated by a\ncopyright notice that is included in or attached to the work\n(an example is provided in the Appendix below).\n\n"Derivative Works" shall mean any work, whether in Source or Object\nform, that is based on (or derived from) the Work and for which the\neditorial revisions, annotations, elaborations, or other modifications\nrepresent, as a whole, an original work of authorship. For the purposes\nof this License, Derivative Works shall not include works that remain\nseparable from, or merely link (or bind by name) to the interfaces of,\nthe Work and Derivative Works thereof.\n\n"Contribution" shall mean any work of authorship, including\nthe original version of the Work and any modifications or additions\nto that Work or Derivative Works thereof, that is intentionally\nsubmitted to Licensor for inclusion in the Work by the copyright owner\nor by an individual or Legal Entity authorized to submit on behalf of\nthe copyright owner. For the purposes of this definition, "submitted"\nmeans any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems,\nand issue tracking systems that are managed by, or on behalf of, the\nLicensor for the purpose of discussing and improving the Work, but\nexcluding communication that is conspicuously marked or otherwise\ndesignated in writing by the copyright owner as "Not a Contribution."\n\n"Contributor" shall mean Licensor and any individual or Legal Entity\non behalf of whom a Contribution has been received by Licensor and\nsubsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\ncopyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the\nWork and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\nthis License, each Contributor hereby grants to You a perpetual,\nworldwide, non-exclusive, no-charge, royalty-free, irrevocable\n(except as stated in this section) patent license to make, have made,\nuse, offer to sell, sell, import, and otherwise transfer the Work,\nwhere such license applies only to those patent claims licensable\nby such Contributor that are necessarily infringed by their\nContribution(s) alone or by combination of their Contribution(s)\nwith the Work to which such Contribution(s) was submitted. If You\ninstitute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work\nor a Contribution incorporated within the Work constitutes direct\nor contributory patent infringement, then any patent licenses\ngranted to You under this License for that Work shall terminate\nas of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\nWork or Derivative Works thereof in any medium, with or without\nmodifications, and in Source or Object form, provided that You\nmeet the following conditions:\n\n(a) You must give any other recipients of the Work or\nDerivative Works a copy of this License; and\n\n(b) You must cause any modified files to carry prominent notices\nstating that You changed the files; and\n\n(c) You must retain, in the Source form of any Derivative Works\nthat You distribute, all copyright, patent, trademark, and\nattribution notices from the Source form of the Work,\nexcluding those notices that do not pertain to any part of\nthe Derivative Works; and\n\n(d) If the Work includes a "NOTICE" text file as part of its\ndistribution, then any Derivative Works that You distribute must\ninclude a readable copy of the attribution notices contained\nwithin such NOTICE file, excluding those notices that do not\npertain to any part of the Derivative Works, in at least one\nof the following places: within a NOTICE text file distributed\nas part of the Derivative Works; within the Source form or\ndocumentation, if provided along with the Derivative Works; or,\nwithin a display generated by the Derivative Works, if and\nwherever such third-party notices normally appear. The contents\nof the NOTICE file are for informational purposes only and\ndo not modify the License. You may add Your own attribution\nnotices within Derivative Works that You distribute, alongside\nor as an addendum to the NOTICE text from the Work, provided\nthat such additional attribution notices cannot be construed\nas modifying the License.\n\nYou may add Your own copyright statement to Your modifications and\nmay provide additional or different license terms and conditions\nfor use, reproduction, or distribution of Your modifications, or\nfor any such Derivative Works as a whole, provided Your use,\nreproduction, and distribution of the Work otherwise complies with\nthe conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\nany Contribution intentionally submitted for inclusion in the Work\nby You to the Licensor shall be under the terms and conditions of\nthis License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify\nthe terms of any separate license agreement you may have executed\nwith Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\nnames, trademarks, service marks, or product names of the Licensor,\nexcept as required for reasonable and customary use in describing the\norigin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\nagreed to in writing, Licensor provides the Work (and each\nContributor provides its Contributions) on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\nimplied, including, without limitation, any warranties or conditions\nof TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\nPARTICULAR PURPOSE. You are solely responsible for determining the\nappropriateness of using or redistributing the Work and assume any\nrisks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\nwhether in tort (including negligence), contract, or otherwise,\nunless required by applicable law (such as deliberate and grossly\nnegligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special,\nincidental, or consequential damages of any character arising as a\nresult of this License or out of the use or inability to use the\nWork (including but not limited to damages for loss of goodwill,\nwork stoppage, computer failure or malfunction, or any and all\nother commercial damages or losses), even if such Contributor\nhas been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\nthe Work or Derivative Works thereof, You may choose to offer,\nand charge a fee for, acceptance of support, warranty, indemnity,\nor other liability obligations and/or rights consistent with this\nLicense. However, in accepting such obligations, You may act only\non Your own behalf and on Your sole responsibility, not on behalf\nof any other Contributor, and only if You agree to indemnify,\ndefend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason\nof your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work.\n\nTo apply the Apache License to your work, attach the following\nboilerplate notice, with the fields enclosed by brackets "[]"\nreplaced with your own identifying information. (Don\'t include\nthe brackets!) The text should be enclosed in the appropriate\ncomment syntax for the file format. We also recommend that a\nfile or class name and description of purpose be included on the\nsame "printed page" as the copyright notice for easier\nidentification within third-party archives.\n\nCopyright [yyyy] [name of copyright owner]\n\nLicensed under the Apache License, Version 2.0 (the "License");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\nhttp://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an "AS IS" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n', name: "craig/LICENSE", }, + { + name: "craig/outputs.tf", + data: '##############################################################################\n# Management VPC Outputs\n##############################################################################\n\noutput "management_vpc_name" {\n value = module.management_vpc.name\n}\n\noutput "management_vpc_id" {\n value = module.management_vpc.id\n}\n\noutput "management_vpc_crn" {\n value = module.management_vpc.crn\n}\n\noutput "management_vpc_subnet_vsi_zone_1_name" {\n value = module.management_vpc.vsi_zone_1_name\n}\n\noutput "management_vpc_subnet_vsi_zone_1_id" {\n value = module.management_vpc.vsi_zone_1_id\n}\n\noutput "management_vpc_subnet_vsi_zone_1_crn" {\n value = module.management_vpc.vsi_zone_1_crn\n}\n\noutput "management_vpc_subnet_vpn_zone_1_name" {\n value = module.management_vpc.vpn_zone_1_name\n}\n\noutput "management_vpc_subnet_vpn_zone_1_id" {\n value = module.management_vpc.vpn_zone_1_id\n}\n\noutput "management_vpc_subnet_vpn_zone_1_crn" {\n value = module.management_vpc.vpn_zone_1_crn\n}\n\noutput "management_vpc_subnet_vsi_zone_2_name" {\n value = module.management_vpc.vsi_zone_2_name\n}\n\noutput "management_vpc_subnet_vsi_zone_2_id" {\n value = module.management_vpc.vsi_zone_2_id\n}\n\noutput "management_vpc_subnet_vsi_zone_2_crn" {\n value = module.management_vpc.vsi_zone_2_crn\n}\n\noutput "management_vpc_subnet_vsi_zone_3_name" {\n value = module.management_vpc.vsi_zone_3_name\n}\n\noutput "management_vpc_subnet_vsi_zone_3_id" {\n value = module.management_vpc.vsi_zone_3_id\n}\n\noutput "management_vpc_subnet_vsi_zone_3_crn" {\n value = module.management_vpc.vsi_zone_3_crn\n}\n\noutput "management_vpc_subnet_vpe_zone_1_name" {\n value = module.management_vpc.vpe_zone_1_name\n}\n\noutput "management_vpc_subnet_vpe_zone_1_id" {\n value = module.management_vpc.vpe_zone_1_id\n}\n\noutput "management_vpc_subnet_vpe_zone_1_crn" {\n value = module.management_vpc.vpe_zone_1_crn\n}\n\noutput "management_vpc_subnet_vpe_zone_2_name" {\n value = module.management_vpc.vpe_zone_2_name\n}\n\noutput "management_vpc_subnet_vpe_zone_2_id" {\n value = module.management_vpc.vpe_zone_2_id\n}\n\noutput "management_vpc_subnet_vpe_zone_2_crn" {\n value = module.management_vpc.vpe_zone_2_crn\n}\n\noutput "management_vpc_subnet_vpe_zone_3_name" {\n value = module.management_vpc.vpe_zone_3_name\n}\n\noutput "management_vpc_subnet_vpe_zone_3_id" {\n value = module.management_vpc.vpe_zone_3_id\n}\n\noutput "management_vpc_subnet_vpe_zone_3_crn" {\n value = module.management_vpc.vpe_zone_3_crn\n}\n\noutput "management_vpc_security_group_management_vpe_name" {\n value = module.management_vpc.management_vpe_name\n}\n\noutput "management_vpc_security_group_management_vpe_id" {\n value = module.management_vpc.management_vpe_id\n}\n\noutput "management_vpc_security_group_management_vsi_name" {\n value = module.management_vpc.management_vsi_name\n}\n\noutput "management_vpc_security_group_management_vsi_id" {\n value = module.management_vpc.management_vsi_id\n}\n\n##############################################################################\n##############################################################################\n# Workload VPC Outputs\n##############################################################################\n\noutput "workload_vpc_name" {\n value = module.workload_vpc.name\n}\n\noutput "workload_vpc_id" {\n value = module.workload_vpc.id\n}\n\noutput "workload_vpc_crn" {\n value = module.workload_vpc.crn\n}\n\noutput "workload_vpc_subnet_vsi_zone_1_name" {\n value = module.workload_vpc.vsi_zone_1_name\n}\n\noutput "workload_vpc_subnet_vsi_zone_1_id" {\n value = module.workload_vpc.vsi_zone_1_id\n}\n\noutput "workload_vpc_subnet_vsi_zone_1_crn" {\n value = module.workload_vpc.vsi_zone_1_crn\n}\n\noutput "workload_vpc_subnet_vsi_zone_2_name" {\n value = module.workload_vpc.vsi_zone_2_name\n}\n\noutput "workload_vpc_subnet_vsi_zone_2_id" {\n value = module.workload_vpc.vsi_zone_2_id\n}\n\noutput "workload_vpc_subnet_vsi_zone_2_crn" {\n value = module.workload_vpc.vsi_zone_2_crn\n}\n\noutput "workload_vpc_subnet_vsi_zone_3_name" {\n value = module.workload_vpc.vsi_zone_3_name\n}\n\noutput "workload_vpc_subnet_vsi_zone_3_id" {\n value = module.workload_vpc.vsi_zone_3_id\n}\n\noutput "workload_vpc_subnet_vsi_zone_3_crn" {\n value = module.workload_vpc.vsi_zone_3_crn\n}\n\noutput "workload_vpc_subnet_vpe_zone_1_name" {\n value = module.workload_vpc.vpe_zone_1_name\n}\n\noutput "workload_vpc_subnet_vpe_zone_1_id" {\n value = module.workload_vpc.vpe_zone_1_id\n}\n\noutput "workload_vpc_subnet_vpe_zone_1_crn" {\n value = module.workload_vpc.vpe_zone_1_crn\n}\n\noutput "workload_vpc_subnet_vpe_zone_2_name" {\n value = module.workload_vpc.vpe_zone_2_name\n}\n\noutput "workload_vpc_subnet_vpe_zone_2_id" {\n value = module.workload_vpc.vpe_zone_2_id\n}\n\noutput "workload_vpc_subnet_vpe_zone_2_crn" {\n value = module.workload_vpc.vpe_zone_2_crn\n}\n\noutput "workload_vpc_subnet_vpe_zone_3_name" {\n value = module.workload_vpc.vpe_zone_3_name\n}\n\noutput "workload_vpc_subnet_vpe_zone_3_id" {\n value = module.workload_vpc.vpe_zone_3_id\n}\n\noutput "workload_vpc_subnet_vpe_zone_3_crn" {\n value = module.workload_vpc.vpe_zone_3_crn\n}\n\noutput "workload_vpc_security_group_workload_vpe_name" {\n value = module.workload_vpc.workload_vpe_name\n}\n\noutput "workload_vpc_security_group_workload_vpe_id" {\n value = module.workload_vpc.workload_vpe_id\n}\n\n##############################################################################\n', + }, { name: "craig/management_vpc", data: "" }, { name: "craig/management_vpc", data: "" }, { @@ -129,7 +133,7 @@ describe("craig api", () => { }, { name: "craig/management_vpc/outputs.tf", - data: '##############################################################################\n# Management VPC Outputs\n##############################################################################\n\noutput "id" {\n value = ibm_is_vpc.management_vpc.id\n}\n\noutput "crn" {\n value = ibm_is_vpc.management_vpc.crn\n}\n\noutput "vsi_zone_1_id" {\n value = ibm_is_subnet.management_vsi_zone_1.id\n}\n\noutput "vsi_zone_1_crn" {\n value = ibm_is_subnet.management_vsi_zone_1.crn\n}\n\noutput "vpn_zone_1_id" {\n value = ibm_is_subnet.management_vpn_zone_1.id\n}\n\noutput "vpn_zone_1_crn" {\n value = ibm_is_subnet.management_vpn_zone_1.crn\n}\n\noutput "vsi_zone_2_id" {\n value = ibm_is_subnet.management_vsi_zone_2.id\n}\n\noutput "vsi_zone_2_crn" {\n value = ibm_is_subnet.management_vsi_zone_2.crn\n}\n\noutput "vsi_zone_3_id" {\n value = ibm_is_subnet.management_vsi_zone_3.id\n}\n\noutput "vsi_zone_3_crn" {\n value = ibm_is_subnet.management_vsi_zone_3.crn\n}\n\noutput "vpe_zone_1_id" {\n value = ibm_is_subnet.management_vpe_zone_1.id\n}\n\noutput "vpe_zone_1_crn" {\n value = ibm_is_subnet.management_vpe_zone_1.crn\n}\n\noutput "vpe_zone_2_id" {\n value = ibm_is_subnet.management_vpe_zone_2.id\n}\n\noutput "vpe_zone_2_crn" {\n value = ibm_is_subnet.management_vpe_zone_2.crn\n}\n\noutput "vpe_zone_3_id" {\n value = ibm_is_subnet.management_vpe_zone_3.id\n}\n\noutput "vpe_zone_3_crn" {\n value = ibm_is_subnet.management_vpe_zone_3.crn\n}\n\noutput "management_vpe_id" {\n value = ibm_is_security_group.management_vpc_management_vpe_sg.id\n}\n\noutput "management_vsi_id" {\n value = ibm_is_security_group.management_vpc_management_vsi_sg.id\n}\n\n##############################################################################\n', + data: '##############################################################################\n# Management VPC Outputs\n##############################################################################\n\noutput "name" {\n value = ibm_is_vpc.management_vpc.name\n}\n\noutput "id" {\n value = ibm_is_vpc.management_vpc.id\n}\n\noutput "crn" {\n value = ibm_is_vpc.management_vpc.crn\n}\n\noutput "vsi_zone_1_name" {\n value = ibm_is_subnet.management_vsi_zone_1.name\n}\n\noutput "vsi_zone_1_id" {\n value = ibm_is_subnet.management_vsi_zone_1.id\n}\n\noutput "vsi_zone_1_crn" {\n value = ibm_is_subnet.management_vsi_zone_1.crn\n}\n\noutput "vpn_zone_1_name" {\n value = ibm_is_subnet.management_vpn_zone_1.name\n}\n\noutput "vpn_zone_1_id" {\n value = ibm_is_subnet.management_vpn_zone_1.id\n}\n\noutput "vpn_zone_1_crn" {\n value = ibm_is_subnet.management_vpn_zone_1.crn\n}\n\noutput "vsi_zone_2_name" {\n value = ibm_is_subnet.management_vsi_zone_2.name\n}\n\noutput "vsi_zone_2_id" {\n value = ibm_is_subnet.management_vsi_zone_2.id\n}\n\noutput "vsi_zone_2_crn" {\n value = ibm_is_subnet.management_vsi_zone_2.crn\n}\n\noutput "vsi_zone_3_name" {\n value = ibm_is_subnet.management_vsi_zone_3.name\n}\n\noutput "vsi_zone_3_id" {\n value = ibm_is_subnet.management_vsi_zone_3.id\n}\n\noutput "vsi_zone_3_crn" {\n value = ibm_is_subnet.management_vsi_zone_3.crn\n}\n\noutput "vpe_zone_1_name" {\n value = ibm_is_subnet.management_vpe_zone_1.name\n}\n\noutput "vpe_zone_1_id" {\n value = ibm_is_subnet.management_vpe_zone_1.id\n}\n\noutput "vpe_zone_1_crn" {\n value = ibm_is_subnet.management_vpe_zone_1.crn\n}\n\noutput "vpe_zone_2_name" {\n value = ibm_is_subnet.management_vpe_zone_2.name\n}\n\noutput "vpe_zone_2_id" {\n value = ibm_is_subnet.management_vpe_zone_2.id\n}\n\noutput "vpe_zone_2_crn" {\n value = ibm_is_subnet.management_vpe_zone_2.crn\n}\n\noutput "vpe_zone_3_name" {\n value = ibm_is_subnet.management_vpe_zone_3.name\n}\n\noutput "vpe_zone_3_id" {\n value = ibm_is_subnet.management_vpe_zone_3.id\n}\n\noutput "vpe_zone_3_crn" {\n value = ibm_is_subnet.management_vpe_zone_3.crn\n}\n\noutput "management_vpe_name" {\n value = ibm_is_security_group.management_vpc_management_vpe_sg.name\n}\n\noutput "management_vpe_id" {\n value = ibm_is_security_group.management_vpc_management_vpe_sg.id\n}\n\noutput "management_vsi_name" {\n value = ibm_is_security_group.management_vpc_management_vsi_sg.name\n}\n\noutput "management_vsi_id" {\n value = ibm_is_security_group.management_vpc_management_vsi_sg.id\n}\n\n##############################################################################\n', }, { name: "craig/workload_vpc", data: "" }, { name: "craig/workload_vpc", data: "" }, @@ -155,7 +159,7 @@ describe("craig api", () => { }, { name: "craig/workload_vpc/outputs.tf", - data: '##############################################################################\n# Workload VPC Outputs\n##############################################################################\n\noutput "id" {\n value = ibm_is_vpc.workload_vpc.id\n}\n\noutput "crn" {\n value = ibm_is_vpc.workload_vpc.crn\n}\n\noutput "vsi_zone_1_id" {\n value = ibm_is_subnet.workload_vsi_zone_1.id\n}\n\noutput "vsi_zone_1_crn" {\n value = ibm_is_subnet.workload_vsi_zone_1.crn\n}\n\noutput "vsi_zone_2_id" {\n value = ibm_is_subnet.workload_vsi_zone_2.id\n}\n\noutput "vsi_zone_2_crn" {\n value = ibm_is_subnet.workload_vsi_zone_2.crn\n}\n\noutput "vsi_zone_3_id" {\n value = ibm_is_subnet.workload_vsi_zone_3.id\n}\n\noutput "vsi_zone_3_crn" {\n value = ibm_is_subnet.workload_vsi_zone_3.crn\n}\n\noutput "vpe_zone_1_id" {\n value = ibm_is_subnet.workload_vpe_zone_1.id\n}\n\noutput "vpe_zone_1_crn" {\n value = ibm_is_subnet.workload_vpe_zone_1.crn\n}\n\noutput "vpe_zone_2_id" {\n value = ibm_is_subnet.workload_vpe_zone_2.id\n}\n\noutput "vpe_zone_2_crn" {\n value = ibm_is_subnet.workload_vpe_zone_2.crn\n}\n\noutput "vpe_zone_3_id" {\n value = ibm_is_subnet.workload_vpe_zone_3.id\n}\n\noutput "vpe_zone_3_crn" {\n value = ibm_is_subnet.workload_vpe_zone_3.crn\n}\n\noutput "workload_vpe_id" {\n value = ibm_is_security_group.workload_vpc_workload_vpe_sg.id\n}\n\n##############################################################################\n', + data: '##############################################################################\n# Workload VPC Outputs\n##############################################################################\n\noutput "name" {\n value = ibm_is_vpc.workload_vpc.name\n}\n\noutput "id" {\n value = ibm_is_vpc.workload_vpc.id\n}\n\noutput "crn" {\n value = ibm_is_vpc.workload_vpc.crn\n}\n\noutput "vsi_zone_1_name" {\n value = ibm_is_subnet.workload_vsi_zone_1.name\n}\n\noutput "vsi_zone_1_id" {\n value = ibm_is_subnet.workload_vsi_zone_1.id\n}\n\noutput "vsi_zone_1_crn" {\n value = ibm_is_subnet.workload_vsi_zone_1.crn\n}\n\noutput "vsi_zone_2_name" {\n value = ibm_is_subnet.workload_vsi_zone_2.name\n}\n\noutput "vsi_zone_2_id" {\n value = ibm_is_subnet.workload_vsi_zone_2.id\n}\n\noutput "vsi_zone_2_crn" {\n value = ibm_is_subnet.workload_vsi_zone_2.crn\n}\n\noutput "vsi_zone_3_name" {\n value = ibm_is_subnet.workload_vsi_zone_3.name\n}\n\noutput "vsi_zone_3_id" {\n value = ibm_is_subnet.workload_vsi_zone_3.id\n}\n\noutput "vsi_zone_3_crn" {\n value = ibm_is_subnet.workload_vsi_zone_3.crn\n}\n\noutput "vpe_zone_1_name" {\n value = ibm_is_subnet.workload_vpe_zone_1.name\n}\n\noutput "vpe_zone_1_id" {\n value = ibm_is_subnet.workload_vpe_zone_1.id\n}\n\noutput "vpe_zone_1_crn" {\n value = ibm_is_subnet.workload_vpe_zone_1.crn\n}\n\noutput "vpe_zone_2_name" {\n value = ibm_is_subnet.workload_vpe_zone_2.name\n}\n\noutput "vpe_zone_2_id" {\n value = ibm_is_subnet.workload_vpe_zone_2.id\n}\n\noutput "vpe_zone_2_crn" {\n value = ibm_is_subnet.workload_vpe_zone_2.crn\n}\n\noutput "vpe_zone_3_name" {\n value = ibm_is_subnet.workload_vpe_zone_3.name\n}\n\noutput "vpe_zone_3_id" {\n value = ibm_is_subnet.workload_vpe_zone_3.id\n}\n\noutput "vpe_zone_3_crn" {\n value = ibm_is_subnet.workload_vpe_zone_3.crn\n}\n\noutput "workload_vpe_name" {\n value = ibm_is_security_group.workload_vpc_workload_vpe_sg.name\n}\n\noutput "workload_vpe_id" {\n value = ibm_is_security_group.workload_vpc_workload_vpe_sg.id\n}\n\n##############################################################################\n', }, ]; let mockController = { diff --git a/unit-tests/craig-to-cdktf.test.js b/unit-tests/craig-to-cdktf.test.js index 998458eb..b3a5a2fb 100644 --- a/unit-tests/craig-to-cdktf.test.js +++ b/unit-tests/craig-to-cdktf.test.js @@ -1883,19 +1883,53 @@ describe("craigToCdktf", () => { }, }, output: { - id: { value: "${ibm_is_vpc.management_vpc.id}" }, - crn: { value: "${ibm_is_vpc.management_vpc.crn}" }, + name: { + value: "${ibm_is_vpc.management_vpc.name}", + }, + id: { + value: "${ibm_is_vpc.management_vpc.id}", + }, + crn: { + value: "${ibm_is_vpc.management_vpc.crn}", + }, + vpe_zone_1_name: { + value: "${ibm_is_subnet.management_vpe_zone_1.name}", + }, + vpe_zone_1_id: { + value: "${ibm_is_subnet.management_vpe_zone_1.id}", + }, + vpe_zone_1_crn: { + value: "${ibm_is_subnet.management_vpe_zone_1.crn}", + }, + vpe_zone_2_name: { + value: "${ibm_is_subnet.management_vpe_zone_2.name}", + }, + vpe_zone_2_id: { + value: "${ibm_is_subnet.management_vpe_zone_2.id}", + }, + vpe_zone_2_crn: { + value: "${ibm_is_subnet.management_vpe_zone_2.crn}", + }, + vpe_zone_3_name: { + value: "${ibm_is_subnet.management_vpe_zone_3.name}", + }, + vpe_zone_3_id: { + value: "${ibm_is_subnet.management_vpe_zone_3.id}", + }, + vpe_zone_3_crn: { + value: "${ibm_is_subnet.management_vpe_zone_3.crn}", + }, + vsi_zone_1_name: { + value: "${ibm_is_subnet.management_vsi_zone_1.name}", + }, vsi_zone_1_id: { value: "${ibm_is_subnet.management_vsi_zone_1.id}", }, vsi_zone_1_crn: { value: "${ibm_is_subnet.management_vsi_zone_1.crn}", }, - vpn_zone_1_id: { - value: "${ibm_is_subnet.management_vpn_zone_1.id}", - }, - vpn_zone_1_crn: { - value: "${ibm_is_subnet.management_vpn_zone_1.crn}", + vsi_zone_2_name: { + value: "${ibm_is_subnet.management_vsi_zone_2.name}", }, vsi_zone_2_id: { value: "${ibm_is_subnet.management_vsi_zone_2.id}", @@ -1903,29 +1937,27 @@ describe("craigToCdktf", () => { vsi_zone_2_crn: { value: "${ibm_is_subnet.management_vsi_zone_2.crn}", }, + vsi_zone_3_name: { + value: "${ibm_is_subnet.management_vsi_zone_3.name}", + }, vsi_zone_3_id: { value: "${ibm_is_subnet.management_vsi_zone_3.id}", }, vsi_zone_3_crn: { value: "${ibm_is_subnet.management_vsi_zone_3.crn}", }, - vpe_zone_1_id: { - value: "${ibm_is_subnet.management_vpe_zone_1.id}", - }, - vpe_zone_1_crn: { - value: "${ibm_is_subnet.management_vpe_zone_1.crn}", + vpn_zone_1_name: { + value: "${ibm_is_subnet.management_vpn_zone_1.name}", }, - vpe_zone_2_id: { - value: "${ibm_is_subnet.management_vpe_zone_2.id}", - }, - vpe_zone_2_crn: { - value: "${ibm_is_subnet.management_vpe_zone_2.crn}", + vpn_zone_1_id: { + value: "${ibm_is_subnet.management_vpn_zone_1.id}", }, - vpe_zone_3_id: { - value: "${ibm_is_subnet.management_vpe_zone_3.id}", + vpn_zone_1_crn: { + value: "${ibm_is_subnet.management_vpn_zone_1.crn}", }, - vpe_zone_3_crn: { - value: "${ibm_is_subnet.management_vpe_zone_3.crn}", + management_vpe_sg_name: { + value: + "${ibm_is_security_group.management_vpc_management_vpe_sg_sg.name}", }, management_vpe_sg_id: { value: diff --git a/unit-tests/data-files/config-to-files/modules-slz-network-files.json b/unit-tests/data-files/config-to-files/modules-slz-network-files.json index 04727966..76561dc6 100644 --- a/unit-tests/data-files/config-to-files/modules-slz-network-files.json +++ b/unit-tests/data-files/config-to-files/modules-slz-network-files.json @@ -2,7 +2,7 @@ "management_vpc": { "acl_management_management.tf": "##############################################################################\n# Management Management ACL\n##############################################################################\n\nresource \"ibm_is_network_acl\" \"management_management_acl\" {\n name = \"${var.prefix}-management-management-acl\"\n vpc = ibm_is_vpc.management_vpc.id\n resource_group = var.slz_management_rg_id\n tags = [\n \"slz\",\n \"landing-zone\"\n ]\n rules {\n source = \"161.26.0.0/16\"\n action = \"allow\"\n destination = \"10.0.0.0/8\"\n direction = \"inbound\"\n name = \"allow-ibm-inbound\"\n }\n rules {\n source = \"10.0.0.0/8\"\n action = \"allow\"\n destination = \"10.0.0.0/8\"\n direction = \"inbound\"\n name = \"allow-all-network-inbound\"\n }\n rules {\n source = \"0.0.0.0/0\"\n action = \"allow\"\n destination = \"0.0.0.0/0\"\n direction = \"outbound\"\n name = \"allow-all-outbound\"\n }\n}\n\n##############################################################################\n", "main.tf": "##############################################################################\n# Management VPC\n##############################################################################\n\nresource \"ibm_is_vpc\" \"management_vpc\" {\n name = \"${var.prefix}-management-vpc\"\n resource_group = var.slz_management_rg_id\n tags = var.tags\n no_sg_acl_rules = true\n address_prefix_management = \"manual\"\n default_network_acl_name = null\n default_security_group_name = null\n default_routing_table_name = null\n}\n\nresource \"ibm_is_vpc_address_prefix\" \"management_vsi_zone_1_prefix\" {\n name = \"${var.prefix}-management-vsi-zone-1\"\n vpc = ibm_is_vpc.management_vpc.id\n zone = \"${var.region}-1\"\n cidr = \"10.10.10.0/24\"\n}\n\nresource \"ibm_is_vpc_address_prefix\" \"management_vsi_zone_2_prefix\" {\n name = \"${var.prefix}-management-vsi-zone-2\"\n vpc = ibm_is_vpc.management_vpc.id\n zone = \"${var.region}-2\"\n cidr = \"10.10.20.0/24\"\n}\n\nresource \"ibm_is_vpc_address_prefix\" \"management_vsi_zone_3_prefix\" {\n name = \"${var.prefix}-management-vsi-zone-3\"\n vpc = ibm_is_vpc.management_vpc.id\n zone = \"${var.region}-3\"\n cidr = \"10.10.30.0/24\"\n}\n\nresource \"ibm_is_vpc_address_prefix\" \"management_vpe_zone_1_prefix\" {\n name = \"${var.prefix}-management-vpe-zone-1\"\n vpc = ibm_is_vpc.management_vpc.id\n zone = \"${var.region}-1\"\n cidr = \"10.20.10.0/24\"\n}\n\nresource \"ibm_is_vpc_address_prefix\" \"management_vpe_zone_2_prefix\" {\n name = \"${var.prefix}-management-vpe-zone-2\"\n vpc = ibm_is_vpc.management_vpc.id\n zone = \"${var.region}-2\"\n cidr = \"10.20.20.0/24\"\n}\n\nresource \"ibm_is_vpc_address_prefix\" \"management_vpe_zone_3_prefix\" {\n name = \"${var.prefix}-management-vpe-zone-3\"\n vpc = ibm_is_vpc.management_vpc.id\n zone = \"${var.region}-3\"\n cidr = \"10.20.30.0/24\"\n}\n\nresource \"ibm_is_vpc_address_prefix\" \"management_vpn_zone_1_prefix\" {\n name = \"${var.prefix}-management-vpn-zone-1\"\n vpc = ibm_is_vpc.management_vpc.id\n zone = \"${var.region}-1\"\n cidr = \"10.30.10.0/24\"\n}\n\nresource \"ibm_is_subnet\" \"management_vsi_zone_1\" {\n vpc = ibm_is_vpc.management_vpc.id\n name = \"${var.prefix}-management-vsi-zone-1\"\n zone = \"${var.region}-1\"\n resource_group = var.slz_management_rg_id\n tags = var.tags\n network_acl = ibm_is_network_acl.management_management_acl.id\n ipv4_cidr_block = ibm_is_vpc_address_prefix.management_vsi_zone_1_prefix.cidr\n}\n\nresource \"ibm_is_subnet\" \"management_vpn_zone_1\" {\n vpc = ibm_is_vpc.management_vpc.id\n name = \"${var.prefix}-management-vpn-zone-1\"\n zone = \"${var.region}-1\"\n resource_group = var.slz_management_rg_id\n tags = var.tags\n network_acl = ibm_is_network_acl.management_management_acl.id\n ipv4_cidr_block = ibm_is_vpc_address_prefix.management_vpn_zone_1_prefix.cidr\n}\n\nresource \"ibm_is_subnet\" \"management_vsi_zone_2\" {\n vpc = ibm_is_vpc.management_vpc.id\n name = \"${var.prefix}-management-vsi-zone-2\"\n zone = \"${var.region}-2\"\n resource_group = var.slz_management_rg_id\n tags = var.tags\n network_acl = ibm_is_network_acl.management_management_acl.id\n ipv4_cidr_block = ibm_is_vpc_address_prefix.management_vsi_zone_2_prefix.cidr\n}\n\nresource \"ibm_is_subnet\" \"management_vsi_zone_3\" {\n vpc = ibm_is_vpc.management_vpc.id\n name = \"${var.prefix}-management-vsi-zone-3\"\n zone = \"${var.region}-3\"\n resource_group = var.slz_management_rg_id\n tags = var.tags\n network_acl = ibm_is_network_acl.management_management_acl.id\n ipv4_cidr_block = ibm_is_vpc_address_prefix.management_vsi_zone_3_prefix.cidr\n}\n\nresource \"ibm_is_subnet\" \"management_vpe_zone_1\" {\n vpc = ibm_is_vpc.management_vpc.id\n name = \"${var.prefix}-management-vpe-zone-1\"\n zone = \"${var.region}-1\"\n resource_group = var.slz_management_rg_id\n tags = var.tags\n network_acl = ibm_is_network_acl.management_management_acl.id\n ipv4_cidr_block = ibm_is_vpc_address_prefix.management_vpe_zone_1_prefix.cidr\n}\n\nresource \"ibm_is_subnet\" \"management_vpe_zone_2\" {\n vpc = ibm_is_vpc.management_vpc.id\n name = \"${var.prefix}-management-vpe-zone-2\"\n zone = \"${var.region}-2\"\n resource_group = var.slz_management_rg_id\n tags = var.tags\n network_acl = ibm_is_network_acl.management_management_acl.id\n ipv4_cidr_block = ibm_is_vpc_address_prefix.management_vpe_zone_2_prefix.cidr\n}\n\nresource \"ibm_is_subnet\" \"management_vpe_zone_3\" {\n vpc = ibm_is_vpc.management_vpc.id\n name = \"${var.prefix}-management-vpe-zone-3\"\n zone = \"${var.region}-3\"\n resource_group = var.slz_management_rg_id\n tags = var.tags\n network_acl = ibm_is_network_acl.management_management_acl.id\n ipv4_cidr_block = ibm_is_vpc_address_prefix.management_vpe_zone_3_prefix.cidr\n}\n\n##############################################################################\n", - "outputs.tf": "##############################################################################\n# Management VPC Outputs\n##############################################################################\n\noutput \"id\" {\n value = ibm_is_vpc.management_vpc.id\n}\n\noutput \"crn\" {\n value = ibm_is_vpc.management_vpc.crn\n}\n\noutput \"vsi_zone_1_id\" {\n value = ibm_is_subnet.management_vsi_zone_1.id\n}\n\noutput \"vsi_zone_1_crn\" {\n value = ibm_is_subnet.management_vsi_zone_1.crn\n}\n\noutput \"vpn_zone_1_id\" {\n value = ibm_is_subnet.management_vpn_zone_1.id\n}\n\noutput \"vpn_zone_1_crn\" {\n value = ibm_is_subnet.management_vpn_zone_1.crn\n}\n\noutput \"vsi_zone_2_id\" {\n value = ibm_is_subnet.management_vsi_zone_2.id\n}\n\noutput \"vsi_zone_2_crn\" {\n value = ibm_is_subnet.management_vsi_zone_2.crn\n}\n\noutput \"vsi_zone_3_id\" {\n value = ibm_is_subnet.management_vsi_zone_3.id\n}\n\noutput \"vsi_zone_3_crn\" {\n value = ibm_is_subnet.management_vsi_zone_3.crn\n}\n\noutput \"vpe_zone_1_id\" {\n value = ibm_is_subnet.management_vpe_zone_1.id\n}\n\noutput \"vpe_zone_1_crn\" {\n value = ibm_is_subnet.management_vpe_zone_1.crn\n}\n\noutput \"vpe_zone_2_id\" {\n value = ibm_is_subnet.management_vpe_zone_2.id\n}\n\noutput \"vpe_zone_2_crn\" {\n value = ibm_is_subnet.management_vpe_zone_2.crn\n}\n\noutput \"vpe_zone_3_id\" {\n value = ibm_is_subnet.management_vpe_zone_3.id\n}\n\noutput \"vpe_zone_3_crn\" {\n value = ibm_is_subnet.management_vpe_zone_3.crn\n}\n\noutput \"management_vpe_sg_id\" {\n value = ibm_is_security_group.management_vpc_management_vpe_sg_sg.id\n}\n\n##############################################################################\n", + "outputs.tf": "##############################################################################\n# Management VPC Outputs\n##############################################################################\n\noutput \"name\" {\n value = ibm_is_vpc.management_vpc.name\n}\n\noutput \"id\" {\n value = ibm_is_vpc.management_vpc.id\n}\n\noutput \"crn\" {\n value = ibm_is_vpc.management_vpc.crn\n}\n\noutput \"vsi_zone_1_name\" {\n value = ibm_is_subnet.management_vsi_zone_1.name\n}\n\noutput \"vsi_zone_1_id\" {\n value = ibm_is_subnet.management_vsi_zone_1.id\n}\n\noutput \"vsi_zone_1_crn\" {\n value = ibm_is_subnet.management_vsi_zone_1.crn\n}\n\noutput \"vpn_zone_1_name\" {\n value = ibm_is_subnet.management_vpn_zone_1.name\n}\n\noutput \"vpn_zone_1_id\" {\n value = ibm_is_subnet.management_vpn_zone_1.id\n}\n\noutput \"vpn_zone_1_crn\" {\n value = ibm_is_subnet.management_vpn_zone_1.crn\n}\n\noutput \"vsi_zone_2_name\" {\n value = ibm_is_subnet.management_vsi_zone_2.name\n}\n\noutput \"vsi_zone_2_id\" {\n value = ibm_is_subnet.management_vsi_zone_2.id\n}\n\noutput \"vsi_zone_2_crn\" {\n value = ibm_is_subnet.management_vsi_zone_2.crn\n}\n\noutput \"vsi_zone_3_name\" {\n value = ibm_is_subnet.management_vsi_zone_3.name\n}\n\noutput \"vsi_zone_3_id\" {\n value = ibm_is_subnet.management_vsi_zone_3.id\n}\n\noutput \"vsi_zone_3_crn\" {\n value = ibm_is_subnet.management_vsi_zone_3.crn\n}\n\noutput \"vpe_zone_1_name\" {\n value = ibm_is_subnet.management_vpe_zone_1.name\n}\n\noutput \"vpe_zone_1_id\" {\n value = ibm_is_subnet.management_vpe_zone_1.id\n}\n\noutput \"vpe_zone_1_crn\" {\n value = ibm_is_subnet.management_vpe_zone_1.crn\n}\n\noutput \"vpe_zone_2_name\" {\n value = ibm_is_subnet.management_vpe_zone_2.name\n}\n\noutput \"vpe_zone_2_id\" {\n value = ibm_is_subnet.management_vpe_zone_2.id\n}\n\noutput \"vpe_zone_2_crn\" {\n value = ibm_is_subnet.management_vpe_zone_2.crn\n}\n\noutput \"vpe_zone_3_name\" {\n value = ibm_is_subnet.management_vpe_zone_3.name\n}\n\noutput \"vpe_zone_3_id\" {\n value = ibm_is_subnet.management_vpe_zone_3.id\n}\n\noutput \"vpe_zone_3_crn\" {\n value = ibm_is_subnet.management_vpe_zone_3.crn\n}\n\noutput \"management_vpe_sg_name\" {\n value = ibm_is_security_group.management_vpc_management_vpe_sg_sg.name\n}\n\noutput \"management_vpe_sg_id\" {\n value = ibm_is_security_group.management_vpc_management_vpe_sg_sg.id\n}\n\n##############################################################################\n", "rt_routing_table.tf": "##############################################################################\n# Routing Table Routing Table\n##############################################################################\n\nresource \"ibm_is_vpc_routing_table\" \"management_vpc_routing_table_table\" {\n name = \"${var.prefix}-management-vpc-routing-table-table\"\n vpc = ibm_is_vpc.management_vpc.id\n route_direct_link_ingress = true\n route_transit_gateway_ingress = true\n route_vpc_zone_ingress = true\n}\n\nresource \"ibm_is_vpc_routing_table_route\" \"management_vpc_routing_table_table_test_route_route\" {\n vpc = ibm_is_vpc.management_vpc.id\n routing_table = ibm_is_vpc_routing_table.management_vpc_routing_table_table.routing_table\n zone = \"${var.region}-1\"\n name = \"${var.prefix}-management-routing-table-test-route-route\"\n destination = \"1.2.3.4/5\"\n action = \"delegate\"\n next_hop = \"0.0.0.0\"\n}\n\n##############################################################################\n", "sg_management_vpe_sg.tf": "##############################################################################\n# Security Group Management VPE Sg\n##############################################################################\n\nresource \"ibm_is_security_group\" \"management_vpc_management_vpe_sg_sg\" {\n name = \"${var.prefix}-management-management-vpe-sg-sg\"\n vpc = ibm_is_vpc.management_vpc.id\n resource_group = var.slz_management_rg_id\n tags = [\n \"slz\",\n \"landing-zone\"\n ]\n}\n\nresource \"ibm_is_security_group_rule\" \"management_vpc_management_vpe_sg_sg_rule_allow_ibm_inbound\" {\n group = ibm_is_security_group.management_vpc_management_vpe_sg_sg.id\n remote = \"161.26.0.0/16\"\n direction = \"inbound\"\n}\n\nresource \"ibm_is_security_group_rule\" \"management_vpc_management_vpe_sg_sg_rule_allow_vpc_inbound\" {\n group = ibm_is_security_group.management_vpc_management_vpe_sg_sg.id\n remote = \"10.0.0.0/8\"\n direction = \"inbound\"\n}\n\nresource \"ibm_is_security_group_rule\" \"management_vpc_management_vpe_sg_sg_rule_allow_vpc_outbound\" {\n group = ibm_is_security_group.management_vpc_management_vpe_sg_sg.id\n remote = \"10.0.0.0/8\"\n direction = \"outbound\"\n}\n\nresource \"ibm_is_security_group_rule\" \"management_vpc_management_vpe_sg_sg_rule_allow_ibm_tcp_53_outbound\" {\n group = ibm_is_security_group.management_vpc_management_vpe_sg_sg.id\n remote = \"161.26.0.0/16\"\n direction = \"outbound\"\n tcp {\n port_min = 53\n port_max = 53\n }\n}\n\nresource \"ibm_is_security_group_rule\" \"management_vpc_management_vpe_sg_sg_rule_allow_ibm_tcp_80_outbound\" {\n group = ibm_is_security_group.management_vpc_management_vpe_sg_sg.id\n remote = \"161.26.0.0/16\"\n direction = \"outbound\"\n tcp {\n port_min = 80\n port_max = 80\n }\n}\n\nresource \"ibm_is_security_group_rule\" \"management_vpc_management_vpe_sg_sg_rule_allow_ibm_tcp_443_outbound\" {\n group = ibm_is_security_group.management_vpc_management_vpe_sg_sg.id\n remote = \"161.26.0.0/16\"\n direction = \"outbound\"\n tcp {\n port_min = 443\n port_max = 443\n }\n}\n\n##############################################################################\n", "variables.tf": "##############################################################################\n# Management VPC Variables\n##############################################################################\n\nvariable \"tags\" {\n description = \"List of tags\"\n type = list(string)\n}\n\nvariable \"region\" {\n description = \"IBM Cloud Region where resources will be provisioned\"\n type = string\n}\n\nvariable \"prefix\" {\n description = \"Name prefix that will be prepended to named resources\"\n type = string\n}\n\nvariable \"slz_management_rg_id\" {\n description = \"ID for the resource group slz-management-rg\"\n type = string\n}\n\n##############################################################################\n", diff --git a/unit-tests/forms/wizard.test.js b/unit-tests/forms/wizard.test.js index c6d23bf1..6687b455 100644 --- a/unit-tests/forms/wizard.test.js +++ b/unit-tests/forms/wizard.test.js @@ -57,7 +57,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.12.1", + craig_version: "1.12.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -972,7 +972,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.12.1", + craig_version: "1.12.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -1886,7 +1886,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.12.1", + craig_version: "1.12.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -2394,7 +2394,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.12.1", + craig_version: "1.12.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -2893,7 +2893,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.12.1", + craig_version: "1.12.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -3469,7 +3469,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.12.1", + craig_version: "1.12.2", no_vpn_secrets_manager_auth: false, }, resource_groups: [ @@ -3636,7 +3636,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.12.1", + craig_version: "1.12.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -4204,7 +4204,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.12.1", + craig_version: "1.12.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -4746,7 +4746,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.12.1", + craig_version: "1.12.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -5293,7 +5293,7 @@ describe("setup wizard", () => { enable_classic: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.12.1", + craig_version: "1.12.2", no_vpn_secrets_manager_auth: false, }, resource_groups: [ @@ -5782,7 +5782,7 @@ describe("setup wizard", () => { enable_power_vs: true, enable_classic: false, power_vs_zones: ["dal10"], - craig_version: "1.12.1", + craig_version: "1.12.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -6281,7 +6281,7 @@ describe("setup wizard", () => { enable_power_vs: true, enable_classic: false, power_vs_zones: ["dal10"], - craig_version: "1.12.1", + craig_version: "1.12.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, diff --git a/unit-tests/json-to-iac/outputs.test.js b/unit-tests/json-to-iac/outputs.test.js new file mode 100644 index 00000000..b9257208 --- /dev/null +++ b/unit-tests/json-to-iac/outputs.test.js @@ -0,0 +1,586 @@ +const { assert } = require("chai"); +const { outputsTf } = require("../../client/src/lib"); + +describe("outputs", () => { + describe("outputsTf", () => { + it("should return correct outputs file", () => { + let config = { + _options: { + craig_version: "1.12.1", + prefix: "jv-dev", + region: "eu-de", + tags: ["hello", "world"], + dynamic_subnets: false, + power_vs_zones: [], + zones: "1", + endpoints: "private", + account_id: null, + power_vs_high_availability: false, + fs_cloud: false, + enable_power_vs: false, + template: "VSI", + enable_classic: false, + }, + access_groups: [], + appid: [], + atracker: { + add_route: true, + bucket: null, + locations: ["global"], + enabled: false, + type: "cos", + name: "atracker", + cos_key: null, + target_name: "atracker-cos", + instance: false, + plan: "lite", + resource_group: null, + }, + cbr_rules: [], + cbr_zones: [], + clusters: [], + dns: [], + event_streams: [], + f5_vsi: [], + iam_account_settings: { + enable: false, + mfa: null, + allowed_ip_addresses: null, + include_history: false, + if_match: null, + max_sessions_per_identity: null, + restrict_create_service_id: null, + restrict_create_platform_apikey: null, + session_expiration_in_seconds: null, + session_invalidation_in_seconds: null, + }, + icd: [], + key_management: [ + { + keys: [ + { + dual_auth_delete: false, + name: "slz-atracker-key", + endpoint: "private", + force_delete: false, + root_key: true, + key_ring: "ring", + rotation: 12, + }, + { + dual_auth_delete: false, + name: "key", + endpoint: "private", + force_delete: false, + root_key: true, + key_ring: "ring", + rotation: 12, + }, + { + dual_auth_delete: false, + name: "slz-vsi-volume-key", + endpoint: "private", + force_delete: false, + root_key: true, + key_ring: "ring", + rotation: 12, + }, + ], + authorize_vpc_reader_role: true, + name: "kms", + resource_group: "service-rg", + use_data: false, + use_hs_crypto: false, + }, + ], + load_balancers: [], + logdna: { + enabled: false, + plan: "lite", + endpoints: "private", + platform_logs: false, + resource_group: "service-rg", + cos: null, + bucket: null, + }, + object_storage: [ + { + kms: "kms", + name: "cos", + plan: "standard", + resource_group: "service-rg", + use_random_suffix: true, + use_data: false, + buckets: [ + { + endpoint: "public", + force_delete: true, + kms_key: "key", + name: "management-bucket", + storage_class: "standard", + use_random_suffix: true, + }, + { + endpoint: "public", + force_delete: true, + kms_key: "key", + name: "workload-bucket", + storage_class: "standard", + use_random_suffix: true, + }, + ], + keys: [], + }, + ], + power: [], + power_instances: [], + power_volumes: [], + resource_groups: [ + { + name: "service-rg", + use_data: false, + use_prefix: true, + }, + { + name: "asset-development", + use_data: true, + use_prefix: true, + }, + { + name: "workload-rg", + use_data: false, + use_prefix: true, + }, + ], + routing_tables: [], + scc: { + credential_description: null, + id: null, + passphrase: null, + name: "", + location: "us", + collector_description: null, + is_public: false, + scope_description: null, + enable: false, + }, + secrets_manager: [], + security_groups: [ + { + vpc: "workload", + }, + { + vpc: "management", + name: "management-vsi", + resource_group: "asset-development", + rules: [ + { + direction: "outbound", + name: "allow-vpc-outbound", + source: "0.0.0.0/0", + tcp: { + port_min: 443, + port_max: 443, + source_port_max: null, + source_port_min: null, + }, + icmp: { + type: null, + code: null, + }, + udp: { + port_min: null, + port_max: null, + }, + sg: "management-vsi", + vpc: "management", + ruleProtocol: "tcp", + port_min: "443", + port_max: "443", + type: null, + code: null, + }, + { + direction: "outbound", + name: "allow-ibm-tcp-53-outbound", + source: "161.26.0.0/16", + tcp: { + port_min: 343, + port_max: null, + source_port_max: null, + source_port_min: null, + }, + icmp: { + type: null, + code: null, + }, + udp: { + port_min: null, + port_max: null, + }, + sg: "management-vsi", + vpc: "management", + ruleProtocol: "tcp", + port_min: "343", + port_max: null, + type: null, + code: null, + }, + { + direction: "outbound", + name: "allow-ibm-tcp-80-outbound", + source: "161.26.0.0/16", + tcp: { + port_max: 80, + port_min: 80, + }, + icmp: { + code: null, + type: null, + }, + udp: { + port_max: null, + port_min: null, + }, + sg: "management-vsi", + vpc: "management", + ruleProtocol: "tcp", + port_min: null, + port_max: null, + type: null, + code: null, + }, + { + direction: "outbound", + name: "allow-ibm-tcp-443-outbound", + source: "161.26.0.0/16", + tcp: { + port_min: 443, + port_max: 443, + source_port_max: null, + source_port_min: null, + }, + icmp: { + type: null, + code: null, + }, + udp: { + port_min: null, + port_max: null, + }, + sg: "management-vsi", + vpc: "management", + ruleProtocol: "tcp", + port_min: "443", + port_max: "443", + type: null, + code: null, + }, + ], + }, + ], + ssh_keys: [ + { + name: "jv-dev", + use_data: false, + resource_group: "asset-development", + public_key: "", + }, + ], + sysdig: { + enabled: false, + plan: "graduated-tier", + resource_group: "service-rg", + name: "sysdig", + platform_logs: false, + }, + teleport_vsi: [], + transit_gateways: [ + { + global: false, + name: "transit-gateway", + resource_group: "service-rg", + connections: [ + { + tgw: "transit-gateway", + vpc: "management", + }, + ], + use_data: false, + prefix_filters: [], + gre_tunnels: [], + }, + ], + virtual_private_endpoints: [], + vpcs: [ + { + name: "management", + public_gateways: [], + acls: [ + { + resource_group: "asset-development", + name: "management", + vpc: "management", + rules: [ + { + action: "allow", + destination: "10.0.0.0/8", + direction: "inbound", + name: "allow-ibm-inbound", + source: "0.0.0.0/0", + icmp: { + type: null, + code: null, + }, + tcp: { + port_min: null, + port_max: null, + source_port_min: null, + source_port_max: null, + }, + udp: { + port_min: null, + port_max: null, + source_port_min: null, + source_port_max: null, + }, + vpc: "management", + acl: "management", + ruleProtocol: "all", + port_min: null, + port_max: null, + type: null, + code: null, + source_port_min: null, + source_port_max: null, + }, + { + action: "allow", + destination: "10.0.0.0/8", + direction: "inbound", + name: "allow-all-network-inbound", + source: "10.0.0.0/8", + icmp: { + type: null, + code: null, + }, + tcp: { + port_min: null, + port_max: null, + source_port_min: null, + source_port_max: null, + }, + udp: { + port_min: null, + port_max: null, + source_port_min: null, + source_port_max: null, + }, + vpc: "management", + acl: "management", + ruleProtocol: "all", + port_min: null, + port_max: null, + type: null, + code: null, + source_port_min: null, + source_port_max: null, + }, + { + action: "allow", + destination: "0.0.0.0/0", + direction: "outbound", + name: "allow-all-outbound", + source: "0.0.0.0/0", + icmp: { + type: null, + code: null, + }, + tcp: { + port_min: null, + port_max: null, + source_port_min: null, + source_port_max: null, + }, + udp: { + port_min: null, + port_max: null, + source_port_min: null, + source_port_max: null, + }, + vpc: "management", + acl: "management", + ruleProtocol: "all", + port_min: null, + port_max: null, + type: null, + code: null, + source_port_min: null, + source_port_max: null, + }, + { + name: "frog", + action: "allow", + direction: "inbound", + icmp: { + type: null, + code: null, + }, + tcp: { + port_min: null, + port_max: null, + source_port_min: null, + source_port_max: null, + }, + udp: { + port_min: null, + port_max: null, + source_port_min: null, + source_port_max: null, + }, + source: "161.26.0.0/16", + destination: "0.0.0.0", + acl: "management", + vpc: "management", + ruleProtocol: "all", + port_min: null, + port_max: null, + type: null, + code: null, + source_port_min: null, + source_port_max: null, + }, + ], + use_data: false, + }, + ], + subnets: [ + { + name: "vsi-zone-1", + network_acl: "management", + cidr: "10.10.10.0/24", + has_prefix: true, + vpc: "management", + zone: 1, + public_gateway: false, + resource_group: "asset-development", + }, + ], + address_prefixes: [ + { + name: "vsi-zone-1", + cidr: "10.10.10.0/24", + zone: 1, + vpc: "management", + }, + ], + bucket: "management-bucket", + manual_address_prefix_management: true, + cos: "cos", + classic_access: false, + default_network_acl_name: null, + default_routing_table_name: null, + default_security_group_name: null, + resource_group: "asset-development", + publicGateways: [], + subnetTiers: [ + { + name: "vsi", + zones: 1, + }, + ], + use_data: false, + }, + ], + vpn_gateways: [], + vpn_servers: [], + vsi: [ + { + kms: "kms", + encryption_key: "slz-vsi-volume-key", + image: "ibm-ubuntu-20-04-6-minimal-amd64-3", + profile: "cx2-4x8", + name: "jv-dev-server", + security_groups: ["management-vsi"], + ssh_keys: ["jv-dev"], + subnets: ["vsi-zone-1"], + vpc: "management", + vsi_per_subnet: 1, + resource_group: "asset-development", + override_vsi_name: null, + user_data: null, + network_interfaces: [], + volumes: [], + image_name: + "Ubuntu Linux 20.04 LTS Focal Fossa Minimal Install (amd64) [ibm-ubuntu-20-04-6-minimal-amd64-3]", + enable_floating_ip: true, + primary_interface_ip_spoofing: false, + }, + ], + classic_ssh_keys: [], + classic_vlans: [], + vtl: [], + classic_gateways: [], + cis: [], + scc_v2: { + enable: false, + resource_group: null, + region: "", + account_id: "${var.account_id}", + profile_attachments: [], + }, + cis_glbs: [], + fortigate_vnf: [], + _schematics: { + workspace_name: "jv-dev", + workspace_url: + "https://cloud.ibm.com/schematics/workspaces/us-south.workspace.jv-dev.81837d43", + }, + }; + let actualData = outputsTf(config); + let expectedData = `############################################################################## +# Management VPC Outputs +############################################################################## + +output "management_vpc_name" { + value = module.management_vpc.name +} + +output "management_vpc_id" { + value = module.management_vpc.id +} + +output "management_vpc_crn" { + value = module.management_vpc.crn +} + +output "management_vpc_subnet_vsi_zone_1_name" { + value = module.management_vpc.vsi_zone_1_name +} + +output "management_vpc_subnet_vsi_zone_1_id" { + value = module.management_vpc.vsi_zone_1_id +} + +output "management_vpc_subnet_vsi_zone_1_crn" { + value = module.management_vpc.vsi_zone_1_crn +} + +output "management_vpc_security_group_management_vsi_name" { + value = module.management_vpc.management_vsi_name +} + +output "management_vpc_security_group_management_vsi_id" { + value = module.management_vpc.management_vsi_id +} + +############################################################################## +`; + assert.deepEqual( + actualData, + expectedData, + "it should return correct outputs" + ); + }); + }); +}); diff --git a/unit-tests/json-to-iac/vpc.test.js b/unit-tests/json-to-iac/vpc.test.js index 763e183c..b302432c 100644 --- a/unit-tests/json-to-iac/vpc.test.js +++ b/unit-tests/json-to-iac/vpc.test.js @@ -4277,7 +4277,7 @@ resource "ibm_is_subnet" "customer_a_subnet_tier_zone_2" { "sg_vsi_sg.tf": '##############################################################################\n# Security Group VSI Sg\n##############################################################################\n\nresource "ibm_is_security_group" "customer_a_vpc_vsi_sg_sg" {\n name = "${var.prefix}-customer-a-vsi-sg-sg"\n vpc = ibm_is_vpc.customer_a_vpc.id\n resource_group = var.craig_rg_id\n tags = [\n "hello",\n "world"\n ]\n}\n\nresource "ibm_is_security_group_rule" "customer_a_vpc_vsi_sg_sg_rule_ssh" {\n group = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n remote = "0.0.0.0"\n direction = "inbound"\n tcp {\n port_min = 22\n port_max = 22\n }\n}\n\nresource "ibm_is_security_group_rule" "customer_a_vpc_vsi_sg_sg_rule_ping" {\n group = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n remote = "0.0.0.0"\n direction = "inbound"\n icmp {\n type = 8\n code = 8\n }\n}\n\n##############################################################################\n', "outputs.tf": - '##############################################################################\n# Customer AVPC Outputs\n##############################################################################\n\noutput "id" {\n value = ibm_is_vpc.customer_a_vpc.id\n}\n\noutput "crn" {\n value = ibm_is_vpc.customer_a_vpc.crn\n}\n\noutput "subnet_tier_zone_1_id" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.id\n}\n\noutput "subnet_tier_zone_1_crn" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.crn\n}\n\noutput "subnet_tier_zone_2_id" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.id\n}\n\noutput "subnet_tier_zone_2_crn" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.crn\n}\n\noutput "vsi_sg_id" {\n value = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n}\n\n##############################################################################\n', + '##############################################################################\n# Customer AVPC Outputs\n##############################################################################\n\noutput "name" {\n value = ibm_is_vpc.customer_a_vpc.name\n}\n\noutput "id" {\n value = ibm_is_vpc.customer_a_vpc.id\n}\n\noutput "crn" {\n value = ibm_is_vpc.customer_a_vpc.crn\n}\n\noutput "subnet_tier_zone_1_name" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.name\n}\n\noutput "subnet_tier_zone_1_id" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.id\n}\n\noutput "subnet_tier_zone_1_crn" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.crn\n}\n\noutput "subnet_tier_zone_2_name" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.name\n}\n\noutput "subnet_tier_zone_2_id" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.id\n}\n\noutput "subnet_tier_zone_2_crn" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.crn\n}\n\noutput "vsi_sg_name" {\n value = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.name\n}\n\noutput "vsi_sg_id" {\n value = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n}\n\n##############################################################################\n', }, "main.tf": '##############################################################################\n# Customer AVPC Module\n##############################################################################\n\nmodule "customer_a_vpc" {\n source = "./customer_a_vpc"\n region = var.region\n prefix = var.prefix\n craig_rg_id = ibm_resource_group.craig_rg.id\n tags = [\n "hello",\n "world"\n ]\n}\n\n##############################################################################\n', @@ -4696,7 +4696,7 @@ resource "ibm_is_subnet" "customer_a_subnet_tier_zone_2" { "sg_vsi_sg.tf": '##############################################################################\n# Security Group VSI Sg\n##############################################################################\n\nresource "ibm_is_security_group" "customer_a_vpc_vsi_sg_sg" {\n name = "${var.prefix}-customer-a-vsi-sg-sg"\n vpc = ibm_is_vpc.customer_a_vpc.id\n resource_group = var.craig_rg_id\n tags = [\n "hello",\n "world"\n ]\n}\n\nresource "ibm_is_security_group_rule" "customer_a_vpc_vsi_sg_sg_rule_ssh" {\n group = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n remote = "0.0.0.0"\n direction = "inbound"\n tcp {\n port_min = 22\n port_max = 22\n }\n}\n\nresource "ibm_is_security_group_rule" "customer_a_vpc_vsi_sg_sg_rule_ping" {\n group = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n remote = "0.0.0.0"\n direction = "inbound"\n icmp {\n type = 8\n code = 8\n }\n}\n\n##############################################################################\n', "outputs.tf": - '##############################################################################\n# Customer AVPC Outputs\n##############################################################################\n\noutput "id" {\n value = data.ibm_is_vpc.customer_a_vpc.id\n}\n\noutput "crn" {\n value = data.ibm_is_vpc.customer_a_vpc.crn\n}\n\noutput "subnet_tier_zone_1_id" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.id\n}\n\noutput "subnet_tier_zone_1_crn" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.crn\n}\n\noutput "subnet_tier_zone_2_id" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.id\n}\n\noutput "subnet_tier_zone_2_crn" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.crn\n}\n\noutput "vsi_sg_id" {\n value = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n}\n\n##############################################################################\n', + '##############################################################################\n# Customer AVPC Outputs\n##############################################################################\n\noutput "name" {\n value = data.ibm_is_vpc.customer_a_vpc.name\n}\n\noutput "id" {\n value = data.ibm_is_vpc.customer_a_vpc.id\n}\n\noutput "crn" {\n value = data.ibm_is_vpc.customer_a_vpc.crn\n}\n\noutput "subnet_tier_zone_1_name" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.name\n}\n\noutput "subnet_tier_zone_1_id" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.id\n}\n\noutput "subnet_tier_zone_1_crn" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.crn\n}\n\noutput "subnet_tier_zone_2_name" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.name\n}\n\noutput "subnet_tier_zone_2_id" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.id\n}\n\noutput "subnet_tier_zone_2_crn" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.crn\n}\n\noutput "vsi_sg_name" {\n value = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.name\n}\n\noutput "vsi_sg_id" {\n value = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n}\n\n##############################################################################\n', }, "main.tf": '##############################################################################\n# Customer AVPC Module\n##############################################################################\n\nmodule "customer_a_vpc" {\n source = "./customer_a_vpc"\n region = var.region\n prefix = var.prefix\n craig_rg_id = ibm_resource_group.craig_rg.id\n tags = [\n "hello",\n "world"\n ]\n}\n\n##############################################################################\n', @@ -5116,7 +5116,7 @@ resource "ibm_is_subnet" "customer_a_subnet_tier_zone_2" { "sg_vsi_sg.tf": '##############################################################################\n# Security Group VSI Sg\n##############################################################################\n\ndata "ibm_is_security_group" "customer_a_vpc_vsi_sg_sg" {\n name = "vsi-sg"\n vpc = data.ibm_is_vpc.customer_a_vpc.id\n}\n\nresource "ibm_is_security_group_rule" "customer_a_vpc_vsi_sg_sg_rule_ssh" {\n group = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n remote = "0.0.0.0"\n direction = "inbound"\n tcp {\n port_min = 22\n port_max = 22\n }\n}\n\nresource "ibm_is_security_group_rule" "customer_a_vpc_vsi_sg_sg_rule_ping" {\n group = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n remote = "0.0.0.0"\n direction = "inbound"\n icmp {\n type = 8\n code = 8\n }\n}\n\n##############################################################################\n', "outputs.tf": - '##############################################################################\n# Customer AVPC Outputs\n##############################################################################\n\noutput "id" {\n value = data.ibm_is_vpc.customer_a_vpc.id\n}\n\noutput "crn" {\n value = data.ibm_is_vpc.customer_a_vpc.crn\n}\n\noutput "subnet_tier_zone_1_id" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.id\n}\n\noutput "subnet_tier_zone_1_crn" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.crn\n}\n\noutput "subnet_tier_zone_2_id" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.id\n}\n\noutput "subnet_tier_zone_2_crn" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.crn\n}\n\noutput "vsi_sg_id" {\n value = data.ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n}\n\n##############################################################################\n', + '##############################################################################\n# Customer AVPC Outputs\n##############################################################################\n\noutput "name" {\n value = data.ibm_is_vpc.customer_a_vpc.name\n}\n\noutput "id" {\n value = data.ibm_is_vpc.customer_a_vpc.id\n}\n\noutput "crn" {\n value = data.ibm_is_vpc.customer_a_vpc.crn\n}\n\noutput "subnet_tier_zone_1_name" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.name\n}\n\noutput "subnet_tier_zone_1_id" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.id\n}\n\noutput "subnet_tier_zone_1_crn" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_1.crn\n}\n\noutput "subnet_tier_zone_2_name" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.name\n}\n\noutput "subnet_tier_zone_2_id" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.id\n}\n\noutput "subnet_tier_zone_2_crn" {\n value = ibm_is_subnet.customer_a_subnet_tier_zone_2.crn\n}\n\noutput "vsi_sg_name" {\n value = data.ibm_is_security_group.customer_a_vpc_vsi_sg_sg.name\n}\n\noutput "vsi_sg_id" {\n value = data.ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n}\n\n##############################################################################\n', }, "main.tf": '##############################################################################\n# Customer AVPC Module\n##############################################################################\n\nmodule "customer_a_vpc" {\n source = "./customer_a_vpc"\n region = var.region\n prefix = var.prefix\n craig_rg_id = ibm_resource_group.craig_rg.id\n tags = [\n "hello",\n "world"\n ]\n}\n\n##############################################################################\n', @@ -5500,7 +5500,7 @@ resource "ibm_is_subnet" "customer_a_subnet_tier_zone_2" { "sg_vsi_sg.tf": '##############################################################################\n# Security Group VSI Sg\n##############################################################################\n\ndata "ibm_is_security_group" "customer_a_vpc_vsi_sg_sg" {\n name = "vsi-sg"\n vpc = data.ibm_is_vpc.customer_a_vpc.id\n}\n\nresource "ibm_is_security_group_rule" "customer_a_vpc_vsi_sg_sg_rule_ssh" {\n group = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n remote = "0.0.0.0"\n direction = "inbound"\n tcp {\n port_min = 22\n port_max = 22\n }\n}\n\nresource "ibm_is_security_group_rule" "customer_a_vpc_vsi_sg_sg_rule_ping" {\n group = ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n remote = "0.0.0.0"\n direction = "inbound"\n icmp {\n type = 8\n code = 8\n }\n}\n\n##############################################################################\n', "outputs.tf": - '##############################################################################\n# Customer AVPC Outputs\n##############################################################################\n\noutput "id" {\n value = data.ibm_is_vpc.customer_a_vpc.id\n}\n\noutput "crn" {\n value = data.ibm_is_vpc.customer_a_vpc.crn\n}\n\noutput "subnet_tier_zone_1_id" {\n value = data.ibm_is_subnet.customer_a_subnet_tier_zone_1.id\n}\n\noutput "subnet_tier_zone_1_crn" {\n value = data.ibm_is_subnet.customer_a_subnet_tier_zone_1.crn\n}\n\noutput "vsi_sg_id" {\n value = data.ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n}\n\n##############################################################################\n', + '##############################################################################\n# Customer AVPC Outputs\n##############################################################################\n\noutput "name" {\n value = data.ibm_is_vpc.customer_a_vpc.name\n}\n\noutput "id" {\n value = data.ibm_is_vpc.customer_a_vpc.id\n}\n\noutput "crn" {\n value = data.ibm_is_vpc.customer_a_vpc.crn\n}\n\noutput "subnet_tier_zone_1_name" {\n value = data.ibm_is_subnet.customer_a_subnet_tier_zone_1.name\n}\n\noutput "subnet_tier_zone_1_id" {\n value = data.ibm_is_subnet.customer_a_subnet_tier_zone_1.id\n}\n\noutput "subnet_tier_zone_1_crn" {\n value = data.ibm_is_subnet.customer_a_subnet_tier_zone_1.crn\n}\n\noutput "vsi_sg_name" {\n value = data.ibm_is_security_group.customer_a_vpc_vsi_sg_sg.name\n}\n\noutput "vsi_sg_id" {\n value = data.ibm_is_security_group.customer_a_vpc_vsi_sg_sg.id\n}\n\n##############################################################################\n', }, "main.tf": '##############################################################################\n# Customer AVPC Module\n##############################################################################\n\nmodule "customer_a_vpc" {\n source = "./customer_a_vpc"\n region = var.region\n prefix = var.prefix\n craig_rg_id = ibm_resource_group.craig_rg.id\n tags = [\n "hello",\n "world"\n ]\n}\n\n##############################################################################\n', From 3d85ee2d3fce65e559091459ee5de78c4849a83b Mon Sep 17 00:00:00 2001 From: jvallexm Date: Tue, 5 Mar 2024 12:05:55 -0500 Subject: [PATCH 02/16] Issue 1598: Additional VPN Server Certificate (#1604) * feat: power vs v2 enhancements * feat: variables * changelog * fix: cert * fix: subforms --- CHANGELOG.md | 3 + .../src/components/forms/utils/ToggleForm.js | 6 +- client/src/lib/docs/release-notes.json | 8 +- client/src/lib/json-to-iac/variables.js | 9 +- client/src/lib/json-to-iac/vpn-server.js | 72 +++- unit-tests/json-to-iac/variables.test.js | 12 + unit-tests/json-to-iac/vpn-server.test.js | 379 +++++++++++++++++- 7 files changed, 474 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b17eb09..6fd8da57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,9 +13,12 @@ All notable changes to this project will be documented in this file. - VPC names, IDs, and CRNs are exported as outputs - Subnet names, IDs, and CRNS are exported as outputs - VPC Security Group names, and IDs are exported as outputs +- When bringing your own certificate for VPN Servers, two separate certificates are now imported. Additional variables have been added to support the new imported certificate ### Fixes +- Fixed an issue causing certificates imported into an existing Secrets Manager instance to have incorrect references within Terraform +- Fixed an issue causing nested forms to not be shown by default when invalid ## 1.12.1 diff --git a/client/src/components/forms/utils/ToggleForm.js b/client/src/components/forms/utils/ToggleForm.js index aa596bca..df560f84 100644 --- a/client/src/components/forms/utils/ToggleForm.js +++ b/client/src/components/forms/utils/ToggleForm.js @@ -1,6 +1,6 @@ import React from "react"; import PropTypes from "prop-types"; -import { disableSave, propsMatchState } from "../../../lib"; +import { disableSave, forceShowForm, propsMatchState } from "../../../lib"; import StatefulTabs from "./StatefulTabs"; import { StatelessFormWrapper } from "./StatelessFormWrapper"; import DynamicForm from "../DynamicForm"; @@ -192,7 +192,7 @@ class CraigToggleForm extends React.Component { } shouldShow() { - return this.props.forceOpen(this.state, this.props); + return forceShowForm(this.state, this.props); } networkRuleOrderDidChange(didNotChange) { @@ -247,7 +247,7 @@ class CraigToggleForm extends React.Component { > { if (server.bring_your_own_cert) { - ["cert_pem", "private_key_pem", "intermediate_pem"].forEach((certVar) => { + [ + "cert_pem", + "private_key_pem", + "intermediate_pem", + "client_ca_cert_pem", + "client_ca_private_key_pem", + ].forEach((certVar) => { variables[ snakeCase(`${server.vpc} vpn_server ${server.name} ${certVar}`) ] = { diff --git a/client/src/lib/json-to-iac/vpn-server.js b/client/src/lib/json-to-iac/vpn-server.js index 484c9e0f..71ba2c1b 100644 --- a/client/src/lib/json-to-iac/vpn-server.js +++ b/client/src/lib/json-to-iac/vpn-server.js @@ -4,6 +4,8 @@ const { isNullOrEmptyString, titleCase, contains, + splatContains, + revision, } = require("lazy-z"); const { rgIdRef, tfBlock, jsonToTfPrint, kebabName } = require("./utils"); const { formatAddressPrefix } = require("./vpc"); @@ -84,7 +86,11 @@ function ibmIsVpnServer(server, craig) { contains(["byo", "INSECURE"], server.method) ) { serverData.client_authentication[0].client_ca_crn = - overrideCert || server.client_ca_crn; + overrideCert && server.method === "certificate" + ? overrideCert.replace(/imported(?=\w+\.crn)/, "client_ca_imported") + : overrideCert + ? overrideCert.replace(/imported(?=\w+\.crn)/, "client_ca_imported") + : server.client_ca_crn; } else { serverData.client_authentication[0].identity_provider = "iam"; } @@ -128,7 +134,7 @@ function ibmIsVpnServerRoute(server, route) { * @param {*} server * @returns {string} Terraform code */ -function DANGER_formatDevRsaCertificate(server) { +function DANGER_formatDevRsaCertificate(server, config) { let dangerCertTf = ""; ["ca_key", "client_key", "server_key"].forEach((key) => { dangerCertTf += jsonToTfPrint( @@ -209,7 +215,13 @@ function DANGER_formatDevRsaCertificate(server) { "ibm_sm_imported_certificate", `danger ${server.vpc} vpn server ${server.name} dev cert`, { - instance_id: `\${ibm_resource_instance.${snakeCase( + instance_id: `\${${ + splatContains(config.secrets_manager, "name", server.secrets_manager) && + new revision(config).child("secrets_manager", server.secrets_manager) + .data.use_data + ? "data." + : "" + }ibm_resource_instance.${snakeCase( server.secrets_manager )}_secrets_manager.guid}`, region: varDotRegion, @@ -254,9 +266,21 @@ function formatVpnServer(server, config) { ? jsonToTfPrint( "resource", "ibm_sm_imported_certificate", - data.name + "_imported_certificate", + snakeCase(data.name) + "_imported_certificate", { - instance_id: `\${ibm_resource_instance.${snakeCase( + instance_id: `\${${ + splatContains( + config.secrets_manager, + "name", + server.secrets_manager + ) && + new revision(config).child( + "secrets_manager", + server.secrets_manager + ).data.use_data + ? "data." + : "" + }ibm_resource_instance.${snakeCase( server.secrets_manager )}_secrets_manager.guid}`, region: varDotRegion, @@ -268,9 +292,45 @@ function formatVpnServer(server, config) { private_key: `\${var.${data.name}_private_key_pem}`, intermediate: `\${var.${data.name}_intermediate_pem}`, } + ) + + jsonToTfPrint( + "resource", + "ibm_sm_imported_certificate", + snakeCase(data.name) + "_client_ca_imported_certificate", + { + instance_id: `\${${ + splatContains( + config.secrets_manager, + "name", + server.secrets_manager + ) && + new revision(config).child( + "secrets_manager", + server.secrets_manager + ).data.use_data + ? "data." + : "" + }ibm_resource_instance.${snakeCase( + server.secrets_manager + )}_secrets_manager.guid}`, + region: varDotRegion, + name: kebabName([ + server.vpc, + server.name, + "server", + "client-ca", + "cert", + ]), + description: `Secret for \${var.prefix} ${titleCase( + server.vpc + " " + server.name + )} Server Client CA authentication`, + certificate: `\${var.${data.name}_client_ca_cert_pem}`, + private_key: `\${var.${data.name}_client_ca_private_key_pem}`, + intermediate: `\${var.${data.name}_intermediate_pem}`, + } ) : server.DANGER_developer_certificate || server.method === "INSECURE" - ? DANGER_formatDevRsaCertificate(server) + ? DANGER_formatDevRsaCertificate(server, config) : ""; return ( diff --git a/unit-tests/json-to-iac/variables.test.js b/unit-tests/json-to-iac/variables.test.js index 3f0f0a27..262c7207 100644 --- a/unit-tests/json-to-iac/variables.test.js +++ b/unit-tests/json-to-iac/variables.test.js @@ -756,6 +756,18 @@ variable "management_vpn_server_abc_intermediate_pem" { sensitive = true } +variable "management_vpn_server_abc_client_ca_cert_pem" { + description = "Imported certificate client ca PEM for Management Vpn Server Abc. Certificate will be stored in Secrets Manager" + type = string + sensitive = true +} + +variable "management_vpn_server_abc_client_ca_private_key_pem" { + description = "Imported certificate client ca private key PEM for Management Vpn Server Abc. Certificate will be stored in Secrets Manager" + type = string + sensitive = true +} + ############################################################################## `; assert.deepEqual( diff --git a/unit-tests/json-to-iac/vpn-server.test.js b/unit-tests/json-to-iac/vpn-server.test.js index 10a19030..31c12bf7 100644 --- a/unit-tests/json-to-iac/vpn-server.test.js +++ b/unit-tests/json-to-iac/vpn-server.test.js @@ -281,6 +281,16 @@ resource "ibm_sm_imported_certificate" "management_vpn_server_abc_imported_certi intermediate = var.management_vpn_server_abc_intermediate_pem } +resource "ibm_sm_imported_certificate" "management_vpn_server_abc_client_ca_imported_certificate" { + instance_id = ibm_resource_instance.secrets_manager_secrets_manager.guid + region = var.region + name = "\${var.prefix}-management-abc-server-client-ca-cert" + description = "Secret for \${var.prefix} Management Abc Server Client CA authentication" + certificate = var.management_vpn_server_abc_client_ca_cert_pem + private_key = var.management_vpn_server_abc_client_ca_private_key_pem + intermediate = var.management_vpn_server_abc_intermediate_pem +} + resource "ibm_is_vpn_server" "management_vpn_server_abc" { certificate_crn = ibm_sm_imported_certificate.management_vpn_server_abc_imported_certificate.crn client_idle_timeout = 2000 @@ -292,7 +302,81 @@ resource "ibm_is_vpn_server" "management_vpn_server_abc" { resource_group = ibm_resource_group.slz_management_rg.id client_authentication { method = "certificate" - client_ca_crn = ibm_sm_imported_certificate.management_vpn_server_abc_imported_certificate.crn + client_ca_crn = ibm_sm_imported_certificate.management_vpn_server_abc_client_ca_imported_certificate.crn + } + client_dns_server_ips = [ + "optional" + ] + subnets = [ + module.management_vpc.vsi_zone_1_id + ] + security_groups = [ + module.management_vpc.management_vpe_sg_id + ] +} +`; + assert.deepEqual(actualData, expectedData, "should return correct data"); + }); + it("should return correct tf for vpn server using bring your own certificate and secrets manager from data", () => { + slzNetwork.secrets_manager.push({ + use_data: true, + name: "secrets-manager", + }); + let actualData = formatVpnServer( + { + name: "abc", + certificate_crn: "xyz", + method: "certificate", + client_ca_crn: "hij", + client_ip_pool: "xyz", + client_dns_server_ips: "optional", + client_idle_timeout: 2000, + enable_split_tunneling: true, + port: 255, + protocol: "udp", + resource_group: "slz-management-rg", + security_groups: ["management-vpe-sg"], + subnets: ["vsi-zone-1"], + vpc: "management", + routes: [], + bring_your_own_cert: true, + secrets_manager: "secrets-manager", + }, + slzNetwork + ); + let expectedData = ` +resource "ibm_sm_imported_certificate" "management_vpn_server_abc_imported_certificate" { + instance_id = data.ibm_resource_instance.secrets_manager_secrets_manager.guid + region = var.region + name = "\${var.prefix}-management-abc-server-cert" + description = "Secret for \${var.prefix} Management Abc Server authentication" + certificate = var.management_vpn_server_abc_cert_pem + private_key = var.management_vpn_server_abc_private_key_pem + intermediate = var.management_vpn_server_abc_intermediate_pem +} + +resource "ibm_sm_imported_certificate" "management_vpn_server_abc_client_ca_imported_certificate" { + instance_id = data.ibm_resource_instance.secrets_manager_secrets_manager.guid + region = var.region + name = "\${var.prefix}-management-abc-server-client-ca-cert" + description = "Secret for \${var.prefix} Management Abc Server Client CA authentication" + certificate = var.management_vpn_server_abc_client_ca_cert_pem + private_key = var.management_vpn_server_abc_client_ca_private_key_pem + intermediate = var.management_vpn_server_abc_intermediate_pem +} + +resource "ibm_is_vpn_server" "management_vpn_server_abc" { + certificate_crn = ibm_sm_imported_certificate.management_vpn_server_abc_imported_certificate.crn + client_idle_timeout = 2000 + client_ip_pool = "xyz" + enable_split_tunneling = true + name = "\${var.prefix}-management-abc-server" + port = 255 + protocol = "udp" + resource_group = ibm_resource_group.slz_management_rg.id + client_authentication { + method = "certificate" + client_ca_crn = ibm_sm_imported_certificate.management_vpn_server_abc_client_ca_imported_certificate.crn } client_dns_server_ips = [ "optional" @@ -308,6 +392,12 @@ resource "ibm_is_vpn_server" "management_vpn_server_abc" { assert.deepEqual(actualData, expectedData, "should return correct data"); }); it("should return correct tf for vpn server using bring your own certificate from method", () => { + slzNetwork.secrets_manager = [ + { + name: "secrets-manager", + use_data: false, + }, + ]; let actualData = formatVpnServer( { name: "abc", @@ -340,6 +430,16 @@ resource "ibm_sm_imported_certificate" "management_vpn_server_abc_imported_certi intermediate = var.management_vpn_server_abc_intermediate_pem } +resource "ibm_sm_imported_certificate" "management_vpn_server_abc_client_ca_imported_certificate" { + instance_id = ibm_resource_instance.secrets_manager_secrets_manager.guid + region = var.region + name = "\${var.prefix}-management-abc-server-client-ca-cert" + description = "Secret for \${var.prefix} Management Abc Server Client CA authentication" + certificate = var.management_vpn_server_abc_client_ca_cert_pem + private_key = var.management_vpn_server_abc_client_ca_private_key_pem + intermediate = var.management_vpn_server_abc_intermediate_pem +} + resource "ibm_is_vpn_server" "management_vpn_server_abc" { certificate_crn = ibm_sm_imported_certificate.management_vpn_server_abc_imported_certificate.crn client_idle_timeout = 2000 @@ -351,7 +451,7 @@ resource "ibm_is_vpn_server" "management_vpn_server_abc" { resource_group = ibm_resource_group.slz_management_rg.id client_authentication { method = "certificate" - client_ca_crn = ibm_sm_imported_certificate.management_vpn_server_abc_imported_certificate.crn + client_ca_crn = ibm_sm_imported_certificate.management_vpn_server_abc_client_ca_imported_certificate.crn } client_dns_server_ips = [ "optional" @@ -471,6 +571,280 @@ resource "ibm_sm_imported_certificate" "DANGER_management_vpn_server_abc_dev_cer ############################################################################## +resource "ibm_is_vpn_server" "management_vpn_server_abc" { + certificate_crn = ibm_sm_imported_certificate.DANGER_management_vpn_server_abc_dev_cert.crn + client_idle_timeout = 2000 + client_ip_pool = "xyz" + enable_split_tunneling = true + name = "\${var.prefix}-management-abc-server" + port = 255 + protocol = "udp" + resource_group = ibm_resource_group.slz_management_rg.id + client_authentication { + method = "certificate" + client_ca_crn = ibm_sm_imported_certificate.DANGER_management_vpn_server_abc_dev_cert.crn + } + client_dns_server_ips = [ + "optional" + ] + subnets = [ + module.management_vpc.vsi_zone_1_id + ] + security_groups = [ + module.management_vpc.management_vpe_sg_id + ] +} +`; + assert.deepEqual(actualData, expectedData, "should return correct data"); + }); + it("should return correct tf for vpn server using developer certificate", () => { + slzNetwork.secrets_manager = [ + { + name: "secrets-manager", + use_data: false, + }, + ]; + let actualData = formatVpnServer( + { + name: "abc", + certificate_crn: "xyz", + method: "certificate", + client_ca_crn: "hij", + client_ip_pool: "xyz", + client_dns_server_ips: "optional", + client_idle_timeout: 2000, + enable_split_tunneling: true, + port: 255, + protocol: "udp", + resource_group: "slz-management-rg", + security_groups: ["management-vpe-sg"], + subnets: ["vsi-zone-1"], + vpc: "management", + routes: [], + DANGER_developer_certificate: true, + secrets_manager: "secrets-manager", + }, + slzNetwork + ); + let expectedData = `############################################################################## +# DANGER ZONE - DEVELOPMENT ONLY - DO NOT USE IN PRODUCTION +############################################################################## + +resource "tls_private_key" "DANGER_management_vpn_abc_ca_key" { + algorithm = "RSA" +} + +resource "tls_private_key" "DANGER_management_vpn_abc_client_key" { + algorithm = "RSA" +} + +resource "tls_private_key" "DANGER_management_vpn_abc_server_key" { + algorithm = "RSA" +} + +resource "tls_self_signed_cert" "DANGER_management_vpn_abc_ca_cert" { + is_ca_certificate = true + private_key_pem = tls_private_key.DANGER_management_vpn_abc_ca_key.private_key_pem + validity_period_hours = 3 * 365 * 24 + subject { + common_name = "My Cert Authority" + organization = "My, Inc" + } + allowed_uses = [ + "cert_signing", + "crl_signing" + ] +} + +resource "tls_cert_request" "DANGER_management_vpn_abc_client_request" { + private_key_pem = tls_private_key.DANGER_management_vpn_abc_client_key.private_key_pem + subject { + common_name = "my.vpn.client" + organization = "My, Inc" + } +} + +resource "tls_cert_request" "DANGER_management_vpn_abc_server_request" { + private_key_pem = tls_private_key.DANGER_management_vpn_abc_server_key.private_key_pem + subject { + common_name = "my.vpn.server" + organization = "My, Inc" + } +} + +resource "tls_locally_signed_cert" "DANGER_management_vpn_abc_client_cert" { + cert_request_pem = tls_cert_request.DANGER_management_vpn_abc_client_request.cert_request_pem + ca_private_key_pem = tls_private_key.DANGER_management_vpn_abc_ca_key.private_key_pem + ca_cert_pem = tls_self_signed_cert.DANGER_management_vpn_abc_ca_cert.cert_pem + validity_period_hours = 3 * 365 * 24 + allowed_uses = [ + "key_encipherment", + "digital_signature", + "client_auth" + ] +} + +resource "tls_locally_signed_cert" "DANGER_management_vpn_abc_server_cert" { + cert_request_pem = tls_cert_request.DANGER_management_vpn_abc_server_request.cert_request_pem + ca_private_key_pem = tls_private_key.DANGER_management_vpn_abc_ca_key.private_key_pem + ca_cert_pem = tls_self_signed_cert.DANGER_management_vpn_abc_ca_cert.cert_pem + validity_period_hours = 3 * 365 * 24 + allowed_uses = [ + "key_encipherment", + "digital_signature", + "server_auth" + ] +} + +resource "ibm_sm_imported_certificate" "DANGER_management_vpn_server_abc_dev_cert" { + instance_id = ibm_resource_instance.secrets_manager_secrets_manager.guid + region = var.region + name = "\${var.prefix}-management-abc-server-dev-cert" + description = "DANGER - INSECURE - FOR DEVELOPMENT USE ONLY - Secret for \${var.prefix} Management Abc Server authentication" + certificate = tls_locally_signed_cert.DANGER_management_vpn_abc_server_cert.cert_pem + private_key = tls_private_key.DANGER_management_vpn_abc_server_key.private_key_pem + intermediate = tls_self_signed_cert.DANGER_management_vpn_abc_ca_cert.cert_pem +} + +############################################################################## + +resource "ibm_is_vpn_server" "management_vpn_server_abc" { + certificate_crn = ibm_sm_imported_certificate.DANGER_management_vpn_server_abc_dev_cert.crn + client_idle_timeout = 2000 + client_ip_pool = "xyz" + enable_split_tunneling = true + name = "\${var.prefix}-management-abc-server" + port = 255 + protocol = "udp" + resource_group = ibm_resource_group.slz_management_rg.id + client_authentication { + method = "certificate" + client_ca_crn = ibm_sm_imported_certificate.DANGER_management_vpn_server_abc_dev_cert.crn + } + client_dns_server_ips = [ + "optional" + ] + subnets = [ + module.management_vpc.vsi_zone_1_id + ] + security_groups = [ + module.management_vpc.management_vpe_sg_id + ] +} +`; + assert.deepEqual(actualData, expectedData, "should return correct data"); + }); + it("should return correct tf for vpn server using developer certificate with secrets manager from data", () => { + slzNetwork.secrets_manager = [ + { + name: "secrets-manager", + use_data: true, + }, + ]; + let actualData = formatVpnServer( + { + name: "abc", + certificate_crn: "xyz", + method: "certificate", + client_ca_crn: "hij", + client_ip_pool: "xyz", + client_dns_server_ips: "optional", + client_idle_timeout: 2000, + enable_split_tunneling: true, + port: 255, + protocol: "udp", + resource_group: "slz-management-rg", + security_groups: ["management-vpe-sg"], + subnets: ["vsi-zone-1"], + vpc: "management", + routes: [], + DANGER_developer_certificate: true, + secrets_manager: "secrets-manager", + }, + slzNetwork + ); + let expectedData = `############################################################################## +# DANGER ZONE - DEVELOPMENT ONLY - DO NOT USE IN PRODUCTION +############################################################################## + +resource "tls_private_key" "DANGER_management_vpn_abc_ca_key" { + algorithm = "RSA" +} + +resource "tls_private_key" "DANGER_management_vpn_abc_client_key" { + algorithm = "RSA" +} + +resource "tls_private_key" "DANGER_management_vpn_abc_server_key" { + algorithm = "RSA" +} + +resource "tls_self_signed_cert" "DANGER_management_vpn_abc_ca_cert" { + is_ca_certificate = true + private_key_pem = tls_private_key.DANGER_management_vpn_abc_ca_key.private_key_pem + validity_period_hours = 3 * 365 * 24 + subject { + common_name = "My Cert Authority" + organization = "My, Inc" + } + allowed_uses = [ + "cert_signing", + "crl_signing" + ] +} + +resource "tls_cert_request" "DANGER_management_vpn_abc_client_request" { + private_key_pem = tls_private_key.DANGER_management_vpn_abc_client_key.private_key_pem + subject { + common_name = "my.vpn.client" + organization = "My, Inc" + } +} + +resource "tls_cert_request" "DANGER_management_vpn_abc_server_request" { + private_key_pem = tls_private_key.DANGER_management_vpn_abc_server_key.private_key_pem + subject { + common_name = "my.vpn.server" + organization = "My, Inc" + } +} + +resource "tls_locally_signed_cert" "DANGER_management_vpn_abc_client_cert" { + cert_request_pem = tls_cert_request.DANGER_management_vpn_abc_client_request.cert_request_pem + ca_private_key_pem = tls_private_key.DANGER_management_vpn_abc_ca_key.private_key_pem + ca_cert_pem = tls_self_signed_cert.DANGER_management_vpn_abc_ca_cert.cert_pem + validity_period_hours = 3 * 365 * 24 + allowed_uses = [ + "key_encipherment", + "digital_signature", + "client_auth" + ] +} + +resource "tls_locally_signed_cert" "DANGER_management_vpn_abc_server_cert" { + cert_request_pem = tls_cert_request.DANGER_management_vpn_abc_server_request.cert_request_pem + ca_private_key_pem = tls_private_key.DANGER_management_vpn_abc_ca_key.private_key_pem + ca_cert_pem = tls_self_signed_cert.DANGER_management_vpn_abc_ca_cert.cert_pem + validity_period_hours = 3 * 365 * 24 + allowed_uses = [ + "key_encipherment", + "digital_signature", + "server_auth" + ] +} + +resource "ibm_sm_imported_certificate" "DANGER_management_vpn_server_abc_dev_cert" { + instance_id = data.ibm_resource_instance.secrets_manager_secrets_manager.guid + region = var.region + name = "\${var.prefix}-management-abc-server-dev-cert" + description = "DANGER - INSECURE - FOR DEVELOPMENT USE ONLY - Secret for \${var.prefix} Management Abc Server authentication" + certificate = tls_locally_signed_cert.DANGER_management_vpn_abc_server_cert.cert_pem + private_key = tls_private_key.DANGER_management_vpn_abc_server_key.private_key_pem + intermediate = tls_self_signed_cert.DANGER_management_vpn_abc_ca_cert.cert_pem +} + +############################################################################## + resource "ibm_is_vpn_server" "management_vpn_server_abc" { certificate_crn = ibm_sm_imported_certificate.DANGER_management_vpn_server_abc_dev_cert.crn client_idle_timeout = 2000 @@ -498,6 +872,7 @@ resource "ibm_is_vpn_server" "management_vpn_server_abc" { assert.deepEqual(actualData, expectedData, "should return correct data"); }); it("should return correct tf for vpn server using developer certificate from method", () => { + slzNetwork.secrets_manager = []; let actualData = formatVpnServer( { name: "abc", From b316ab95e255095a385e2d98bfe475022ce959a7 Mon Sep 17 00:00:00 2001 From: jvallexm Date: Tue, 5 Mar 2024 13:28:06 -0500 Subject: [PATCH 03/16] Vpn server fix (#1608) * feat: power vs v2 enhancements * feat: variables * changelog * fix: cert * fix: subforms * vpn variable fix --- client/src/lib/json-to-iac/variables.js | 2 +- unit-tests/json-to-iac/variables.test.js | 686 +++++++++++++++++++++++ 2 files changed, 687 insertions(+), 1 deletion(-) diff --git a/client/src/lib/json-to-iac/variables.js b/client/src/lib/json-to-iac/variables.js index 0b0e3624..f3852b50 100644 --- a/client/src/lib/json-to-iac/variables.js +++ b/client/src/lib/json-to-iac/variables.js @@ -179,7 +179,7 @@ function variablesDotTf(config, useF5, templateTarMode) { }); config.vpn_servers.forEach((server) => { - if (server.bring_your_own_cert) { + if (server.bring_your_own_cert || server.method === "byo") { [ "cert_pem", "private_key_pem", diff --git a/unit-tests/json-to-iac/variables.test.js b/unit-tests/json-to-iac/variables.test.js index 262c7207..6b2b6a70 100644 --- a/unit-tests/json-to-iac/variables.test.js +++ b/unit-tests/json-to-iac/variables.test.js @@ -915,4 +915,690 @@ variable "secrets_manager_example_secret_password" { "it should return correct variables" ); }); + it("should return correct variables for byo cert in vpn server", () => { + let actualData = variablesDotTf({ + _options: { + prefix: "c2s", + region: "us-south", + tags: ["poc"], + zones: 1, + endpoints: "public", + account_id: null, + dynamic_subnets: false, + enable_power_vs: true, + enable_classic: false, + power_vs_zones: ["dal10"], + craig_version: "1.12.2", + power_vs_high_availability: false, + template: "Empty Project", + fs_cloud: false, + }, + access_groups: [], + appid: [], + atracker: { + enabled: false, + type: "cos", + name: "atracker", + target_name: "a-tracker", + bucket: null, + add_route: true, + cos_key: null, + locations: ["global", "us-south"], + instance: false, + plan: "lite", + resource_group: "service-rg", + }, + cbr_rules: [], + cbr_zones: [], + cis: [], + cis_glbs: [], + classic_gateways: [], + classic_ssh_keys: [], + classic_vlans: [], + clusters: [], + dns: [], + event_streams: [], + f5_vsi: [], + fortigate_vnf: [], + iam_account_settings: { + enable: false, + mfa: null, + allowed_ip_addresses: null, + include_history: false, + if_match: null, + max_sessions_per_identity: null, + restrict_create_service_id: null, + restrict_create_platform_apikey: null, + session_expiration_in_seconds: null, + session_invalidation_in_seconds: null, + }, + icd: [], + key_management: [ + { + name: "kms", + resource_group: "service-rg", + use_hs_crypto: false, + authorize_vpc_reader_role: true, + use_data: false, + keys: [ + { + key_ring: "ring", + name: "key", + root_key: true, + force_delete: true, + endpoint: "public", + rotation: 1, + dual_auth_delete: false, + }, + ], + }, + ], + load_balancers: [], + logdna: { + enabled: false, + plan: "7-day", + endpoints: "private", + platform_logs: false, + resource_group: "service-rg", + cos: null, + bucket: null, + name: "logdna", + archive: false, + }, + object_storage: [], + power: [], + power_instances: [], + power_volumes: [], + resource_groups: [ + { + use_prefix: true, + name: "service-rg", + use_data: false, + }, + { + use_prefix: true, + name: "transit-rg", + use_data: false, + }, + ], + routing_tables: [ + { + routes: [ + { + name: "on-prem", + zone: "1", + destination: "10.40.0.0/16", + action: "deliver", + next_hop: "10.250.0.1", + routing_table: "poweringress", + vpc: "transit", + }, + ], + name: "poweringress", + vpc: "transit", + internet_ingress: false, + transit_gateway_ingress: true, + vpc_zone_ingress: true, + direct_link_ingress: false, + route_direct_link_ingress: false, + route_vpc_zone_ingress: false, + accept_routes_from_resource_type: [], + }, + ], + scc: { + credential_description: null, + id: null, + passphrase: null, + name: "", + location: "us", + collector_description: null, + is_public: false, + scope_description: null, + enable: false, + }, + scc_v2: { + enable: false, + resource_group: null, + region: "", + account_id: "${var.account_id}", + profile_attachments: [], + }, + secrets_manager: [ + { + resource_group: "service-rg", + use_data: true, + name: "Secrets Manager-vidhi", + plan: "standard", + encryption_key: null, + kms: null, + secrets: [], + }, + ], + security_groups: [ + { + vpc: "transit", + name: "transit-vpe", + resource_group: "transit-rg", + rules: [ + { + name: "general-inbound", + direction: "inbound", + icmp: { + type: null, + code: null, + }, + tcp: { + port_min: null, + port_max: null, + }, + udp: { + port_min: null, + port_max: null, + }, + source: "10.0.0.0/8", + vpc: "transit", + sg: "transit-vpe", + ruleProtocol: "all", + port_min: null, + port_max: null, + type: null, + code: null, + }, + { + name: "powervs-inbound", + direction: "inbound", + icmp: { + type: null, + code: null, + }, + tcp: { + port_min: null, + port_max: null, + }, + udp: { + port_min: null, + port_max: null, + }, + source: "192.168.0.0/24", + vpc: "transit", + sg: "transit-vpe", + ruleProtocol: "all", + port_min: null, + port_max: null, + type: null, + code: null, + }, + { + name: "general-outbound", + direction: "outbound", + icmp: { + type: null, + code: null, + }, + tcp: { + port_min: null, + port_max: null, + }, + udp: { + port_min: null, + port_max: null, + }, + source: "10.0.0.0/8", + vpc: "transit", + sg: "transit-vpe", + ruleProtocol: "all", + port_min: null, + port_max: null, + type: null, + code: null, + }, + ], + }, + { + vpc: "transit", + name: "transit-vsi", + resource_group: "transit-rg", + rules: [ + { + name: "general-inbound", + direction: "inbound", + icmp: { + type: null, + code: null, + }, + tcp: { + port_min: null, + port_max: null, + }, + udp: { + port_min: null, + port_max: null, + }, + source: "10.0.0.0/8", + vpc: "transit", + sg: "transit-vsi", + ruleProtocol: "all", + port_min: null, + port_max: null, + type: null, + code: null, + }, + { + name: "ibm-inbound", + direction: "inbound", + icmp: { + type: null, + code: null, + }, + tcp: { + port_min: null, + port_max: null, + }, + udp: { + port_min: null, + port_max: null, + }, + source: "161.26.0.0/16", + vpc: "transit", + sg: "transit-vsi", + ruleProtocol: "all", + port_min: null, + port_max: null, + type: null, + code: null, + }, + { + name: "powervs-inbound", + direction: "inbound", + icmp: { + type: null, + code: null, + }, + tcp: { + port_min: null, + port_max: null, + }, + udp: { + port_min: null, + port_max: null, + }, + source: "192.168.0.0/24", + vpc: "transit", + sg: "transit-vsi", + ruleProtocol: "all", + port_min: null, + port_max: null, + type: null, + code: null, + }, + { + name: "all-outbound", + direction: "outbound", + icmp: { + type: null, + code: null, + }, + tcp: { + port_min: null, + port_max: null, + }, + udp: { + port_min: null, + port_max: null, + }, + source: "0.0.0.0/0", + vpc: "transit", + sg: "transit-vsi", + ruleProtocol: "all", + port_min: null, + port_max: null, + type: null, + code: null, + }, + ], + }, + ], + ssh_keys: [ + { + name: "vsi-ssh-key", + public_key: "NONE", + use_data: false, + resource_group: "transit-rg", + }, + ], + sysdig: { + enabled: false, + plan: "graduated-tier", + resource_group: "service-rg", + name: "sysdig", + platform_logs: false, + }, + teleport_vsi: [], + transit_gateways: [ + { + name: "transit-gateway", + resource_group: "service-rg", + global: false, + connections: [ + { + tgw: "transit-gateway", + vpc: "transit", + }, + ], + use_data: false, + gre_tunnels: [], + prefix_filters: [], + }, + ], + virtual_private_endpoints: [ + { + name: "transit-cos", + service: "cos", + vpc: "transit", + resource_group: "transit-rg", + security_groups: ["transit-vpe"], + subnets: ["vpe-zone-1"], + instance: null, + }, + ], + vpcs: [ + { + cos: null, + bucket: "$disabled", + name: "transit", + resource_group: "transit-rg", + classic_access: false, + manual_address_prefix_management: true, + default_network_acl_name: null, + default_security_group_name: null, + default_routing_table_name: null, + publicGateways: [1], + address_prefixes: [ + { + vpc: "transit", + zone: 1, + name: "transit-zone-1", + cidr: "10.10.0.0/22", + }, + ], + subnets: [ + { + vpc: "transit", + zone: 1, + cidr: "10.10.0.0/26", + name: "vsi-zone-1", + network_acl: "transit", + resource_group: "transit-rg", + public_gateway: true, + has_prefix: false, + }, + { + vpc: "transit", + zone: 1, + cidr: "10.10.0.128/29", + name: "vpe-zone-1", + resource_group: "transit-rg", + network_acl: "transit", + public_gateway: false, + has_prefix: false, + }, + { + vpc: "transit", + zone: 1, + cidr: "10.10.0.144/28", + name: "vpn-zone-1", + networkAcl: "transit", + resource_group: "transit-rg", + has_prefix: false, + network_acl: "transit", + public_gateway: false, + }, + ], + public_gateways: [ + { + vpc: "transit", + zone: 1, + resource_group: "transit-rg", + }, + ], + acls: [ + { + resource_group: "transit-rg", + name: "transit", + vpc: "transit", + rules: [ + { + name: "all-inbound", + action: "allow", + direction: "inbound", + icmp: { + type: null, + code: null, + }, + tcp: { + port_min: null, + port_max: null, + source_port_min: null, + source_port_max: null, + }, + udp: { + port_min: null, + port_max: null, + source_port_min: null, + source_port_max: null, + }, + source: "0.0.0.0/0", + destination: "10.0.0.0/8", + acl: "transit", + vpc: "transit", + ruleProtocol: "all", + port_min: null, + port_max: null, + type: null, + code: null, + source_port_min: null, + source_port_max: null, + }, + { + name: "all-outbound", + action: "allow", + direction: "outbound", + icmp: { + type: null, + code: null, + }, + tcp: { + port_min: null, + port_max: null, + source_port_min: null, + source_port_max: null, + }, + udp: { + port_min: null, + port_max: null, + source_port_min: null, + source_port_max: null, + }, + source: "10.0.0.0/8", + destination: "0.0.0.0/0", + acl: "transit", + vpc: "transit", + ruleProtocol: "all", + port_min: null, + port_max: null, + type: null, + code: null, + source_port_min: null, + source_port_max: null, + }, + ], + use_data: false, + }, + ], + subnetTiers: [ + { + name: "vsi", + zones: 1, + }, + { + name: "vpe", + zones: 1, + }, + { + name: "vpn", + zones: 1, + }, + ], + use_data: false, + }, + ], + vpn_gateways: [ + { + name: "dal10gw", + resource_group: "transit-rg", + vpc: "transit", + subnet: "vpn-zone-1", + policy_mode: true, + connections: [ + { + name: "on-prem-connection", + peer_cidrs: ["10.40.0.0/16"], + local_cidrs: [ + "192.168.0.0/24", + "10.10.0.0/26", + "10.10.0.128/29", + "10.10.0.144/28", + ], + vpn: "dal10gw", + peer_address: "10.40.0.0", + }, + ], + additional_prefixes: ["10.40.0.0/16"], + }, + ], + vpn_servers: [ + { + vpc: "transit", + subnets: ["vpn-zone-1"], + security_groups: ["transit-vsi"], + ssh_keys: [], + name: "test-c2s", + resource_group: "transit-rg", + method: "byo", + certificate_crn: + "crn:v1:bluemix:public:secrets-manager:us-south:a/cdefe6d99f7ea459aacb25775fb88a33:3e99268e-ea59-4893-a095-f0934c33346a:secret:aa8ebb11-bc2b-1012-1289-1516aae031e1", + secrets_manager: "Secrets Manager-vidhi", + client_ca_crn: + "crn:v1:bluemix:public:secrets-manager:us-south:a/cdefe6d99f7ea459aacb25775fb88a33:3e99268e-ea59-4893-a095-f0934c33346a:secret:9f132030-b6a6-78e8-dcf1-4e124befc360", + client_ip_pool: "192.168.0.0/16", + port: "443", + protocol: "udp", + enable_split_tunneling: false, + client_idle_timeout: null, + client_dns_server_ips: null, + zone: null, + additional_prefixes: [], + routes: [], + }, + ], + vsi: [ + { + kms: "kms", + encryption_key: "key", + image: "ibm-redhat-9-2-minimal-amd64-3", + image_name: + "Red Hat Enterprise Linux 9.x - Minimal Install (amd64) [ibm-redhat-9-2-minimal-amd64-3]", + profile: "cx2-2x4", + name: "example-deployment", + security_groups: ["transit-vsi"], + ssh_keys: ["vsi-ssh-key"], + vpc: "transit", + vsi_per_subnet: "1", + resource_group: "transit-rg", + override_vsi_name: null, + user_data: null, + network_interfaces: [], + subnets: ["vsi-zone-1"], + volumes: [], + subnet: "", + enable_floating_ip: false, + primary_interface_ip_spoofing: false, + }, + ], + vtl: [], + }); + let expectedData = `############################################################################## +# Variables +############################################################################## + +variable "ibmcloud_api_key" { + description = "The IBM Cloud platform API key needed to deploy IAM enabled resources." + type = string + sensitive = true +} + +variable "region" { + description = "IBM Cloud Region where resources will be provisioned" + type = string + default = "us-south" +} + +variable "prefix" { + description = "Name prefix that will be prepended to named resources" + type = string + default = "c2s" +} + +variable "vsi_ssh_key_public_key" { + description = "Public SSH Key Value for Vsi SSH Key" + type = string + sensitive = true + default = "NONE" +} + +variable "dal10gw_on_prem_connection_preshared_key" { + description = "Preshared key for VPN Gateway dal10gw connection on-prem-connection" + type = string + sensitive = true +} + +variable "transit_vpn_server_test_c2s_cert_pem" { + description = "Imported certificate PEM for Transit Vpn Server Test C 2s. Certificate will be stored in Secrets Manager" + type = string + sensitive = true +} + +variable "transit_vpn_server_test_c2s_private_key_pem" { + description = "Imported certificate private key PEM for Transit Vpn Server Test C 2s. Certificate will be stored in Secrets Manager" + type = string + sensitive = true +} + +variable "transit_vpn_server_test_c2s_intermediate_pem" { + description = "Imported certificate intermediate PEM for Transit Vpn Server Test C 2s. Certificate will be stored in Secrets Manager" + type = string + sensitive = true +} + +variable "transit_vpn_server_test_c2s_client_ca_cert_pem" { + description = "Imported certificate client ca PEM for Transit Vpn Server Test C 2s. Certificate will be stored in Secrets Manager" + type = string + sensitive = true +} + +variable "transit_vpn_server_test_c2s_client_ca_private_key_pem" { + description = "Imported certificate client ca private key PEM for Transit Vpn Server Test C 2s. Certificate will be stored in Secrets Manager" + type = string + sensitive = true +} + +############################################################################## +`; + + assert.deepEqual( + actualData, + expectedData, + "it should return correct variables" + ); + }); }); From 6694d51e9b1e89845ed70a496436149b69fb706a Mon Sep 17 00:00:00 2001 From: Pseusco Date: Tue, 5 Mar 2024 13:53:25 -0500 Subject: [PATCH 04/16] Issue 1521: Added tooltip to describe RHEL image (#1603) * add tooltip to vsi image Signed-off-by: Lucas-Franke * edit tooltip Signed-off-by: Lucas-Franke * remove quotes Signed-off-by: Lucas-Franke --------- Signed-off-by: Lucas-Franke --- client/src/lib/state/vsi.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/src/lib/state/vsi.js b/client/src/lib/state/vsi.js index 8e35d6a1..a35c30d7 100644 --- a/client/src/lib/state/vsi.js +++ b/client/src/lib/state/vsi.js @@ -406,6 +406,12 @@ function initVsiStore(store) { apiEndpoint: function (stateData, componentProps) { return `/api/vsi/${componentProps.craig.store.json._options.region}/images`; }, + tooltip: { + content: + "When using a Red Had Enterprise Linux Image, additional networking rules must be added to successfully provision your VSI. Ensure outbound traffic is allowed in Security Groups at CIDR range 161.26.0.0/16 for TCP ports 80, 443, and 8443, and for UDP port 53.", + align: "top-left", + alignModal: "top-left", + }, }, profile: { size: "small", From 8460ea3bd1c28223e4a2ec9c174061207b688db4 Mon Sep 17 00:00:00 2001 From: Vidhi Shah Date: Wed, 6 Mar 2024 07:57:53 -0600 Subject: [PATCH 05/16] remove routing table route and enable vpn gateway & server (#1609) * remove routing table route and enable vpn gateway and server * update craig version * update readme --------- Co-authored-by: Vidhi Shah --- .docs/powervs-poc.md | 21 +--------------- .../docs/templates/power-poc-quick-start.json | 25 ++++++------------- 2 files changed, 9 insertions(+), 37 deletions(-) diff --git a/.docs/powervs-poc.md b/.docs/powervs-poc.md index 6fc7de43..c0297c9b 100644 --- a/.docs/powervs-poc.md +++ b/.docs/powervs-poc.md @@ -47,12 +47,10 @@ To set the public SSH key value for the VPC VSI, click on the red `VPC Deploymen To set the public SSH key value for the Power VS VSIs, click on the red `Power VS` item on the left navigation bar, then click on the key icon. Click on the key icon, expand the SSH Keys section, fill in the public key value, and click the Save button. ### On-premises network CIDRS and Peer Address -To set network CIDRs that are being used by the on-prem environment the VPN Gateway and a routing table must be updated. +To set network CIDRs that are being used by the on-prem environment the VPN Gateway must be updated. To update the VPN Gateway, click on `VPC Deployments` on the left navigation bar. Scroll down and click on the gateway icon in the `vpn-zone-1` network. Expand the connection section and update the network CIDR in the `Additional Address Prefixes` and `Peer CIDRs` fields. Set VPN connection Peer Address, the address for the on-prem connection, in the `Peer Address` field. Click on both blue Save buttons when finished. -To update the VPN Gateway, click on `VPC Deployments` on the left navigation bar then click on the `poweringress` routing table icon. Change the on-prem CIDR in the `Destination` field and click the blue Save button. - #### On-premises network CIDR outside of 10.0.0.0/8 If you are using an on-premises network CIDR outside of the `10.0.0.0/8` range in addition to the changes above you will need to add inbound and outbound rules to the `transit-vsi` and `transit-vpe` security groups. These security groups can be found by clicking on `VPC Deployments` on the left navigation bar and then clicking on each security group icon. @@ -135,23 +133,6 @@ IBM Cloud Schematics provides a cost estimation for the project resources after ## Post-deployment configuration -### Update Power VS route to VPN Gateway -After deploying the PoC resources the routing table for traffic from Power VS to the VPN Gateway for on-premises must be updated. - -First, find the VPN Gateway for VPC's active private address. -> * You can find this address from [IBM cloud console](https://cloud.ibm.com/). -> * From left menu click on `VPC Infrastructures > VPNs`. -> * Select the region where VPN has been deployed and all VPNs in that region will be listed. -> * Select the VPN that was deployed. -> * Copy or write down the Private IP of the active gateway member - -Update the routing table: -> * From left menu click on `VPC Infrastructures > Routing Tables`. -> * Select the VPC that was deployed. -> * Select the routing table with `poweringress` in its name. -> Modify the route by clicking the 3 vertical dot icon and choosing Edit. -> Set the Next hop IP address to the private IP address of the active VPN gateway member - ### Virtual server configuration After deploying the PoC resources additional configuration in the VSI operating systems is usually required. IBM i VSIs deployed using the stock images have [required post-deployment configuration](https://cloud.ibm.com/docs/power-iaas?topic=power-iaas-configuring-ibmi). diff --git a/client/src/lib/docs/templates/power-poc-quick-start.json b/client/src/lib/docs/templates/power-poc-quick-start.json index d50d75b0..02d39fa2 100644 --- a/client/src/lib/docs/templates/power-poc-quick-start.json +++ b/client/src/lib/docs/templates/power-poc-quick-start.json @@ -10,11 +10,10 @@ "enable_power_vs": true, "enable_classic": false, "power_vs_zones": ["dal10"], - "craig_version": "1.12.0", + "craig_version": "1.12.2", "power_vs_high_availability": false, "template": "Power VS POC", - "fs_cloud": false, - "no_vpn_secrets_manager_auth": false + "fs_cloud": false }, "access_groups": [], "appid": [], @@ -537,17 +536,7 @@ ], "routing_tables": [ { - "routes": [ - { - "name": "on-prem", - "zone": "1", - "destination": "10.40.0.0/16", - "action": "deliver", - "next_hop": "10.250.0.1", - "routing_table": "poweringress", - "vpc": "transit" - } - ], + "routes": [], "name": "poweringress", "vpc": "transit", "internet_ingress": false, @@ -556,7 +545,7 @@ "direct_link_ingress": false, "route_direct_link_ingress": false, "route_vpc_zone_ingress": false, - "accept_routes_from_resource_type": [] + "accept_routes_from_resource_type": ["vpn_gateway", "vpn_server"] } ], "scc": { @@ -939,7 +928,8 @@ "source_port_min": null, "source_port_max": null } - ] + ], + "use_data": false } ], "subnetTiers": [ @@ -955,7 +945,8 @@ "name": "vpn", "zones": 1 } - ] + ], + "use_data": false } ], "vpn_gateways": [ From 2ed8ccc70e85afd932c801f225b7064b2bdcfdcd Mon Sep 17 00:00:00 2001 From: terechc Date: Wed, 6 Mar 2024 15:55:00 -0500 Subject: [PATCH 06/16] Issue 1600: Ansible script for the tasks in `template-test.sh` (#1607) * simple role * sp * stop on errors * prefix * PR fixes * Delete main.yml * Delete main.yml * dynamic variablestore * sp * sp * PR updates --- ansible/template-test/tasks/main.yml | 153 +++++++++++++++++++++++++++ ansible/template-test/vars/main.yml | 37 +++++++ 2 files changed, 190 insertions(+) create mode 100644 ansible/template-test/tasks/main.yml create mode 100644 ansible/template-test/vars/main.yml diff --git a/ansible/template-test/tasks/main.yml b/ansible/template-test/tasks/main.yml new file mode 100644 index 00000000..8186b69d --- /dev/null +++ b/ansible/template-test/tasks/main.yml @@ -0,0 +1,153 @@ +--- +# To run the playbook locally, run `ansible-playbook main.yml` in this directory. +# This playbook creates a schematics workspace, uploads a craig .tar file for a specific template to that workspace, +# Generates a plan, applies the plan to create the resources in the template, and destroys the newly created resources. +# If any step fails, the playbook will stop and print the error to the terminal. + +- name: Upload CRAIG template to schematics workspace + hosts: localhost + vars_files: ../vars/main.yml + tasks: + - name: Get IAM Access Token + uri: + url: https://iam.cloud.ibm.com/identity/token + method: POST + headers: + Content-Type: application/x-www-form-urlencoded + body: "grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey={{api_key}}" + register: token + + - name: Download {{template}}.tar to current directory + get_url: + url: "{{craig_url}}/{{template}}" + dest: "{{playbook_dir}}/{{template}}.tar" + async: 120 + retries: 10 + + - name: Create Schematics Workspace + uri: + url: https://schematics.cloud.ibm.com/v1/workspaces + method: POST + headers: + Authorization: Bearer {{token.json.access_token}} + body_format: json + body: + "name": "{{workspace_name}}" + "resource_group": "{{resource_group}}" + "type": ["terraform_v1.5"] + "location": "{{region}}" + "description": Automated CRAIG Testing Workspace + "tags": ["craig"] + "template_data": [{ "type": "terraform_v1.5"}] + status_code: 201 + register: workspace + + - name: Upload {{template}}.tar to Schematics Workspace + command: "curl -s --request PUT \ + --url 'https://schematics.cloud.ibm.com/v1/workspaces/{{ workspace.json.id }}/template_data/{{ workspace.json.template_data[0].id }}/template_repo_upload' \ + -H 'Authorization: Bearer {{ token.json.access_token }}' \ + -H 'Content-Type: multipart/form-data' \ + --form 'file=@{{playbook_dir}}/{{template}}.tar'" + async: 120 + + - name: Wait until {{template}}.tar has been successfully uploaded + uri: + url: https://schematics.cloud.ibm.com/v1/workspaces/{{ workspace.json.id }} + method: GET + body_format: json + headers: + Authorization: Bearer {{token.json.access_token}} + register: workspace_status + until: workspace_status.json.status == "INACTIVE" + delay: 10 + retries: 50 + + - name: Update variablestore + set_fact: + variablestore: "{{ variablestore + [{'name': item, 'secure': true, 'use_default': false, 'value': ssh_key}] }}" + loop: "{{template_map[template]}}" + + - name: Update vars in workspace + uri: + url: https://schematics.cloud.ibm.com/v1/workspaces/{{ workspace.json.id }}/template_data/{{ workspace.json.template_data[0].id }}/values + method: PUT + headers: + Authorization: Bearer {{token.json.access_token}} + Content-Type: application/json + body_format: json + body: + variablestore: "{{ variablestore }}" + + - name: Start generate plan action + uri: + url: https://schematics.cloud.ibm.com/v1/workspaces/{{ workspace.json.id }}/plan + method: POST + body_format: json + headers: + Authorization: Bearer {{token.json.access_token}} + status_code: 202 + register: job + + - name: Ensure generate plan finishes + uri: + url: https://schematics.cloud.ibm.com/v2/jobs/{{job.json.activityid}} + method: GET + body_format: json + headers: + Authorization: Bearer {{token.json.access_token}} + register: plan + until: plan.json.status.workspace_job_status.status_code == "job_finished" or plan.json.status.workspace_job_status.status_code == "job_failed" + failed_when: plan.json.status.workspace_job_status.status_code == "job_failed" + delay: 90 + retries: 50 + + - name: Start apply plan action + uri: + url: https://schematics.cloud.ibm.com/v1/workspaces/{{workspace.json.id}}/apply + method: PUT + body_format: json + headers: + Authorization: Bearer {{token.json.access_token}} + status_code: 202 + register: apply + + - name: Ensure apply plan finishes + uri: + url: https://schematics.cloud.ibm.com/v2/jobs/{{apply.json.activityid}} + method: GET + body_format: json + headers: + Authorization: Bearer {{token.json.access_token}} + register: apply_plan + until: apply_plan.json.status.workspace_job_status.status_code == "job_finished" or apply_plan.json.status.workspace_job_status.status_code == "job_failed" + failed_when: apply_plan.json.status.workspace_job_status.status_code == "job_failed" + delay: 120 + retries: 50 + + - name: Start destroy action + uri: + url: https://schematics.cloud.ibm.com/v1/workspaces/{{workspace.json.id}}/destroy + method: PUT + body_format: json + headers: + Authorization: Bearer {{token.json.access_token}} + status_code: 202 + register: destroy + + - name: Ensure destory finishes + uri: + url: https://schematics.cloud.ibm.com/v2/jobs/{{destroy.json.activityid}} + method: GET + body_format: json + headers: + Authorization: Bearer {{token.json.access_token}} + register: destroy_plan + until: destroy_plan.json.status.workspace_job_status.status_code == "job_finished" or destroy_plan.json.status.workspace_job_status.status_code == "job_failed" + failed_when: destroy_plan.json.status.workspace_job_status.status_code == "job_failed" + delay: 120 + retries: 50 + + - name: Delete local {{template}}.tar file + file: + state: absent + path: /{{playbook_dir}}/{{template}}.tar \ No newline at end of file diff --git a/ansible/template-test/vars/main.yml b/ansible/template-test/vars/main.yml new file mode 100644 index 00000000..d96547ca --- /dev/null +++ b/ansible/template-test/vars/main.yml @@ -0,0 +1,37 @@ +--- +# For the playbook to execute correctly, you must set the 5 variables in brackets below. Do not alter the others. +# Specify the template name exactly how it is spelled below in the template_map variable + +api_key: +ssh_key: +prefix: +template: