diff --git a/app/config/custom-environment-variables.json b/app/config/custom-environment-variables.json index 9da2a390..d7daa552 100644 --- a/app/config/custom-environment-variables.json +++ b/app/config/custom-environment-variables.json @@ -1,16 +1,18 @@ { "basicAuth": { "enabled": "BASICAUTH_ENABLED", - "username": "BASICAUTH_USERNAME", - "password": "BASICAUTH_PASSWORD" + "password": "BASICAUTH_PASSWORD", + "username": "BASICAUTH_USERNAME" }, "db": { "enabled": "DB_ENABLED", "database": "DB_DATABASE", "host": "DB_HOST", - "username": "DB_USERNAME", "password": "DB_PASSWORD", - "port": "DB_PORT" + "poolMin": "DB_POOL_MIN", + "poolMax": "DB_POOL_MAX", + "port": "DB_PORT", + "username": "DB_USERNAME" }, "keycloak": { "enabled": "KC_ENABLED", diff --git a/app/config/default.json b/app/config/default.json index 799086bd..901f421d 100644 --- a/app/config/default.json +++ b/app/config/default.json @@ -3,6 +3,8 @@ "database": "coms", "host": "localhost", "port": "5432", + "poolMin": "2", + "poolMax": "10", "username": "app" }, "objectStorage": { diff --git a/app/knexfile.js b/app/knexfile.js index f7042658..504611f3 100644 --- a/app/knexfile.js +++ b/app/knexfile.js @@ -53,8 +53,8 @@ module.exports = { directory: __dirname + '/src/db/migrations' }, pool: { - min: 2, - max: 10 + min: parseInt(config.get('db.poolMin')), + max: parseInt(config.get('db.poolMax')) // This shouldn't be here: https://github.com/knex/knex/issues/3455#issuecomment-535554401 // propagateCreateError: false }, diff --git a/app/src/components/constants.js b/app/src/components/constants.js index afad64fb..9cb524af 100644 --- a/app/src/components/constants.js +++ b/app/src/components/constants.js @@ -32,6 +32,12 @@ module.exports = Object.freeze({ URL: 'url' }, + /** + * Generic email regex modified to require domain of at least 2 characters + * @see {@link https://emailregex.com/} + */ + EMAILREGEX: '^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]{2,})+$', + /** Maximum Content Length supported by S3 CopyObjectCommand */ MAXCOPYOBJECTLENGTH: 5 * 1024 * 1024 * 1024, diff --git a/app/src/validators/common.js b/app/src/validators/common.js index 155c6140..7c381ce8 100644 --- a/app/src/validators/common.js +++ b/app/src/validators/common.js @@ -1,6 +1,6 @@ const { Joi: baseJoi } = require('express-validation'); -const { Permissions } = require('../components/constants'); +const { EMAILREGEX, Permissions } = require('../components/constants'); /** * @constant Joi @@ -39,7 +39,7 @@ const type = { truthy: Joi.boolean() .truthy('true', 1, '1', 't', 'yes', 'y', 'false', 0, '0', 'f', 'no', 'n'), - email: Joi.string().max(255).email(), + email: Joi.string().pattern(new RegExp(EMAILREGEX)).max(255), uuidv4: Joi.string().guid({ version: 'uuidv4' diff --git a/app/tests/unit/validators/common.spec.js b/app/tests/unit/validators/common.spec.js index 2db9e511..22d866e2 100644 --- a/app/tests/unit/validators/common.spec.js +++ b/app/tests/unit/validators/common.spec.js @@ -2,7 +2,7 @@ const crypto = require('crypto'); const jestJoi = require('jest-joi'); expect.extend(jestJoi.matchers); -const { Permissions } = require('../../../src/components/constants'); +const { EMAILREGEX, Permissions } = require('../../../src/components/constants'); const { scheme, type } = require('../../../src/validators/common'); describe('type', () => { @@ -50,7 +50,6 @@ describe('type', () => { describe('email', () => { const model = type.email.describe(); - it('is a string', () => { expect(model).toBeTruthy(); expect(model.type).toEqual('string'); @@ -60,14 +59,18 @@ describe('type', () => { expect(Array.isArray(model.rules)).toBeTruthy(); expect(model.rules).toHaveLength(2); expect(model.rules).toEqual(expect.arrayContaining([ - expect.objectContaining( - { - 'args': { - 'limit': 255 - }, - 'name': 'max' + expect.objectContaining({ + 'args': { + 'regex': new RegExp(EMAILREGEX).toString() + }, + 'name': 'pattern' + }), + expect.objectContaining({ + 'args': { + 'limit': 255 }, - { 'name': 'email' }) + 'name': 'max' + }) ])); }); diff --git a/charts/coms/Chart.yaml b/charts/coms/Chart.yaml index 8155a355..e9cfaaa4 100644 --- a/charts/coms/Chart.yaml +++ b/charts/coms/Chart.yaml @@ -3,7 +3,7 @@ name: common-object-management-service # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.0.12 +version: 0.0.13 kubeVersion: ">= 1.13.0" description: A microservice for managing access control to S3 Objects # A chart can be either an 'application' or a 'library' chart. diff --git a/charts/coms/templates/deploymentconfig.yaml b/charts/coms/templates/deploymentconfig.yaml index 9baa81be..209e3c43 100644 --- a/charts/coms/templates/deploymentconfig.yaml +++ b/charts/coms/templates/deploymentconfig.yaml @@ -1,3 +1,10 @@ +{{ $dbHostName := .Values.config.configMap.DB_HOST }} +{{ $dbSecretName := printf "%s-%s" (include "coms.fullname" .) "passphrase" }} +{{- if .Values.patroni.enabled }} +{{ $dbHostName = include "patroni.fullname" .Subcharts.patroni }} +{{ $dbSecretName = include "patroni.fullname" .Subcharts.patroni }} +{{- end }} + {{- define "coms.connectsTo" -}} apiVersion: apps/v1 kind: StatefulSet @@ -40,19 +47,19 @@ spec: valueFrom: secretKeyRef: key: app-db-name - name: {{ include "patroni.fullname" .Subcharts.patroni }} + name: {{ $dbSecretName }} - name: DB_HOST - value: {{ include "patroni.fullname" .Subcharts.patroni }} + value: {{ $dbHostName }} - name: DB_USERNAME valueFrom: secretKeyRef: key: app-db-username - name: {{ include "patroni.fullname" .Subcharts.patroni }} + name: {{ $dbSecretName }} - name: DB_PASSWORD valueFrom: secretKeyRef: key: app-db-password - name: {{ include "patroni.fullname" .Subcharts.patroni }} + name: {{ $dbSecretName }} {{- end }} type: Rolling template: @@ -115,19 +122,19 @@ spec: valueFrom: secretKeyRef: key: app-db-name - name: {{ include "patroni.fullname" .Subcharts.patroni }} + name: {{ $dbSecretName }} - name: DB_HOST - value: {{ include "patroni.fullname" .Subcharts.patroni }} + value: {{ $dbHostName }} - name: DB_USERNAME valueFrom: secretKeyRef: key: app-db-username - name: {{ include "patroni.fullname" .Subcharts.patroni }} + name: {{ $dbSecretName }} - name: DB_PASSWORD valueFrom: secretKeyRef: key: app-db-password - name: {{ include "patroni.fullname" .Subcharts.patroni }} + name: {{ $dbSecretName }} {{- end }} {{- if or .Values.features.oidcAuth .Values.config.configMap.KC_ENABLED }} - name: KC_CLIENTID diff --git a/charts/coms/templates/hpa.yaml b/charts/coms/templates/hpa.yaml index 39208a97..e4b7c545 100644 --- a/charts/coms/templates/hpa.yaml +++ b/charts/coms/templates/hpa.yaml @@ -1,6 +1,6 @@ {{- if .Values.autoscaling.enabled }} --- -apiVersion: autoscaling/v2beta2 +apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: {{ include "coms.fullname" . }} diff --git a/charts/coms/templates/secret.yaml b/charts/coms/templates/secret.yaml index beb7e228..e80e78e4 100644 --- a/charts/coms/templates/secret.yaml +++ b/charts/coms/templates/secret.yaml @@ -1,18 +1,18 @@ -{{- $bPassword := (randAlphaNum 32) | b64enc }} -{{- $bUsername := (randAlphaNum 32) | b64enc }} -{{- $pPassword := (randAlphaNum 32) | b64enc }} -{{- $pUsername := (randAlphaNum 32) | b64enc }} +{{- $baPassword := (randAlphaNum 32) }} +{{- $baUsername := (randAlphaNum 32) }} +{{- $dbPassword := (randAlphaNum 32) }} +{{- $dbUsername := (randAlphaNum 32) }} -{{- $bSecretName := printf "%s-%s" (include "coms.fullname" .) "basicauth" }} -{{- $bSecret := (lookup "v1" "Secret" .Release.Namespace $bSecretName ) }} -{{- $kSecretName := printf "%s-%s" (include "coms.fullname" .) "keycloak" }} -{{- $kSecret := (lookup "v1" "Secret" .Release.Namespace $kSecretName ) }} -{{- $oSecretName := printf "%s-%s" (include "coms.fullname" .) "objectstorage" }} -{{- $oSecret := (lookup "v1" "Secret" .Release.Namespace $oSecretName ) }} -{{- $pSecretName := printf "%s-%s" (include "coms.fullname" .) "passphrase" }} -{{- $pSecret := (lookup "v1" "Secret" .Release.Namespace $pSecretName ) }} +{{- $baSecretName := printf "%s-%s" (include "coms.fullname" .) "basicauth" }} +{{- $baSecret := (lookup "v1" "Secret" .Release.Namespace $baSecretName ) }} +{{- $dbSecretName := printf "%s-%s" (include "coms.fullname" .) "passphrase" }} +{{- $dbSecret := (lookup "v1" "Secret" .Release.Namespace $dbSecretName ) }} +{{- $kcSecretName := printf "%s-%s" (include "coms.fullname" .) "keycloak" }} +{{- $kcSecret := (lookup "v1" "Secret" .Release.Namespace $kcSecretName ) }} +{{- $osSecretName := printf "%s-%s" (include "coms.fullname" .) "objectstorage" }} +{{- $osSecret := (lookup "v1" "Secret" .Release.Namespace $osSecretName ) }} -{{- if not $bSecret }} +{{- if not $baSecret }} --- apiVersion: v1 kind: Secret @@ -21,14 +21,14 @@ metadata: annotations: "helm.sh/resource-policy": keep {{- end }} - name: {{ $bSecretName }} + name: {{ $baSecretName }} labels: {{ include "coms.labels" . | nindent 4 }} type: kubernetes.io/basic-auth data: - password: {{ .Values.basicAuthSecretOverride.password | default $bPassword | quote }} - username: {{ .Values.basicAuthSecretOverride.username | default $bUsername | quote }} + password: {{ .Values.basicAuthSecretOverride.password | default $baPassword | b64enc | quote }} + username: {{ .Values.basicAuthSecretOverride.username | default $baUsername | b64enc | quote }} {{- end }} -{{- if not $pSecret }} +{{- if not $dbSecret }} --- apiVersion: v1 kind: Secret @@ -37,14 +37,14 @@ metadata: annotations: "helm.sh/resource-policy": keep {{- end }} - name: {{ $pSecretName }} + name: {{ $dbSecretName }} labels: {{ include "coms.labels" . | nindent 4 }} type: kubernetes.io/basic-auth data: - password: {{ .Values.dbSecretOverride.password | default $pPassword | quote }} - username: {{ .Values.dbSecretOverride.username | default $pUsername | quote }} + password: {{ .Values.dbSecretOverride.password | default $dbPassword | b64enc | quote }} + username: {{ .Values.dbSecretOverride.username | default $dbUsername | b64enc | quote }} {{- end }} -{{- if and (not $oSecret) (and .Values.objectStorageSecretOverride.password .Values.objectStorageSecretOverride.username) }} +{{- if and (not $kcSecret) (and .Values.keycloakSecretOverride.password .Values.keycloakSecretOverride.username) }} --- apiVersion: v1 kind: Secret @@ -53,14 +53,14 @@ metadata: annotations: "helm.sh/resource-policy": keep {{- end }} - name: {{ $oSecretName }} + name: {{ $kcSecretName }} labels: {{ include "coms.labels" . | nindent 4 }} type: kubernetes.io/basic-auth data: - password: {{ .Values.objectStorageSecretOverride.password | quote }} - username: {{ .Values.objectStorageSecretOverride.username | quote }} + password: {{ .Values.keycloakSecretOverride.password | b64enc | quote }} + username: {{ .Values.keycloakSecretOverride.username | b64enc | quote }} {{- end }} -{{- if and (not $kSecret) (and .Values.keycloakSecretOverride.password .Values.keycloakSecretOverride.username) }} +{{- if and (not $osSecret) (and .Values.objectStorageSecretOverride.password .Values.objectStorageSecretOverride.username) }} --- apiVersion: v1 kind: Secret @@ -69,10 +69,10 @@ metadata: annotations: "helm.sh/resource-policy": keep {{- end }} - name: {{ $kSecretName }} + name: {{ $osSecretName }} labels: {{ include "coms.labels" . | nindent 4 }} type: kubernetes.io/basic-auth data: - password: {{ .Values.keycloakSecretOverride.password | quote }} - username: {{ .Values.keycloakSecretOverride.username | quote }} + password: {{ .Values.objectStorageSecretOverride.password | b64enc | quote }} + username: {{ .Values.objectStorageSecretOverride.username | b64enc | quote }} {{- end }} diff --git a/charts/coms/values.yaml b/charts/coms/values.yaml index 013a254a..32df368d 100644 --- a/charts/coms/values.yaml +++ b/charts/coms/values.yaml @@ -128,7 +128,10 @@ config: # BASICAUTH_ENABLED: "true" # DB_ENABLED: "true" + # DB_HOST: ~ DB_PORT: "5432" + # DB_POOL_MIN: "2" + # DB_POOL_MAX: "10" # KC_ENABLED: "true" KC_IDENTITYKEY: ~