From d0f70358591a9df2814f3c74ad47f174b425f293 Mon Sep 17 00:00:00 2001 From: jvallexm Date: Mon, 22 Apr 2024 15:37:51 -0400 Subject: [PATCH 1/5] Issue 1808: Download Image Spacing (#1888) * bump version * fix: spacing * prune: old * prune --- CHANGELOG.md | 6 + client/package-lock.json | 4 +- client/package.json | 2 +- .../src/components/pages/diagrams/VpcMap.js | 17 +- client/src/lib/docs/release-notes.json | 8 + old/README.md | 3 - old/cdktf.js | 61 -- old/cdktf.test.js | 172 ----- old/teleport.js | 239 ------- old/teleport.test.js | 588 ------------------ package-lock.json | 4 +- package.json | 2 +- unit-tests/forms/diagrams/filters.test.js | 22 +- unit-tests/forms/wizard.test.js | 24 +- 14 files changed, 59 insertions(+), 1093 deletions(-) delete mode 100644 old/README.md delete mode 100644 old/cdktf.js delete mode 100644 old/cdktf.test.js delete mode 100644 old/teleport.js delete mode 100644 old/teleport.test.js diff --git a/CHANGELOG.md b/CHANGELOG.md index dd357070..d2af737c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## 1.15.2 + +### Fixes + +- Fixed an issue causing incorrect spacing for the titles of VPCs on downloaded `craig.png` images + ## 1.15.1 ### Upgrade Notes diff --git a/client/package-lock.json b/client/package-lock.json index 54d28302..fc6e12dc 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,12 +1,12 @@ { "name": "craig", - "version": "1.15.1", + "version": "1.15.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "craig", - "version": "1.15.1", + "version": "1.15.2", "license": "Apache-2.0", "dependencies": { "@apollo/client": "^3.4.10", diff --git a/client/package.json b/client/package.json index 93383eb3..10e0861b 100644 --- a/client/package.json +++ b/client/package.json @@ -1,6 +1,6 @@ { "name": "craig", - "version": "1.15.1", + "version": "1.15.2", "private": true, "license": "Apache-2.0", "scripts": { diff --git a/client/src/components/pages/diagrams/VpcMap.js b/client/src/components/pages/diagrams/VpcMap.js index f22addc2..9f9e299a 100644 --- a/client/src/components/pages/diagrams/VpcMap.js +++ b/client/src/components/pages/diagrams/VpcMap.js @@ -23,6 +23,8 @@ import { SubnetServiceMap } from "./SubnetServiceMap"; export const VpcMap = (props) => { let craig = props.craig; let nullVpcResources = false; + + // check items for null vpc [ "fortigate_vnf", "vsi", @@ -41,6 +43,9 @@ export const VpcMap = (props) => { nullVpcResources = true; } }); + + // if there are no vpcs, no vpcs are null, and the map is not static, show empty + // resource tile return craig.store.json.vpcs.length === 0 && !nullVpcResources && !props.static ? ( @@ -48,6 +53,7 @@ export const VpcMap = (props) => { name="VPCs" className="width580 marginTopHalfRem" customClick={ + // add custom click for the V2 page window.location.pathname !== "/v2/vpc" ? ( <> Add one from the{" "} @@ -60,15 +66,18 @@ export const VpcMap = (props) => { } /> ) : ( + // init array with name / pgw for null resources (nullVpcResources && !props.noDeployments ? [{ name: null, public_gateways: [] }] : [] ) - .concat(craig.store.json.vpcs) + .concat(craig.store.json.vpcs) // add vpcs .map((vpc, calcVpcIndex) => { let vpcBoxClassName = "subForm marginBottomSmall marginRight1Rem " + (props.small ? " width300" : " width580"); + // is invalid when no rg and not using data, no bucket options selected + // or the vpc has no name let isRed = (isNullOrEmptyString(vpc.resource_group, true) && !vpc.use_data) || isNullOrEmptyString(vpc.bucket, true) || @@ -93,7 +102,11 @@ export const VpcMap = (props) => { static={props.static} >
{ - if ( - !contains(["typescript", "python", "java", "csharp"], req.params.language) - ) { - res.status(400).send({ - error: "Unsupported language " + req.params.language, - }); - } else { - return this.convert(req).then((data) => { - if (!isNullOrEmptyString(data.stderr)) { - res.status(500).send({ - error: "CDKTF Conversion error", - data: data, - }); - } else res.send(data.stdout); - }); - } - }; -} - -module.exports = cdktfController; diff --git a/old/cdktf.test.js b/old/cdktf.test.js deleted file mode 100644 index 9887d594..00000000 --- a/old/cdktf.test.js +++ /dev/null @@ -1,172 +0,0 @@ -const { assert } = require("chai"); -const sinon = require("sinon"); -const cdktf = require("../express-controllers/cdktf"); -const res = require("../unit-tests/mocks/response.mock"); -const craigCdktf = require("../unit-tests/data-files/craig-cdktf.json"); -const fs = require("fs"); -const jsutil = require("util"); // Utils to run child process -const exec = jsutil.promisify(require("child_process").exec); // Exec from child process - -function mockExec(data, spy) { - this.data = data; - this.spy = spy; - this.promise = (command) => { - this.spy(command); - return new Promise((resolve, reject) => { - resolve(this.data); - }); - }; -} - -describe("cdktf api calls", () => { - describe("convert", () => { - let sinonExec = new sinon.spy(); - beforeEach(() => { - sinonExec = new sinon.spy(); - }); - describe("execPromise", () => { - it("should run exec with arbitrary text", () => { - let api = new cdktf(sinonExec); - api.execPromise("echo 'hi'"); - assert.isTrue( - sinonExec.calledOnceWith("echo 'hi'"), - "it should run command" - ); - }); - }); - describe("convert", () => { - beforeEach(() => { - sinonExec = new sinon.spy(); - }); - it("should send stdout data on success", () => { - let api = new cdktf(sinonExec); - api.convert( - { - body: { - data: { - test: { - hello: { - hi: "there", - }, - }, - }, - }, - params: { - language: "typescript", - }, - }, - res - ); - let expectedData = `echo 'data "test" "hello" {\n hi = "there"\n}' | cdktf convert --language typescript`; - assert.isTrue( - sinonExec.calledOnceWith(expectedData), - "it should call with expected data" - ); - }); - }); - describe("convertPost", () => { - it("should return cdktf data", () => { - let api = new cdktf(exec); - let actualData; - return api - .convertPost( - { - body: craigCdktf, - params: { - language: "typescript", - }, - }, - { - send: (data) => { - actualData = data; - }, - } - ) - .then(() => { - // commented out here until learning how to handle modules - // assert.deepEqual( - // actualData, - // fs.readFileSync("./unit-tests/data-files/craig.cdktf.ts", "utf8"), - // "it should return data" - // ); - }); - }).timeout(100000); - it("should return cdktf data", () => { - let callSpy = new sinon.spy(); - let mockPromise = new mockExec( - { - stderr: "err", - }, - callSpy - ).promise; - let api = new cdktf(mockPromise); - let actualData; - let status; - return api - .convertPost( - { - body: craigCdktf, - params: { - language: "typescript", - }, - }, - { - status: function (code) { - status = code; - return { - send: function (data) { - actualData = data; - }, - }; - }, - } - ) - .then(() => { - assert.deepEqual( - actualData, - { - error: "CDKTF Conversion error", - data: { - stderr: "err", - }, - }, - "it should return data" - ); - }); - }).timeout(100000); - it("should respond with an error when data unsupported format", () => { - let api = new cdktf(exec); - let actualData; - let status; - return api.convertPost( - { - body: craigCdktf, - params: { - language: "fff", - }, - }, - { - status: function (code) { - status = code; - return { - send: function (data) { - actualData = data; - assert.deepEqual( - status, - 400, - "it should send correct status" - ); - assert.deepEqual( - actualData, - { error: "Unsupported language fff" }, - "it should send correct error message" - ); - }, - }; - }, - } - ); - }); - }); - }); -}); diff --git a/old/teleport.js b/old/teleport.js deleted file mode 100644 index 4b90b713..00000000 --- a/old/teleport.js +++ /dev/null @@ -1,239 +0,0 @@ -const { jsonToTf } = require("json-to-tf"); -const { - snakeCase, - transpose, - getObjectFromArray, - hclEncode -} = require("lazy-z"); -const { RegexButWithWords } = require("regex-but-with-words"); -const { formatAppIdRedirectUrls } = require("../client/src/lib/json-to-iac/appid"); -const { teleportCloudInitText } = require("../client/src/lib/json-to-iac/constants"); -const { - tfBlock, - tfRef, - bucketRef, - cdktfRef, - jsonToTfPrint -} = require("../client/src/lib/json-to-iac/utils"); -const { formatVsi } = require("../client/src/lib/json-to-iac/vsi"); - -function teleportCloudInit() { - return teleportCloudInitText; -} - -/** - * get cloud init for teleport template - * @param {*} template - * @returns {object} terraform object - */ -function templateCloudinitConfig(template) { - return { - data: { - base64_encode: false, - gzip: false, - part: [ - { - content: `\${local.${snakeCase(template.deployment)}_user_data}` - } - ] - }, - name: `${template.deployment} cloud init` - }; -} - -/** - * get local data for template - * @param {*} template - * @return {object} tf object - */ -function localTemplateUserData(template) { - let templateData = hclEncode( - { - TELEPORT_LICENSE: `\${base64encode(tostring("${template.license}"))}`, - HTTPS_CERT: `\${base64encode(tostring("${template.https_cert}"))}`, - HTTPS_KEY: `\${base64encode(tostring("${template.https_key}"))}`, - HOSTNAME: `\${tostring("${template.hostname}")}`, - DOMAIN: `\${tostring("${template.domain}")}`, - COS_BUCKET: `\${${bucketRef( - template.cos, - template.bucket, - "bucket_name" - ).replace(/\{|}|\$/g, "")}}`, - COS_BUCKET_ENDPOINT: `\${${bucketRef( - template.cos, - template.bucket, - "s3_endpoint_public" - ).replace(/\{|}|\$/g, "")}}`, - HMAC_ACCESS_KEY_ID: `\${${tfRef( - "ibm_resource_key", - `${template.cos} object storage key ${template.cos_key}`, - 'credentials["cos_hmac_keys.access_key_id"]' - ).replace(/\{|}|\$/g, "")}}`, - HMAC_SECRET_ACCESS_KEY_ID: `\${${tfRef( - "ibm_resource_key", - `${template.cos} object storage key ${template.cos_key}`, - 'credentials["cos_hmac_keys.secret_access_key"]' - ).replace(/\{|}|\$/g, "")}}`, - APPID_CLIENT_ID: `\${${tfRef( - "ibm_resource_key", - `${template.appid}-${template.appid_key}-key`, - 'credentials["clientId"]' - ).replace(/\{|}|\$/g, "")}}`, - APPID_CLIENT_SECRET: `\${${tfRef( - "ibm_resource_key", - `${template.appid}-${template.appid_key}-key`, - 'credentials["secret"]' - ).replace(/\{|}|\$/g, "")}}`, - APPID_ISSUER_URL: `\${${tfRef( - "ibm_resource_key", - `${template.appid}-${template.appid_key}-key`, - 'credentials["oauthServerUrl"]' - ).replace(/\{|}|\$/g, "")}}`, - TELEPORT_VERSION: `\${tostring("${template.version}")}`, - MESSAGE_OF_THE_DAY: `\${tostring("${template.message_of_the_day}")}`, - CLAIM_TO_ROLES: template.claim_to_roles - }, - true - ).replace(/\}(?=\s+\{)/g, "},"); - let spacedTemplateData = []; - templateData.split(/\n/g).forEach(line => { - spacedTemplateData.push(` ` + line.replace(/("\${)|(}")/g, "")); - }); - let localData = { - locals: {} - }; - localData.locals[ - snakeCase(template.deployment) + "_user_data" - ] = `templatefile( - "\${path.module}/cloud-init.tpl", -${spacedTemplateData.join("\n")} - )`; - return localData; -} - -/** - * create teleport cloud init file - * @param {Object} template - * @param {string} template.deployment - * @param {string} template.license - * @param {string} template.https_cert - * @param {string} template.https_key - * @param {string} template.hostname - * @param {string} template.domain - * @param {string} template.bucket - * @param {string} template.bucket_endpoint - * @param {string} template.hmac_key_id - * @param {string} template.hmac_secret_key_id - * @param {string} template.appid - * @param {string} template.appid_secret - * @param {string} template.appid_url - * @param {string} template.message_of_the_day - * @param {string} template.version - * @param {Array} template.claim_to_roles - * @param {string} template.claim_to_roles.email - * @param {Array} template.claim_to_roles.roles - * @returns {string} terraform formatted code - */ -function formatTemplateCloudInit(template) { - return tfBlock( - "Test Deployment Cloud Init", - "\n" + - jsonToTf(JSON.stringify(localTemplateUserData(template))) - .replace(/"templatefile/g, "templatefile") - .replace(/\)"/g, ")") + - "\n" + - jsonToTfPrint( - "data", - "template_cloudinit_config", - `${template.deployment} cloud init`, - templateCloudinitConfig(template).data - ) - ); -} - -/** - * create teleport instance terraform - * @param {Object} instance - * @param {string} instance.name - * @param {Object} config - * @param {Object} config._options - * @param {string} config._options.prefix - * @returns {string} teleport instance string - */ -function formatTeleportInstance(instance, config) { - let nameRegex = new RegexButWithWords() - .negatedSet('"') - .oneOrMore() - .look.ahead(exp => { - exp - .literal('"\n') - .whitespace() - .whitespace() - .literal("image"); - }) - .done("g"); - let addressRegex = new RegexButWithWords() - .nonCapturingGroup('"') - .negatedSet('"{') - .oneOrMore() - .look.ahead(exp => { - exp - .literal('"') - .whitespace() - .literal("{"); - }) - .done("g"); - let tf = ""; - transpose( - { - user_data: cdktfRef( - `data.template_cloudinit_config.${snakeCase( - instance.name - )}_cloud_init.rendered` - ) - }, - instance - ); - tf += formatVsi(instance, config) - .replace(addressRegex, `"${snakeCase(instance.name + " teleport vsi")}`) - .replace( - nameRegex, - `${config._options.prefix}-${instance.name}-teleport-vsi` - ); - return tfBlock(instance.name + " Teleport Instance", tf); -} - -/** - * create teleport vsi tf - * @param {Object} config - * @param {Array} config.teleport - * @param {Object} config.teleport.template - * @returns {string} teleport terraform string - */ -function teleportTf(config) { - let tf = ""; - config.teleport_vsi.forEach(instance => { - tf += formatTemplateCloudInit(instance.template) + "\n"; - tf += formatTeleportInstance(instance, config) + "\n"; - tf += tfBlock( - "Redirect urls", - formatAppIdRedirectUrls( - getObjectFromArray(config.appid, "name", instance.appid), - [ - `https://${config._options.prefix}-${instance.name}-teleport-vsi.${instance.template.domain}:3080/v1/webapi/oidc/callback` - ], - instance.name + "_appid_urls" - ) - ); - }); - return tf; -} - -module.exports = { - teleportCloudInit, - formatTemplateCloudInit, - formatTeleportInstance, - teleportTf, - templateCloudinitConfig, - localTemplateUserData -}; diff --git a/old/teleport.test.js b/old/teleport.test.js deleted file mode 100644 index 59589799..00000000 --- a/old/teleport.test.js +++ /dev/null @@ -1,588 +0,0 @@ -const { assert } = require("chai"); -const { - teleportCloudInit, - formatTemplateCloudInit, - formatTeleportInstance, - teleportTf, -} = require("./teleport"); - -describe("teleport", () => { - describe("teleportCloudInit", () => { - it("should return cloud-init.tpl file", () => { - let actualData = teleportCloudInit(); - let expectedData = `#cloud-config -# This file is used to install teleport on a bastion host, configure teleport with App ID, and -# configure teleport with a COS instance. -# https://github.com/cloud-native-toolkit/terraform-vsi-bastion-teleport/blob/main/cloud-init.tpl -packages: - - tar -write_files: - # writing teleport license - - path: /root/license.pem - permissions: "0644" - encoding: base64 - content: \${TELEPORT_LICENSE} - - # writing https cert - - path: /root/ca.crt - permissions: "0644" - encoding: base64 - content: \${HTTPS_CERT} - - # writing https key - - path: /root/ca.key - permissions: "0644" - encoding: base64 - content: \${HTTPS_KEY} - - # writing teleport roles - - path: /root/roles.yaml - permissions: "0644" - content: | - # Example role - # Add any additional ones to the end - kind: "role" - version: "v3" - metadata: - name: "teleport-admin" - spec: - options: - max_connections: 3 - cert_format: standard - client_idle_timeout: 15m - disconnect_expired_cert: no - enhanced_recording: - - command - - network - forward_agent: true - max_session_ttl: 1h - port_forwarding: false - allow: - logins: [root] - node_labels: - "*": "*" - rules: - - resources: ["*"] - verbs: ["*"] - --- - - # writing oidc file to use App ID for authentication - - path: /root/oidc.yaml - permissions: "0644" - content: | - #oidc connector - kind: oidc - version: v2 - metadata: - name: appid - spec: - redirect_url: "https://\${HOSTNAME}.\${DOMAIN}:3080/v1/webapi/oidc/callback" - client_id: "\${APPID_CLIENT_ID}" - display: AppID - client_secret: "\${APPID_CLIENT_SECRET}" - issuer_url: "\${APPID_ISSUER_URL}" - scope: ["openid", "email"] - claims_to_roles: - %{~ for claims in CLAIM_TO_ROLES ~} - - {claim: "email", value: "\${claims.email}", roles: \${jsonencode(claims.roles)}} - %{~ endfor ~} - - # writing configuration for teleport - - path: /etc/teleport.yaml - permissions: "0644" - content: | - #teleport.yaml - teleport: - nodename: \${HOSTNAME}.\${DOMAIN} - data_dir: /var/lib/teleport - log: - output: stderr - severity: DEBUG - storage: - audit_sessions_uri: "s3://\${COS_BUCKET}?endpoint=\${COS_BUCKET_ENDPOINT}®ion=ibm" - - auth_service: - enabled: true - listen_addr: 0.0.0.0:3025 - authentication: - type: oidc - local_auth: false - license_file: /var/lib/teleport/license.pem - message_of_the_day: \${MESSAGE_OF_THE_DAY} - - ssh_service: - enabled: true - commands: - - name: hostname - command: [hostname] - period: 1m0s - - name: arch - command: [uname, -p] - period: 1h0m0s - - proxy_service: - enabled: true - listen_addr: 0.0.0.0:3023 - web_listen_addr: 0.0.0.0:3080 - tunnel_listen_addr: 0.0.0.0:3024 - https_cert_file: /var/lib/teleport/ca.crt - https_key_file: /var/lib/teleport/ca.key - - # writing script to start teleport - - path: /etc/systemd/system/teleport.service - permissions: "0644" - content: | - [Unit] - Description=Teleport Service - After=network.target - - [Service] - Type=simple - Restart=on-failure - Environment=AWS_ACCESS_KEY_ID=\${HMAC_ACCESS_KEY_ID} - Environment=AWS_SECRET_ACCESS_KEY=\${HMAC_SECRET_ACCESS_KEY_ID} - ExecStart=/usr/local/bin/teleport start --config=/etc/teleport.yaml --pid-file=/run/teleport.pid - ExecReload=/bin/kill -HUP $MAINPID - PIDFile=/run/teleport.pid - - [Install] - WantedBy=multi-user.target - - # writing script to install teleport on bastion host - - path: /root/install.sh - permissions: "0755" - content: | - #!/bin/bash - set -x - setup_path="/root" - teleport_file="teleport-ent-v\${TELEPORT_VERSION}-linux-amd64-bin.tar.gz" - teleport_url="https://get.gravitational.com/$teleport_file" - - #retrieve and extract teleport - cd $setup_path - curl --connect-timeout 30 --retry 15 --retry-delay 10 $teleport_url --output $teleport_file - tar -xvzf $teleport_file - - #Copy files over - cp $setup_path/teleport-ent/teleport /usr/local/bin/ - cp $setup_path/teleport-ent/tctl /usr/local/bin/ - cp $setup_path/teleport-ent/tsh /usr/local/bin/ - - #Make the /var/lib/teleport directory - TELEPORT_CONFIG_PATH="/var/lib/teleport" - mkdir $TELEPORT_CONFIG_PATH - - #copy files for /root to /var/lib/ - cp $setup_path/license.pem $TELEPORT_CONFIG_PATH - cp $setup_path/ca.crt $TELEPORT_CONFIG_PATH - cp $setup_path/ca.key $TELEPORT_CONFIG_PATH - - sudo systemctl daemon-reload - sudo systemctl start teleport - sudo systemctl enable teleport - - # allow ports for firewall - # check if firewalld is used - firewall-cmd -h - rc=$? - if [[ $rc -eq 0 ]]; then - systemctl stop firewalld - sudo firewall-offline-cmd --zone=public --add-port=3023/tcp - #sudo firewall-cmd --permanent --zone=public --add-port=3023/tcp - sudo firewall-offline-cmd --zone=public --add-port=3080/tcp - #sudo firewall-cmd --permanent --zone=public --add-port=3080/tcp - systemctl start firewalld - fi - - # check if firewalld is used - ufw version - rc=$? - if [[ $rc -eq 0 ]]; then - ufw allow 3023,3080/tcp - fi - - #distro=$(awk '/DISTRIB_ID=/' /etc/*-release | sed 's/DISTRIB_ID=//' | tr '[:upper:]' '[:lower:]') - #echo $distro - #if [[ $distro == "ubuntu" ]]; then - # ufw allow 3023,3080/tcp - #fi - - sleep 120 - ## Apply the oidc and role configuration - tctl create $setup_path/roles.yaml - tctl create $setup_path/oidc.yaml - -runcmd: - # running the script to install teleport on bastion host - - | - set -x - ( - while [ ! -f /root/install.sh ]; do - sleep 10 - done - /root/install.sh - ) &`; - assert.deepEqual( - actualData, - expectedData, - "it should return correct data" - ); - }); - }); - describe("formatTemplateCloudInit", () => { - it("should create cloud init template file", () => { - let actualData = formatTemplateCloudInit({ - deployment: "test-deployment", - license: "TELEPORT_LICENSE", - https_cert: "HTTPS_CERT", - https_key: "HTTPS_KEY", - hostname: "HOSTNAME", - domain: "DOMAIN", - bucket: "atracker-bucket", - appid: "appid", - appid_key: "b", - message_of_the_day: "MESSAGE_OF_THE_DAY", - version: "TELEPORT_VERSION", - cos_key: "cos-bind-key", - cos: "cos", - claim_to_roles: [ - { - email: "email@email.email", - roles: ["role1", "role2"], - }, - { - email: "email2@email.email", - roles: ["role1", "role2"], - }, - ], - }); - let expectedData = `############################################################################## -# Test Deployment Cloud Init -############################################################################## - -locals { - test_deployment_user_data = templatefile( - "\${path.module}/cloud-init.tpl", - { - TELEPORT_LICENSE = base64encode(tostring("TELEPORT_LICENSE")) - HTTPS_CERT = base64encode(tostring("HTTPS_CERT")) - HTTPS_KEY = base64encode(tostring("HTTPS_KEY")) - HOSTNAME = tostring("HOSTNAME") - DOMAIN = tostring("DOMAIN") - COS_BUCKET = ibm_cos_bucket.cos_object_storage_atracker_bucket_bucket.bucket_name - COS_BUCKET_ENDPOINT = ibm_cos_bucket.cos_object_storage_atracker_bucket_bucket.s3_endpoint_public - HMAC_ACCESS_KEY_ID = ibm_resource_key.cos_object_storage_key_cos_bind_key.credentials["cos_hmac_keys.access_key_id"] - HMAC_SECRET_ACCESS_KEY_ID = ibm_resource_key.cos_object_storage_key_cos_bind_key.credentials["cos_hmac_keys.secret_access_key"] - APPID_CLIENT_ID = ibm_resource_key.appid_b_key.credentials["clientId"] - APPID_CLIENT_SECRET = ibm_resource_key.appid_b_key.credentials["secret"] - APPID_ISSUER_URL = ibm_resource_key.appid_b_key.credentials["oauthServerUrl"] - TELEPORT_VERSION = tostring("TELEPORT_VERSION") - MESSAGE_OF_THE_DAY = tostring("MESSAGE_OF_THE_DAY") - CLAIM_TO_ROLES = [ - { - email = "email@email.email" - roles = ["role1","role2"] - }, - { - email = "email2@email.email" - roles = ["role1","role2"] - } - ] - } - ) -} - -data "template_cloudinit_config" "test_deployment_cloud_init" { - base64_encode = false - gzip = false - part { - content = local.test_deployment_user_data - } -} - -############################################################################## -`; - assert.deepEqual( - actualData, - expectedData, - "it should return correct data" - ); - }); - }); - describe("formatTeleportInstance", () => { - it("should create teleport vsi terraform", () => { - let actualData = formatTeleportInstance( - { - name: "test-deployment", - kms: "slz-kms", - encryption_key: "slz-vsi-volume-key", - image: "ibm-ubuntu-22-04-1-minimal-amd64-1", - profile: "cx2-4x8", - security_groups: ["management-vpe-sg"], - ssh_keys: ["slz-ssh-key"], - subnet: "vsi-zone-1", - vpc: "management", - resource_group: "slz-management-rg", - }, - { - _options: { - prefix: "iac", - region: "us-south", - tags: ["hello", "world"], - }, - resource_groups: [ - { - use_prefix: false, - name: "slz-service-rg", - use_data: false, - }, - { - use_prefix: false, - name: "slz-management-rg", - use_data: false, - }, - { - use_prefix: false, - name: "slz-workload-rg", - use_data: false, - }, - ], - ssh_keys: [ - { - name: "slz-ssh-key", - public_key: "public-key", - resource_group: "slz-management-rg", - use_data: false, - }, - ], - } - ); - let expectedData = `############################################################################## -# Test Deployment Teleport Instance -############################################################################## - -resource "ibm_is_instance" "test_deployment_teleport_vsi" { - name = "iac-test-deployment-teleport-vsi" - image = data.ibm_is_image.ibm_ubuntu_22_04_1_minimal_amd64_1.id - profile = "cx2-4x8" - resource_group = ibm_resource_group.slz_management_rg.id - vpc = ibm_is_vpc.management_vpc.id - zone = "us-south-1" - user_data = data.template_cloudinit_config.test_deployment_cloud_init.rendered - tags = [ - "hello", - "world" - ] - primary_network_interface { - subnet = ibm_is_subnet.management_vsi_zone_1.id - security_groups = [ - ibm_is_security_group.management_vpc_management_vpe_sg_sg.id - ] - } - boot_volume { - encryption = ibm_kms_key.slz_kms_slz_vsi_volume_key_key.crn - } - keys = [ - ibm_is_ssh_key.slz_ssh_key.id - ] -} - -############################################################################## -`; - assert.deepEqual( - actualData, - expectedData, - "it should return correct data" - ); - }); - }); - describe("teleportTf", () => { - it("should return code for teleport instance", () => { - let actualData = teleportTf({ - _options: { - prefix: "iac", - region: "us-south", - tags: ["hello", "world"], - }, - resource_groups: [ - { - use_prefix: false, - name: "slz-service-rg", - use_data: false, - }, - { - use_prefix: false, - name: "slz-management-rg", - use_data: false, - }, - { - use_prefix: false, - name: "slz-workload-rg", - use_data: false, - }, - ], - appid: [ - { - name: "test-appid", - use_data: false, - resource_group: "slz-service-rg", - keys: [ - { - appid: "test-appid", - name: "test-key", - }, - { - appid: "test-appid", - name: "test-key-2", - }, - ], - }, - ], - ssh_keys: [ - { - name: "slz-ssh-key", - public_key: "public-key", - resource_group: "slz-management-rg", - use_data: false, - }, - ], - teleport_vsi: [ - { - appid: "test-appid", - name: "test-deployment", - kms: "slz-kms", - encryption_key: "slz-vsi-volume-key", - image: "ibm-ubuntu-22-04-1-minimal-amd64-1", - profile: "cx2-4x8", - security_groups: ["management-vpe-sg"], - ssh_keys: ["slz-ssh-key"], - subnet: "vsi-zone-1", - vpc: "management", - resource_group: "slz-management-rg", - template: { - deployment: "test-deployment", - license: "TELEPORT_LICENSE", - https_cert: "HTTPS_CERT", - https_key: "HTTPS_KEY", - hostname: "HOSTNAME", - domain: "DOMAIN", - cos: "cos", - bucket: "bucket", - cos_key: "cos_key", - appid: "APPID_CLIENT_ID", - appid_key: "test", - message_of_the_day: "MESSAGE_OF_THE_DAY", - version: "TELEPORT_VERSION", - claim_to_roles: [ - { - email: "email@email.email", - roles: ["role1", "role2"], - }, - { - email: "email2@email.email", - roles: ["role1", "role2"], - }, - ], - }, - }, - ], - }); - let expectedData = `############################################################################## -# Test Deployment Cloud Init -############################################################################## - -locals { - test_deployment_user_data = templatefile( - "\${path.module}/cloud-init.tpl", - { - TELEPORT_LICENSE = base64encode(tostring("TELEPORT_LICENSE")) - HTTPS_CERT = base64encode(tostring("HTTPS_CERT")) - HTTPS_KEY = base64encode(tostring("HTTPS_KEY")) - HOSTNAME = tostring("HOSTNAME") - DOMAIN = tostring("DOMAIN") - COS_BUCKET = ibm_cos_bucket.cos_object_storage_bucket_bucket.bucket_name - COS_BUCKET_ENDPOINT = ibm_cos_bucket.cos_object_storage_bucket_bucket.s3_endpoint_public - HMAC_ACCESS_KEY_ID = ibm_resource_key.cos_object_storage_key_cos_key.credentials["cos_hmac_keys.access_key_id"] - HMAC_SECRET_ACCESS_KEY_ID = ibm_resource_key.cos_object_storage_key_cos_key.credentials["cos_hmac_keys.secret_access_key"] - APPID_CLIENT_ID = ibm_resource_key.appid_client_id_test_key.credentials["clientId"] - APPID_CLIENT_SECRET = ibm_resource_key.appid_client_id_test_key.credentials["secret"] - APPID_ISSUER_URL = ibm_resource_key.appid_client_id_test_key.credentials["oauthServerUrl"] - TELEPORT_VERSION = tostring("TELEPORT_VERSION") - MESSAGE_OF_THE_DAY = tostring("MESSAGE_OF_THE_DAY") - CLAIM_TO_ROLES = [ - { - email = "email@email.email" - roles = ["role1","role2"] - }, - { - email = "email2@email.email" - roles = ["role1","role2"] - } - ] - } - ) -} - -data "template_cloudinit_config" "test_deployment_cloud_init" { - base64_encode = false - gzip = false - part { - content = local.test_deployment_user_data - } -} - -############################################################################## - -############################################################################## -# Test Deployment Teleport Instance -############################################################################## - -resource "ibm_is_instance" "test_deployment_teleport_vsi" { - name = "iac-test-deployment-teleport-vsi" - image = data.ibm_is_image.ibm_ubuntu_22_04_1_minimal_amd64_1.id - profile = "cx2-4x8" - resource_group = ibm_resource_group.slz_management_rg.id - vpc = ibm_is_vpc.management_vpc.id - zone = "us-south-1" - user_data = data.template_cloudinit_config.test_deployment_cloud_init.rendered - tags = [ - "hello", - "world" - ] - primary_network_interface { - subnet = ibm_is_subnet.management_vsi_zone_1.id - security_groups = [ - ibm_is_security_group.management_vpc_management_vpe_sg_sg.id - ] - } - boot_volume { - encryption = ibm_kms_key.slz_kms_slz_vsi_volume_key_key.crn - } - keys = [ - ibm_is_ssh_key.slz_ssh_key.id - ] -} - -############################################################################## - -############################################################################## -# Redirect Urls -############################################################################## - -resource "ibm_appid_redirect_urls" "test_deployment_appid_urls" { - tenant_id = ibm_resource_instance.test_appid.guid - urls = [ - "https://iac-test-deployment-teleport-vsi.DOMAIN:3080/v1/webapi/oidc/callback" - ] -} - -############################################################################## -`; - assert.deepEqual( - actualData, - expectedData, - "it should return correct data" - ); - }); - }); -}); diff --git a/package-lock.json b/package-lock.json index 53413530..b90e5334 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "craig", - "version": "1.15.1", + "version": "1.15.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "craig", - "version": "1.15.1", + "version": "1.15.2", "license": "ISC", "dependencies": { "axios": "^1.6.3", diff --git a/package.json b/package.json index be3e9419..9538431b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "craig", - "version": "1.15.1", + "version": "1.15.2", "description": "gui for generating ibm cloud infrastructure resources", "main": "index.js", "scripts": { diff --git a/unit-tests/forms/diagrams/filters.test.js b/unit-tests/forms/diagrams/filters.test.js index bd46f4a5..97e15713 100644 --- a/unit-tests/forms/diagrams/filters.test.js +++ b/unit-tests/forms/diagrams/filters.test.js @@ -22,16 +22,18 @@ describe("filter functions", () => { let craig; beforeEach(() => { craig = newState(); - craig.store.json.classic_vlans[0] = { - name: "classic-priv-vlan", - datacenter: "dal10", - type: "PRIVATE", - }; - craig.store.json.classic_vlans[1] = { - name: "classic-pub-vlan", - datacenter: "dal10", - type: "PUBLIC", - }; + craig.store.json.classic_vlans = [ + { + name: "classic-priv-vlan", + datacenter: "dal10", + type: "PRIVATE", + }, + { + name: "classic-pub-vlan", + datacenter: "dal10", + type: "PUBLIC", + }, + ]; }); it("should return a list of filtered classic gateways for a non-HADR gateway with a private vlan only", () => { craig.store.json.classic_gateways[0] = { diff --git a/unit-tests/forms/wizard.test.js b/unit-tests/forms/wizard.test.js index eeeaceb9..0564a80f 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.15.1", + craig_version: "1.15.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -975,7 +975,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.15.1", + craig_version: "1.15.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -1892,7 +1892,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.15.1", + craig_version: "1.15.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -2403,7 +2403,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.15.1", + craig_version: "1.15.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -2905,7 +2905,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.15.1", + craig_version: "1.15.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -3484,7 +3484,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.15.1", + craig_version: "1.15.2", no_vpn_secrets_manager_auth: false, }, resource_groups: [ @@ -3654,7 +3654,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.15.1", + craig_version: "1.15.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -4225,7 +4225,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.15.1", + craig_version: "1.15.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -4770,7 +4770,7 @@ describe("setup wizard", () => { enable_power_vs: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.15.1", + craig_version: "1.15.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -5320,7 +5320,7 @@ describe("setup wizard", () => { enable_classic: false, enable_classic: false, power_vs_zones: [], - craig_version: "1.15.1", + craig_version: "1.15.2", no_vpn_secrets_manager_auth: false, }, resource_groups: [ @@ -5812,7 +5812,7 @@ describe("setup wizard", () => { enable_power_vs: true, enable_classic: false, power_vs_zones: ["dal10"], - craig_version: "1.15.1", + craig_version: "1.15.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, @@ -6314,7 +6314,7 @@ describe("setup wizard", () => { enable_power_vs: true, enable_classic: false, power_vs_zones: ["dal10"], - craig_version: "1.15.1", + craig_version: "1.15.2", power_vs_high_availability: false, no_vpn_secrets_manager_auth: false, }, From e2e298e11f3010210271360c9b9dd98b458e4de7 Mon Sep 17 00:00:00 2001 From: jvallexm Date: Tue, 23 Apr 2024 13:02:04 -0400 Subject: [PATCH 2/5] sm resource group (#1890) --- CHANGELOG.md | 4 ++++ client/src/lib/docs/release-notes.json | 4 +++- client/src/lib/state/secrets-manager.js | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2af737c..a5ded01f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. ## 1.15.2 +### Upgrade Notes + +- Existing Secrets Manager instances now require a Resource Group. Add your existing Resource Group to ensure Terraform has access to your Secrets Manager instance + ### Fixes - Fixed an issue causing incorrect spacing for the titles of VPCs on downloaded `craig.png` images diff --git a/client/src/lib/docs/release-notes.json b/client/src/lib/docs/release-notes.json index 9684be85..330faf0a 100644 --- a/client/src/lib/docs/release-notes.json +++ b/client/src/lib/docs/release-notes.json @@ -5,7 +5,9 @@ "fixes": [ "Fixed an issue causing incorrect spacing for the titles of VPCs on downloaded `craig.png` images" ], - "upgrade_notes": [] + "upgrade_notes": [ + "Existing Secrets Manager instances now require a Resource Group. Add your existing Resource Group to ensure Terraform has access to your Secrets Manager instance" + ] }, { "version": "1.15.1", diff --git a/client/src/lib/state/secrets-manager.js b/client/src/lib/state/secrets-manager.js index 8e8f02d3..5b461f56 100644 --- a/client/src/lib/state/secrets-manager.js +++ b/client/src/lib/state/secrets-manager.js @@ -93,7 +93,9 @@ function initSecretsManagerStore(store) { labelText: "Use Existing Instance", }, name: nameField("secrets_manager"), - resource_group: resourceGroupsField(), + resource_group: resourceGroupsField(false, { + noHideWhen: true, + }), plan: { type: "select", default: "standard", From a8bdd0ccd86289194e67b17519593d03b34c0f02 Mon Sep 17 00:00:00 2001 From: jvallexm Date: Thu, 25 Apr 2024 13:13:54 -0400 Subject: [PATCH 3/5] update: sm for vpn server (#1894) --- CHANGELOG.md | 1 + client/src/components/pages/vpc/VpcDeployments.js | 3 --- client/src/lib/docs/release-notes.json | 3 ++- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5ded01f..d3635f3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Upgrade Notes - Existing Secrets Manager instances now require a Resource Group. Add your existing Resource Group to ensure Terraform has access to your Secrets Manager instance +- When creating a VPN Server using the Certificate or Username and Password method, a Secrets Manager instance is no longer required ### Fixes diff --git a/client/src/components/pages/vpc/VpcDeployments.js b/client/src/components/pages/vpc/VpcDeployments.js index 0b89e404..1595068c 100644 --- a/client/src/components/pages/vpc/VpcDeployments.js +++ b/client/src/components/pages/vpc/VpcDeployments.js @@ -353,9 +353,6 @@ class VpcDeploymentsDiagramPage extends React.Component { ) : this.state.selectedItem === "load_balancers" && craig.store.json.vsi.length === 0 ? ( - ) : this.state.selectedItem === "vpn_servers" && - craig.store.json.secrets_manager.length === 0 ? ( - ) : contains(["fortigate_vnf", "vsi"], this.state.selectedItem) && craig.store.json.ssh_keys.length === 0 ? ( Date: Thu, 25 Apr 2024 13:25:36 -0700 Subject: [PATCH 4/5] Update access policy docs (#1895) --- .docs/access-policies.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.docs/access-policies.md b/.docs/access-policies.md index 52313b5c..f80b14ca 100644 --- a/.docs/access-policies.md +++ b/.docs/access-policies.md @@ -98,6 +98,7 @@ The following steps list how to create an access group with these required acces | Service | Resources | Access | |- |- |- | +| All Account Management services | All | Viewer | | Code Engine | All | Writer, Editor | | Container Registry | All | Manager | | Resource Group Only | All resource groups in the account | Viewer, Editor | From e7e7dc5f9403a7ead2483f02b310d43b91d2a55d Mon Sep 17 00:00:00 2001 From: Samuel Matzek Date: Fri, 26 Apr 2024 09:55:39 -0500 Subject: [PATCH 5/5] Document how to add a VPN server to the PowerVS PoC template (#1892) * Add VPN server to template doc * update sg rule * Fix scope of link * Space pad doc tables * Remove import of existing SM step * Update changelog --- .docs/powervs-poc.md | 43 ++++++++++++++++++++++++++ CHANGELOG.md | 4 +++ client/src/lib/docs/release-notes.json | 4 ++- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/.docs/powervs-poc.md b/.docs/powervs-poc.md index 18dbcfda..7bf1d781 100644 --- a/.docs/powervs-poc.md +++ b/.docs/powervs-poc.md @@ -115,6 +115,49 @@ There are multiple ways to manage volumes in Power Virtual Server: * To add volumes that will not be attached to a virtual server, click the "Add Resource" (plus) button on the Power VS workspace, choose "Power Volume", fill in the attributes and click Submit. * To remove volumes that are not attached to a virtual server, click on the volume's icon and click the delete button in the right panel. +### VPC VPN Server - Client to Site VPN +The VPC VPN Server used for client to site VPNs requires SSL/TLS certificates stored in a Secrets Manager instance. The Secrets Manager should be created outside of CRAIG and populated with the certificates before creating the VPN Server deployment in CRAIG. + +1. Create a Secrets Manager instance and either [order public certificates](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-public-certificates&interface=ui +), [create private certificates](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-private-certificates&interface=ui +), or [import certificates](https://cloud.ibm.com/docs/secrets-manager?topic=secrets-manager-certificates&interface=ui). +2. Choose VPC Deployments from the menu and create a new security group for the VPN Server. +Create the security group in the `transit-rg` resource group. +Add the following rules to the group: + +| Name | Direction | CIDR | Protocol | Port | +| --------------- | --------- | --------- | -------- | ---- | +| vpn-inbound-udp | inbound | 0.0.0.0/0 | UDP | 443 | +| vpn-inbound-tcp | inbound | 0.0.0.0/0 | TCP | 443 | +| vpn-outbound | outbound | 0.0.0.0/0 | ALL | ALL | + +3. Create a VPN Server deployment +Set the VPN Server values using the following table as a guide. + +| Field | Value | +| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Resource group | transit-rg | +| VPC | transit | +| Subnets | vpn-zone-1 | +| Security group | security group created in step 3 | +| Authentication method | Certificate | +| Certificate CRN | The CRN of the Secrets Manager secret containing the certificate for the VPN Server. | +| Client CA CRN | The CRN of the Secrets Manager secret containing the certificate for the VPN client. | +| Client CIDR Pool | Specify a network CIDR that does not conflict with any on-premises network, the VPC network, or the Power VS network. The CIDR should also be a subnet of 10.0.0.0/8 to avoid additional security group changes. | +| Port | 443 | +| Protocol | UDP | +| Enable split tunneling | True is recommended | +| Client idle timeout | 600 | +| Client DNS Server IPs | Leave empty | +| Additional VPC Prefixes | Zone 1, add the CIDR specified in `Client CIDR Pool` | + +4. After the VPN server is created, click on the VPN server icon to add routes. Routes are added by clicking the plus icon at the bottom of the VPN Server settings. Add two routes: + +| Name | Destination | Action | +| ------- | ----------------------------------------------------------------------- | --------- | +| vpn-vsi | the VSI network CIDR (`10.10.0.0/28` by default in the template) | Deliver | +| powervs | the Power VS network CIDR (`192.168.0.0/24` by default in the template) | Translate | + ## Saving the configuration and deploying the resources The configuration can be downloaded by clicking the download button in the top right of the screen. This downloads a zip of a file named craig.json and Terraform artifacts. The craig.json can be imported back into CRAIG for continued editing. diff --git a/CHANGELOG.md b/CHANGELOG.md index d3635f3c..bbc68431 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ All notable changes to this project will be documented in this file. - Fixed an issue causing incorrect spacing for the titles of VPCs on downloaded `craig.png` images +### Features + +- Added documentation for adding a VPN Server to the Power VS PoC template + ## 1.15.1 ### Upgrade Notes diff --git a/client/src/lib/docs/release-notes.json b/client/src/lib/docs/release-notes.json index 8f3202b0..6371bbb4 100644 --- a/client/src/lib/docs/release-notes.json +++ b/client/src/lib/docs/release-notes.json @@ -1,7 +1,9 @@ [ { "version": "1.15.2", - "features": [], + "features": [ + "Added documentation for adding a VPN Server to the Power VS PoC template" + ], "fixes": [ "Fixed an issue causing incorrect spacing for the titles of VPCs on downloaded `craig.png` images" ],