Skip to content
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
47 changes: 47 additions & 0 deletions image/templates/common/deploy-central-db.sh.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)"
KUBE_COMMAND=${KUBE_COMMAND:-{{.K8sConfig.Command}}}
NAMESPACE="${ROX_NAMESPACE:-stackrox}"

echo "Deploy Central DB ..."
${KUBE_COMMAND} -n ${NAMESPACE} apply -f "${DIR}/central/."
${KUBE_COMMAND} -n ${NAMESPACE} patch deploy/central -p '
{
"spec": {
"template": {
"spec": {
"containers": [
{
"name": "central",
"volumeMounts": [
{
"name": "central-db-password",
"mountPath": "/run/secrets/stackrox.io/db-password"
},
{
"name": "central-external-db-volume",
"mountPath": "/etc/ext-db"
}
]
}
],
"volumes": [
{
"name": "central-db-password",
"secret": {
"secretName": "central-db-password"
}
},
{
"name": "central-external-db-volume",
"configMap": {
"name": "central-external-db",
"optional": true
}
}
]
}
}
}
}
'
12 changes: 12 additions & 0 deletions image/templates/helm/stackrox-central/.helmtplignore.htpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,17 @@ templates/*
!templates/_*.tpl
!templates/01-central-05-tls-secret.yaml
templates/*
[< else if eq .RenderMode "centralDBOnly" >]
!templates/_*.tpl
!templates/01-central-*-central-db.yaml
!templates/01-central-*-db-serviceaccount.yaml
!templates/01-central-*-db-psps.yaml
!templates/01-central-*-db-security.yaml
!templates/01-central-*-db-configmap.yaml
!templates/01-central-*-external-db-configmap.yaml
!templates/01-central-*-db-networkpolicy.yaml
!templates/01-central-*-db-pvc.yaml
!templates/01-central-*-db-tls-secret.yaml
templates/*
[< end >]
templates/keep.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{{- include "srox.init" . -}}

{{- if and ._rox.central.db._serviceTLS ._rox._ca }}
apiVersion: v1
kind: Secret
metadata:
name: central-db-tls
namespace: {{ .Release.Namespace }}
labels:
{{- include "srox.labels" (list . "secret" "central-db-tls") | nindent 4 }}
annotations:
{{- include "srox.annotations" (list . "secret" "central-db-tls") | nindent 4 }}
"helm.sh/hook": "pre-install,pre-upgrade"
"helm.sh/resource-policy": "keep"
type: Opaque
stringData:
ca.pem: |
{{- ._rox._ca.Cert | nindent 4 }}
cert.pem: |
{{- ._rox.central.db._serviceTLS.Cert | nindent 4 }}
key.pem: |
{{- ._rox.central.db._serviceTLS.Key | nindent 4 }}
{{- end }}
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,3 @@ stringData:
{{- else if or ._rox.central._serviceTLS ._rox.central._jwtSigner }}
{{ include "srox.fail" "Service TLS certificates and/or JWT signer key can only be created/updated if all data AND the service CA are present/specified." }}
{{- end }}
{{- if and ._rox.central.db._serviceTLS ._rox._ca }}
---
apiVersion: v1
kind: Secret
metadata:
name: central-db-tls
namespace: {{ .Release.Namespace }}
labels:
{{- include "srox.labels" (list . "secret" "central-db-tls") | nindent 4 }}
annotations:
{{- include "srox.annotations" (list . "secret" "central-db-tls") | nindent 4 }}
"helm.sh/hook": "pre-install,pre-upgrade"
"helm.sh/resource-policy": "keep"
type: Opaque
stringData:
ca.pem: |
{{- ._rox._ca.Cert | nindent 4 }}
cert.pem: |
{{- ._rox.central.db._serviceTLS.Cert | nindent 4 }}
key.pem: |
{{- ._rox.central.db._serviceTLS.Key | nindent 4 }}
{{- end }}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ spec:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: central-db
name: {{ $claimName }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "srox.labels" (list . "persistentvolumeclaim" "central-db") | nindent 4 }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,6 @@ spec:
mountPath: /var/lib/stackrox
- name: central-config-volume
mountPath: /etc/stackrox
- name: central-external-db-volume
mountPath: /etc/ext-db
- name: proxy-config-volume
mountPath: /run/secrets/stackrox.io/proxy-config/
readOnly: true
Expand All @@ -157,6 +155,8 @@ spec:
{{- if ._rox.central.db.enabled }}
- name: central-db-password
mountPath: /run/secrets/stackrox.io/db-password
- name: central-external-db-volume
mountPath: /etc/ext-db
{{- end }}
{{- range $extraMount := (default list ._rox.central.extraMounts) }}
- name: {{ $extraMount.name }}
Expand Down Expand Up @@ -201,10 +201,6 @@ spec:
configMap:
name: central-config
optional: true
- name: central-external-db-volume
configMap:
name: central-external-db
optional: true
- name: proxy-config-volume
secret:
secretName: proxy-config
Expand All @@ -216,6 +212,10 @@ spec:
- name: central-db-password
secret:
secretName: central-db-password
- name: central-external-db-volume
configMap:
name: central-external-db
optional: true
{{- end }}
- name: stackrox-db
{{- toYaml ._rox.central.persistence._volumeCfg | nindent 8 }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
or no other persistence backend has been configured yet. */}}
{{ if or (not (deepEqual $._rox._configShape.central.db.persistence.persistentVolumeClaim $centralDBCfg.persistence.persistentVolumeClaim)) (not $dbVolumeCfg) }}
{{ $dbPVCCfg := $centralDBCfg.persistence.persistentVolumeClaim }}
{{ $_ := include "srox.mergeInto" (list $dbPVCCfg $._rox._defaults.dbPVCDefaults (dict "createClaim" $.Release.IsInstall)) }}
{{ $_ := include "srox.mergeInto" (list $dbPVCCfg $._rox._defaults.dbPVCDefaults (dict "createClaim" (or .Release.IsInstall (eq $._rox._renderMode "centralDBOnly")))) }}
{{ $_ = set $dbVolumeCfg "persistentVolumeClaim" (dict "claimName" $dbPVCCfg.claimName) }}
{{ if $dbPVCCfg.createClaim }}
{{ $_ = set $centralDBCfg.persistence "_pvcCfg" $dbPVCCfg }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@
[<- end >]
{{ end }}
{{ $_ = set $env "_proxyConfig" $proxyCfg }}
{{ $_ = set $._rox "_renderMode" "[< .RenderMode >]" }}

{{/*
Central setup.
Expand Down
168 changes: 168 additions & 0 deletions pkg/renderer/central_db_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package renderer

import (
"fmt"
"strings"
"testing"

v1 "github.com/stackrox/rox/generated/api/v1"
"github.com/stackrox/rox/generated/storage"
"github.com/stackrox/rox/pkg/buildinfo/testbuildinfo"
"github.com/stackrox/rox/pkg/certgen"
"github.com/stackrox/rox/pkg/images/defaults"
flavorUtils "github.com/stackrox/rox/pkg/images/defaults/testutils"
"github.com/stackrox/rox/pkg/k8sutil"
"github.com/stackrox/rox/pkg/mtls"
"github.com/stackrox/rox/pkg/zip"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)

func TestRenderCentralDBOnly(t *testing.T) {
suite.Run(t, new(centralDBTestSuite))
}

type centralDBTestSuite struct {
suite.Suite
restorer *testbuildinfo.TestBuildTimestampRestorer
testFlavor defaults.ImageFlavor
testCA mtls.CA
centralDBCert *mtls.IssuedCert
}

func (suite *centralDBTestSuite) SetupSuite() {
suite.T().Setenv("TEST_VERSIONS", "true")
suite.testFlavor = flavorUtils.MakeImageFlavorForTest(suite.T())
var err error
suite.testCA, err = certgen.GenerateCA()
require.NoError(suite.T(), err)
suite.centralDBCert, err = suite.testCA.IssueCertForSubject(mtls.CentralDBSubject)
require.NoError(suite.T(), err)
}

func (suite *centralDBTestSuite) TearDownSuite() {
suite.restorer.Restore()
}

func (suite *centralDBTestSuite) testWithHostPath(t *testing.T, c Config, m mode) {
log.Info("Test host path")
c.HostPath = &HostPathPersistence{
DB: &HostPathPersistenceInstance{
HostPath: "/var/lib/stackrox",
},
}
files, err := render(c, m, suite.testFlavor)
assert.NoError(t, err)
suite.verifyFiles(t, files, false)

c.HostPath = &HostPathPersistence{
DB: &HostPathPersistenceInstance{
HostPath: "/var/lib/stackrox-db",
NodeSelectorKey: "key",
NodeSelectorValue: "value",
},
}
files, err = render(c, m, suite.testFlavor)
assert.NoError(t, err)
suite.verifyFiles(t, files, false)
}

func (suite *centralDBTestSuite) verifyFiles(t *testing.T, files []*zip.File, pvc bool) {
fm := make(map[string][]unstructured.Unstructured, len(files))
for _, f := range files {
if f.Name == "README" || strings.HasSuffix(f.Name, ".sh") {
assert.NotEmpty(t, f.Content)
continue
}
unstructuredObjs, err := k8sutil.UnstructuredFromYAMLMulti(string(f.Content))
require.NoError(t, err, f.Name)
fm[strings.TrimPrefix(f.Name, "central/")] = unstructuredObjs
}
// Verify secrets overwrite
suite.verifyFile(t, fm, "01-central-05-db-tls-secret.yaml", "Secret", string(suite.testCA.CertPEM()), "stringData", "ca.pem")
suite.verifyFile(t, fm, "01-central-05-db-tls-secret.yaml", "Secret", string(suite.centralDBCert.CertPEM), "stringData", "cert.pem")
suite.verifyFile(t, fm, "01-central-05-db-tls-secret.yaml", "Secret", string(suite.centralDBCert.KeyPEM), "stringData", "key.pem")
// Verify top level resources
suite.verifyFile(t, fm, "01-central-00-db-serviceaccount.yaml", "ServiceAccount", "central-db", "metadata", "name")
suite.verifyFile(t, fm, "01-central-08-db-configmap.yaml", "ConfigMap", "central-db-config", "metadata", "name")
suite.verifyFile(t, fm, "01-central-08-external-db-configmap.yaml", "ConfigMap", "central-external-db", "metadata", "name")
suite.verifyFile(t, fm, "01-central-12-central-db.yaml", "Deployment", "central-db", "metadata", "name")
// Verify Persistent Volume Claim
if pvc {
suite.verifyFile(t, fm, "01-central-11-db-pvc.yaml", "PersistentVolumeClaim", "name", "metadata", "name")
suite.verifyFile(t, fm, "01-central-11-db-pvc.yaml", "PersistentVolumeClaim", "name", "metadata", "name")
} else {
assert.NotContains(t, files, "01-central-11-db-pvc.yaml")
}
}

func (suite *centralDBTestSuite) verifyFile(t *testing.T, fileMap map[string][]unstructured.Unstructured, fileName string, kind string, value string, fields ...string) {
objs, ok := fileMap[fileName]
require.True(t, ok, "%s not found", fileName)
require.GreaterOrEqual(t, len(objs), 1)
for _, obj := range objs {
val, ok, err := unstructured.NestedString(obj.UnstructuredContent(), "kind")
require.NoError(t, err)
require.True(t, ok)
if val == kind {
val, ok, err := unstructured.NestedString(obj.UnstructuredContent(), fields...)
require.NoError(t, err)
require.True(t, ok)
assert.Equal(t, val, value)
return
}
}
assert.Failf(t, "Cannot find kind", kind)
}

func (suite *centralDBTestSuite) testWithPV(t *testing.T, c Config, m mode) {
log.Info("Test PV")
c.External = &ExternalPersistence{
DB: &ExternalPersistenceInstance{
Name: "name",
},
}
files, err := render(c, m, suite.testFlavor)
assert.NoError(t, err)
suite.verifyFiles(t, files, true)

c.External = &ExternalPersistence{
DB: &ExternalPersistenceInstance{
Name: "name",
StorageClass: "storageClass",
},
}
files, err = render(c, m, suite.testFlavor)
assert.NoError(t, err)
suite.verifyFiles(t, files, true)
}

func (suite *centralDBTestSuite) TestRenderCentralDBBundle() {
for _, orch := range []storage.ClusterType{storage.ClusterType_KUBERNETES_CLUSTER, storage.ClusterType_OPENSHIFT_CLUSTER, storage.ClusterType_OPENSHIFT4_CLUSTER} {
suite.T().Run(fmt.Sprintf("DbBundle-%s", orch), func(t *testing.T) {
centralFileMap := make(map[string][]byte, 4)
centralFileMap["central-db-password"] = []byte("Apassword")
centralFileMap["central-db-cert.pem"] = suite.centralDBCert.CertPEM
centralFileMap["central-db-key.pem"] = suite.centralDBCert.KeyPEM
centralFileMap[mtls.CACertFileName] = suite.testCA.CertPEM()

conf := Config{
ClusterType: storage.ClusterType_KUBERNETES_CLUSTER,
K8sConfig: &K8sConfig{
CommonConfig: CommonConfig{
CentralDBImage: "stackrox/central-db:2.2.11.0-57-g392c0f5bed-dirty",
},
EnableCentralDB: true,
},
SecretsByteMap: centralFileMap,
}
conf.K8sConfig.DeploymentFormat = v1.DeploymentFormat_KUBECTL
conf.ClusterType = orch

suite.testWithHostPath(t, conf, centralDBOnly)
suite.testWithPV(t, conf, centralDBOnly)
})
}
}
13 changes: 8 additions & 5 deletions pkg/renderer/helm_values.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"text/template"

"github.com/pkg/errors"
"github.com/stackrox/rox/pkg/env"
helmTemplate "github.com/stackrox/rox/pkg/helm/template"
"github.com/stackrox/rox/pkg/templates"
"github.com/stackrox/rox/pkg/zip"
Expand Down Expand Up @@ -312,16 +311,20 @@ central:
htpasswd: |
{{- index .SecretsBase64Map "htpasswd" | b64dec | nindent 6 }}
{{- end }}

{{- if .K8sConfig.EnableCentralDB }}
db:
{{- if ne (index .SecretsBase64Map "central-db-password") "" }}
# Password for securing the communication between Central and its DB.
# This password is not relevant to the user (unless for debugging purposes);
# it merely acts as a pre-shared, random secret for securing the connection.
db:
password:
value: {{ index .SecretsBase64Map "central-db-password" | b64dec }}
{{- end }}
{{- if ne (index .SecretsBase64Map "central-db-cert.pem") "" }}
serviceTLS:
cert: |
{{- index .SecretsBase64Map "central-db-cert.pem" | b64dec | nindent 8 }}
key: |
{{- index .SecretsBase64Map "central-db-key.pem" | b64dec | nindent 8 }}
{{- end }}

{{- if ne (index .SecretsBase64Map "jwt-key.pem") "" }}
Expand Down Expand Up @@ -394,7 +397,7 @@ var (
// two entries, one for `values-public.yaml`, and one for `values-private.yaml`.
func renderNewHelmValues(c Config) ([]*zip.File, error) {
privateTemplate := privateValuesTemplate
if env.PostgresDatastoreEnabled.BooleanSetting() {
if c.K8sConfig.EnableCentralDB {
privateTemplate = privateValuesPostgresTemplate
}

Expand Down
Loading