Skip to content

feat: use k8s secrets to store node gossip and grpc tls keys and mount them #499

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 { 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 @@
flags.applicationEnv,
flags.applicationProperties,
flags.bootstrapProperties,
flags.cacheDir,
flags.chainId,
flags.chartDirectory,
flags.deployHederaExplorer,
Expand All @@ -54,6 +63,7 @@
flags.fstChartVersion,
flags.hederaExplorerTlsHostName,
flags.hederaExplorerTlsLoadBalancerIp,
flags.keyFormat,
flags.log4j2Xml,
flags.namespace,
flags.nodeIDs,
Expand Down Expand Up @@ -143,10 +153,12 @@
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 @@
* @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 @@
* @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 @@
* @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 @@

// 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 @@

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)

Check warning on line 245 in src/commands/network.mjs

View check run for this annotation

Codecov / codecov/patch

src/commands/network.mjs#L245

Added line #L245 was not covered by tests
}

this.logger.debug('Prepared config', {
config,
cachedConfig: this.configManager.config
Expand All @@ -221,6 +267,50 @@
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
Loading