Skip to content

Commit

Permalink
feat: use k8s secrets to store node gossip and grpc tls keys and moun…
Browse files Browse the repository at this point in the history
…t them (#499)

Signed-off-by: Jeromy Cannon <[email protected]>
  • Loading branch information
jeromy-cannon authored Sep 4, 2024
1 parent 80639a9 commit ede1842
Show file tree
Hide file tree
Showing 14 changed files with 649 additions and 604 deletions.
1 change: 0 additions & 1 deletion .github/workflows/flow-build-application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ jobs:
needs:
- env-vars
- code-style
- e2e-tests
with:
custom-job-label: Mirror Node
npm-test-script: test-${{ needs.env-vars.outputs.e2e-mirror-node-test-subdir }}
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/flow-pull-request-checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ jobs:
needs:
- env-vars
- code-style
- e2e-tests
with:
custom-job-label: Mirror Node
npm-test-script: test-${{ needs.env-vars.outputs.e2e-mirror-node-test-subdir }}
Expand Down
96 changes: 93 additions & 3 deletions src/commands/network.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,25 @@ import { Listr } from 'listr2'
import { FullstackTestingError, IllegalArgumentError, MissingArgumentError } from '../core/errors.mjs'
import { BaseCommand } from './base.mjs'
import * as flags from './flags.mjs'
import { constants } from '../core/index.mjs'
import { constants, Templates } from '../core/index.mjs'
import * as prompts from './prompts.mjs'
import * as helpers from '../core/helpers.mjs'
import path from 'path'
import { validatePath } from '../core/helpers.mjs'
import fs from 'fs'

export class NetworkCommand extends BaseCommand {
constructor (opts) {
super(opts)

if (!opts || !opts.k8) throw new Error('An instance of core/K8 is required')
if (!opts || !opts.keyManager) throw new IllegalArgumentError('An instance of core/KeyManager is required', opts.keyManager)
if (!opts || !opts.platformInstaller) throw new IllegalArgumentError('An instance of core/PlatformInstaller is required', opts.platformInstaller)
if (!opts || !opts.profileManager) throw new MissingArgumentError('An instance of core/ProfileManager is required', opts.downloader)

this.k8 = opts.k8
this.keyManager = opts.keyManager
this.platformInstaller = opts.platformInstaller
this.profileManager = opts.profileManager
}

Expand All @@ -45,6 +53,7 @@ export class NetworkCommand extends BaseCommand {
flags.applicationEnv,
flags.applicationProperties,
flags.bootstrapProperties,
flags.cacheDir,
flags.chainId,
flags.chartDirectory,
flags.deployHederaExplorer,
Expand All @@ -54,6 +63,7 @@ export class NetworkCommand extends BaseCommand {
flags.fstChartVersion,
flags.hederaExplorerTlsHostName,
flags.hederaExplorerTlsLoadBalancerIp,
flags.keyFormat,
flags.log4j2Xml,
flags.namespace,
flags.nodeIDs,
Expand Down Expand Up @@ -143,10 +153,12 @@ export class NetworkCommand extends BaseCommand {
flags.applicationEnv,
flags.applicationProperties,
flags.bootstrapProperties,
flags.cacheDir,
flags.chainId,
flags.deployHederaExplorer,
flags.deployMirrorNode,
flags.hederaExplorerTlsLoadBalancerIp,
flags.keyFormat,
flags.log4j2Xml,
flags.persistentVolumeClaims,
flags.profileName,
Expand All @@ -160,6 +172,7 @@ export class NetworkCommand extends BaseCommand {
* @typedef {Object} NetworkDeployConfigClass
* -- flags --
* @property {string} applicationEnv
* @property {string} cacheDir
* @property {string} chartDirectory
* @property {boolean} deployHederaExplorer
* @property {boolean} deployMirrorNode
Expand All @@ -168,6 +181,7 @@ export class NetworkCommand extends BaseCommand {
* @property {string} fstChartVersion
* @property {string} hederaExplorerTlsHostName
* @property {string} hederaExplorerTlsLoadBalancerIp
* @property {string} keyFormat
* @property {string} namespace
* @property {string} nodeIDs
* @property {string} persistentVolumeClaims
Expand All @@ -176,8 +190,11 @@ export class NetworkCommand extends BaseCommand {
* @property {string} releaseTag
* @property {string} tlsClusterIssuerType
* -- extra args --
* @property {string[]} nodeIds
* @property {string} chartPath
* @property {string} keysDir
* @property {string[]} nodeIds
* @property {string} stagingDir
* @property {string} stagingKeysDir
* @property {string} valuesArg
* -- methods --
* @property {getUnusedConfigs} getUnusedConfigs
Expand All @@ -189,7 +206,14 @@ export class NetworkCommand extends BaseCommand {

// create a config object for subsequent steps
const config = /** @type {NetworkDeployConfigClass} **/ this.getConfig(NetworkCommand.DEPLOY_CONFIGS_NAME, NetworkCommand.DEPLOY_FLAGS_LIST,
['nodeIds', 'chartPath', 'valuesArg'])
[
'chartPath',
'keysDir',
'nodeIds',
'stagingDir',
'stagingKeysDir',
'valuesArg'
])

config.nodeIds = helpers.parseNodeIds(config.nodeIDs)

Expand All @@ -199,6 +223,28 @@ export class NetworkCommand extends BaseCommand {

config.valuesArg = await this.prepareValuesArg(config)

// compute other config parameters
config.keysDir = path.join(validatePath(config.cacheDir), 'keys')
config.stagingDir = Templates.renderStagingDir(
config.cacheDir,
config.releaseTag
)
config.stagingKeysDir = path.join(validatePath(config.stagingDir), 'keys')

if (!await this.k8.hasNamespace(config.namespace)) {
await this.k8.createNamespace(config.namespace)
}

// prepare staging keys directory
if (!fs.existsSync(config.stagingKeysDir)) {
fs.mkdirSync(config.stagingKeysDir, { recursive: true })
}

// create cached keys dir if it does not exist yet
if (!fs.existsSync(config.keysDir)) {
fs.mkdirSync(config.keysDir)
}

this.logger.debug('Prepared config', {
config,
cachedConfig: this.configManager.config
Expand All @@ -221,6 +267,50 @@ export class NetworkCommand extends BaseCommand {
ctx.config = /** @type {NetworkDeployConfigClass} **/ await self.prepareConfig(task, argv)
}
},
{
title: 'Prepare staging directory',
task: async (ctx, parentTask) => {
const subTasks = [
{
title: 'Copy Gossip keys to staging',
task: async (ctx, _) => {
const config = /** @type {NetworkDeployConfigClass} **/ ctx.config

await this.keyManager.copyGossipKeysToStaging(config.keyFormat, config.keysDir, config.stagingKeysDir, config.nodeIds)
}
},
{
title: 'Copy gRPC TLS keys to staging',
task: async (ctx, _) => {
const config = /** @type {NetworkDeployConfigClass} **/ ctx.config
for (const nodeId of config.nodeIds) {
const tlsKeyFiles = self.keyManager.prepareTLSKeyFilePaths(nodeId, config.keysDir)
await self.keyManager.copyNodeKeysToStaging(tlsKeyFiles, config.stagingKeysDir)
}
}
}
]

return parentTask.newListr(subTasks, {
concurrent: false,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION
})
}
},
{
title: 'Copy node keys to secrets',
task: async (ctx, parentTask) => {
const config = /** @type {NetworkDeployConfigClass} **/ ctx.config

const subTasks = self.platformInstaller.copyNodeKeys(config.stagingDir, config.nodeIds, config.keyFormat)

// set up the sub-tasks
return parentTask.newListr(subTasks, {
concurrent: true,
rendererOptions: constants.LISTR_DEFAULT_RENDERER_OPTION
})
}
},
{
title: `Install chart '${constants.FULLSTACK_DEPLOYMENT_CHART}'`,
task: async (ctx, _) => {
Expand Down
Loading

0 comments on commit ede1842

Please sign in to comment.