diff --git a/.github/environments/values.dev.yaml b/.github/environments/values.dev.yaml index faa53aa9..a77bf7c5 100644 --- a/.github/environments/values.dev.yaml +++ b/.github/environments/values.dev.yaml @@ -6,7 +6,7 @@ config: FRONTEND_CHES_ROADMAP_BCC: NRM.PermittingAndData@gov.bc.ca FRONTEND_CHES_SUBMISSION_CC: NRM.PermittingAndData@gov.bc.ca FRONTEND_COMS_APIPATH: https://coms-dev.api.gov.bc.ca/api/v1 - FRONTEND_COMS_BUCKETID: 1f9e1451-c130-4804-aeb0-b78b5b109c47 + FRONTEND_COMS_BUCKETID: 5aa446ca-23c5-4f3b-9300-d8623bc4d101 FRONTEND_GEOCODER_APIPATH: https://geocoder.api.gov.bc.ca FRONTEND_OIDC_AUTHORITY: https://dev.loginproxy.gov.bc.ca/auth/realms/standard FRONTEND_OIDC_CLIENTID: nr-permit-connect-navigator-service-5188 diff --git a/app/config/custom-environment-variables.json b/app/config/custom-environment-variables.json index b3082265..eb00b754 100644 --- a/app/config/custom-environment-variables.json +++ b/app/config/custom-environment-variables.json @@ -62,6 +62,13 @@ "env": "SERVER_ENV", "logFile": "SERVER_LOGFILE", "logLevel": "SERVER_LOGLEVEL", + "objectStorage": { + "accessKeyId": "OBJECTSTORAGE_ACCESSKEYID", + "bucket": "OBJECTSTORAGE_BUCKET", + "endpoint": "OBJECTSTORAGE_ENDPOINT", + "key": "OBJECTSTORAGE_KEY", + "secretAccessKey": "OBJECTSTORAGE_SECRETACCESSKEY" + }, "oidc": { "authority": "SERVER_OIDC_AUTHORITY", "clientId": "SERVER_OIDC_CLIENTID", diff --git a/app/src/controllers/roadmap.ts b/app/src/controllers/roadmap.ts index 8428d161..4ae7a261 100644 --- a/app/src/controllers/roadmap.ts +++ b/app/src/controllers/roadmap.ts @@ -18,29 +18,34 @@ const controller = { if (req.body.selectedFileIds && req.body.selectedFileIds.length) { const attachments: Array = []; - const comsObjects = await comsService.getObjects(req.headers, req.body.selectedFileIds); + if (req.currentContext?.bearerToken) { + const comsObjects = await comsService.getObjects(req.currentContext?.bearerToken, req.body.selectedFileIds); - // Attempt to get the requested documents from COMS - // If succesful it is converted to base64 encoding and added to the attachment list - const objectPromises = req.body.selectedFileIds.map(async (id) => { - const { status, headers, data } = await comsService.getObject(req.headers, id); + // Attempt to get the requested documents from COMS + // If succesful it is converted to base64 encoding and added to the attachment list + const objectPromises = req.body.selectedFileIds.map(async (id) => { + const { status, headers, data } = await comsService.getObject( + req.currentContext?.bearerToken as string, + id + ); - if (status === 200) { - const filename = comsObjects.find((x: { id: string }) => x.id === id)?.name; - if (filename) { - attachments.push({ - content: Buffer.from(data).toString('base64'), - contentType: headers['content-type'], - encoding: 'base64', - filename: filename - }); - } else { - throw new Error(`Unable to obtain filename for file ${id}`); + if (status === 200) { + const filename = comsObjects.find((x: { id: string }) => x.id === id)?.name; + if (filename) { + attachments.push({ + content: Buffer.from(data).toString('base64'), + contentType: headers['content-type'], + encoding: 'base64', + filename: filename + }); + } else { + throw new Error(`Unable to obtain filename for file ${id}`); + } } - } - }); + }); - await Promise.all(objectPromises); + await Promise.all(objectPromises); + } // All succesful so attachment list is added to payload req.body.emailData.attachments = attachments; diff --git a/app/src/interfaces/IExpress.ts b/app/src/interfaces/IExpress.ts index 5d839219..a849aee2 100644 --- a/app/src/interfaces/IExpress.ts +++ b/app/src/interfaces/IExpress.ts @@ -3,13 +3,17 @@ import * as core from 'express-serve-static-core'; import type { CurrentAuthorization } from '../types/CurrentAuthorization'; import type { CurrentContext } from '../types/CurrentContext'; +declare module 'express-serve-static-core' { + export interface Request { + currentAuthorization: CurrentAuthorization; + currentContext: CurrentContext; + } +} + interface Query extends core.Query {} interface Params extends core.ParamsDictionary {} - export interface Request

extends core.Request { - currentAuthorization?: CurrentAuthorization; - currentContext?: CurrentContext; params: P; query: Q; body: B; diff --git a/app/src/middleware/authentication.ts b/app/src/middleware/authentication.ts index 07e4cb6d..8138cfeb 100644 --- a/app/src/middleware/authentication.ts +++ b/app/src/middleware/authentication.ts @@ -55,6 +55,7 @@ export const currentContext = (initiative: Initiative) => { } if (isValid) { + currentContext.bearerToken = bearerToken; currentContext.tokenPayload = isValid as jwt.JwtPayload; const user = await userService.login(currentContext.tokenPayload); diff --git a/app/src/middleware/requireSomeGroup.ts b/app/src/middleware/requireSomeGroup.ts index d06bd254..908532d1 100644 --- a/app/src/middleware/requireSomeGroup.ts +++ b/app/src/middleware/requireSomeGroup.ts @@ -24,7 +24,7 @@ export const requireSomeGroup = async (req: Request, _res: Response, next: NextF // Auto assign all PROPONENT groups if user has none if (groups && groups.length === 0) { - await yarsService.assignGroup(sub, Initiative.HOUSING, GroupName.PROPONENT); + await yarsService.assignGroup(req.currentContext.bearerToken, sub, Initiative.HOUSING, GroupName.PROPONENT); groups = await yarsService.getSubjectGroups(sub); } diff --git a/app/src/services/coms.ts b/app/src/services/coms.ts index 7433f75c..da2667cb 100644 --- a/app/src/services/coms.ts +++ b/app/src/services/coms.ts @@ -1,8 +1,9 @@ import axios from 'axios'; import config from 'config'; +import { Action } from '../utils/enums/application'; + import type { AxiosInstance, AxiosRequestConfig } from 'axios'; -import type { IncomingHttpHeaders } from 'http'; /** * @function comsAxios @@ -22,16 +23,40 @@ function comsAxios(options: AxiosRequestConfig = {}): AxiosInstance { } const service = { + /** + * @function createBucket + * Creates a bucket record. Bucket should exist in S3. If the set of bucket, endpoint and key match + * an existing record, the user will be added to that existing bucket with the provided permissions + * instead of generating a new bucket record. + * This endpoint can be used to grant the current user permission to upload to a new or existing bucket. + * @param {string} bearerToken The bearer token of the authorized user + * @param {Action[]} permissions An array of permissions to grant the user + */ + async createBucket(bearerToken: string, permissions: Array) { + const { data } = await comsAxios({ + headers: { Authorization: `Bearer ${bearerToken}` } + }).put('/bucket', { + accessKeyId: config.get('server.objectStorage.accessKeyId'), + bucket: config.get('server.objectStorage.bucket'), + bucketName: 'PCNS', + endpoint: config.get('server.objectStorage.endpoint'), + secretAccessKey: config.get('server.objectStorage.secretAccessKey'), + key: config.get('server.objectStorage.key'), + permCodes: permissions + }); + return data; + }, + /** * @function getObject * Get an object - * @param {IncomingHttpHeaders} incomingHeaders The request headers + * @param {string} bearerToken The bearer token of the authorized user * @param {string} objectId The id for the object to get */ - async getObject(incomingHeaders: IncomingHttpHeaders, objectId: string) { + async getObject(bearerToken: string, objectId: string) { const { status, headers, data } = await comsAxios({ responseType: 'arraybuffer', - headers: { Authorization: incomingHeaders.authorization } + headers: { Authorization: `Bearer ${bearerToken}` } }).get(`/object/${objectId}`); return { status, headers, data }; }, @@ -39,11 +64,11 @@ const service = { /** * @function getObjects * Gets a list of objects - * @param {IncomingHttpHeaders} incomingHeaders The request headers + * @param {string} bearerToken The bearer token of the authorized user * @param {string[]} objectIds Array of object ids to get */ - async getObjects(incomingHeaders: IncomingHttpHeaders, objectIds: Array) { - const { data } = await comsAxios({ headers: { Authorization: incomingHeaders.authorization } }).get('/object', { + async getObjects(bearerToken: string, objectIds: Array) { + const { data } = await comsAxios({ headers: { Authorization: `Bearer ${bearerToken}` } }).get('/object', { params: { objectId: objectIds } }); diff --git a/app/src/services/yars.ts b/app/src/services/yars.ts index 16995d9d..41c8f48e 100644 --- a/app/src/services/yars.ts +++ b/app/src/services/yars.ts @@ -1,10 +1,21 @@ /* eslint-disable no-useless-catch */ +import { comsService } from '.'; import prisma from '../db/dataConnection'; -import { Initiative, GroupName } from '../utils/enums/application'; +import { Initiative, GroupName, Action } from '../utils/enums/application'; const service = { - assignGroup: async (sub: string, initiative: Initiative, group: GroupName) => { + /** + * @function assignGroup + * Assigns an identity to the given group + * Assigns permissions to COMS based on the given group + * @param {string | undefined} bearerToken The bearer token of the authorized user + * @param {string} identityId Identity ID of the authorized user + * @param {Initiative} initiative The initiative to associate with the group + * @param {GroupName} group The group to add the user to + * @returns {Promise<{identityId: string;roleId: number;}>} The result of running the create operation + */ + assignGroup: async (bearerToken: string | undefined, sub: string, initiative: Initiative, group: GroupName) => { try { const i = await prisma.initiative.findFirstOrThrow({ where: { @@ -26,6 +37,19 @@ const service = { } }); + const comsPermsMap = new Map>([ + [GroupName.PROPONENT, [Action.CREATE]], + [GroupName.NAVIGATOR, [Action.CREATE, Action.READ, Action.UPDATE, Action.DELETE]], + [GroupName.SUPERVISOR, [Action.CREATE, Action.READ, Action.UPDATE, Action.DELETE]], + [GroupName.ADMIN, [Action.CREATE, Action.READ, Action.UPDATE, Action.DELETE]], + [GroupName.DEVELOPER, [Action.CREATE, Action.READ, Action.UPDATE, Action.DELETE]] + ]); + + const comsPerms = comsPermsMap.get(group); + if (comsPerms && bearerToken) { + await comsService.createBucket(bearerToken, comsPerms); + } + return { identityId: result.sub, roleId: result.group_id }; } catch (e: unknown) { throw e; @@ -59,6 +83,15 @@ const service = { } }, + /** + * @function getGroupPolicyDetails + * Gets a list of group/role/policy/resource/action matching the given parameters + * @param {string} groupId Group ID to match on + * @param {Initiative} initiativeCode Initiative code to match on + * @param {string} resourceName Resource name to match on + * @param {string} actionName Action name to match on + * @returns The result of running the findMany operation + */ getGroupPolicyDetails: async ( groupId: number, initiativeCode: Initiative, @@ -89,6 +122,12 @@ const service = { } }, + /** + * @function getGroupPermissions + * Gets a list of resource/actions associated with the given groupId + * @param {number} groupId Group ID to search + * @returns The result of running the findMany operation + */ getGroupPermissions: async (groupId: number) => { try { const result = await prisma.group_role_policy_vw.findMany({ @@ -108,6 +147,12 @@ const service = { } }, + /** + * @function getPolicyAttributes + * Gets a list of attributes associated with the given policyId + * @param {number} policyId Policy ID to search + * @returns The result of running the findMany operation + */ getPolicyAttributes: async (policyId: number) => { try { const result = await prisma.policy_attribute.findMany({ diff --git a/app/src/types/CurrentContext.ts b/app/src/types/CurrentContext.ts index 3f6a3dfb..81d85586 100644 --- a/app/src/types/CurrentContext.ts +++ b/app/src/types/CurrentContext.ts @@ -4,6 +4,7 @@ import { AuthType, Initiative } from '../utils/enums/application'; export type CurrentContext = { authType?: AuthType; + bearerToken?: string; initiative?: Initiative; tokenPayload?: jwt.JwtPayload; userId?: string; diff --git a/app/tests/unit/controllers/roadmap.spec.ts b/app/tests/unit/controllers/roadmap.spec.ts index 25044a3a..d902bc10 100644 --- a/app/tests/unit/controllers/roadmap.spec.ts +++ b/app/tests/unit/controllers/roadmap.spec.ts @@ -22,7 +22,7 @@ afterEach(() => { jest.resetAllMocks(); }); -const CURRENT_CONTEXT = { authType: 'BEARER', tokenPayload: null, userId: 'abc-123' }; +const CURRENT_CONTEXT = { authType: 'BEARER', bearerToken: 'sometoken', tokenPayload: null, userId: 'abc-123' }; describe('send', () => { const next = jest.fn(); @@ -188,10 +188,59 @@ describe('send', () => { await roadmapController.send(req as any, res as any, next); expect(getObjectsSpy).toHaveBeenCalledTimes(1); - expect(getObjectsSpy).toHaveBeenNthCalledWith(1, req.headers, req.body.selectedFileIds); + expect(getObjectsSpy).toHaveBeenNthCalledWith(1, req.currentContext.bearerToken, req.body.selectedFileIds); expect(getObjectSpy).toHaveBeenCalledTimes(2); - expect(getObjectSpy).toHaveBeenNthCalledWith(1, req.headers, req.body.selectedFileIds[0]); - expect(getObjectSpy).toHaveBeenNthCalledWith(2, req.headers, req.body.selectedFileIds[1]); + expect(getObjectSpy).toHaveBeenNthCalledWith(1, req.currentContext.bearerToken, req.body.selectedFileIds[0]); + expect(getObjectSpy).toHaveBeenNthCalledWith(2, req.currentContext.bearerToken, req.body.selectedFileIds[1]); + expect(emailSpy).toHaveBeenCalledTimes(1); + expect(emailSpy).toHaveBeenCalledWith(req.body.emailData); + expect(res.status).toHaveBeenCalledWith(201); + expect(res.json).toHaveBeenCalledWith(emailResponse.data); + }); + + it('should not call COMS without a bearer token', async () => { + const req = { + body: { + activityId: '123-123', + selectedFileIds: ['123', '456'], + emailData: { + body: 'Some message text', + bodyType: 'text', + from: 'test@gov.bc.ca', + to: 'hello@gov.bc.ca', + subject: 'Unit tests', + attachments: [ + { + content: Buffer.from('foo').toString('base64'), + contentType: 'filetype', + encoding: 'base64', + filename: 'foo' + }, + { + content: Buffer.from('foo').toString('base64'), + contentType: 'filetype', + encoding: 'base64', + filename: 'bar' + } + ] + } + }, + currentContext: { ...CURRENT_CONTEXT, bearerToken: null }, + headers: {} + }; + + const emailResponse = { + data: 'foo', + status: 201 + }; + + emailSpy.mockResolvedValue(emailResponse); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + await roadmapController.send(req as any, res as any, next); + + expect(getObjectsSpy).toHaveBeenCalledTimes(0); + expect(getObjectSpy).toHaveBeenCalledTimes(0); expect(emailSpy).toHaveBeenCalledTimes(1); expect(emailSpy).toHaveBeenCalledWith(req.body.emailData); expect(res.status).toHaveBeenCalledWith(201); @@ -270,10 +319,10 @@ describe('send', () => { await roadmapController.send(req as any, res as any, next); expect(getObjectsSpy).toHaveBeenCalledTimes(1); - expect(getObjectsSpy).toHaveBeenNthCalledWith(1, req.headers, req.body.selectedFileIds); + expect(getObjectsSpy).toHaveBeenNthCalledWith(1, req.currentContext.bearerToken, req.body.selectedFileIds); expect(getObjectSpy).toHaveBeenCalledTimes(2); - expect(getObjectSpy).toHaveBeenNthCalledWith(1, req.headers, req.body.selectedFileIds[0]); - expect(getObjectSpy).toHaveBeenNthCalledWith(2, req.headers, req.body.selectedFileIds[1]); + expect(getObjectSpy).toHaveBeenNthCalledWith(1, req.currentContext.bearerToken, req.body.selectedFileIds[0]); + expect(getObjectSpy).toHaveBeenNthCalledWith(2, req.currentContext.bearerToken, req.body.selectedFileIds[1]); expect(emailSpy).toHaveBeenCalledTimes(1); expect(emailSpy).toHaveBeenCalledWith(req.body.emailData); expect(createNoteSpy).toHaveBeenCalledTimes(1); @@ -329,10 +378,10 @@ describe('send', () => { await roadmapController.send(req as any, res as any, next); expect(getObjectsSpy).toHaveBeenCalledTimes(1); - expect(getObjectsSpy).toHaveBeenNthCalledWith(1, req.headers, req.body.selectedFileIds); + expect(getObjectsSpy).toHaveBeenNthCalledWith(1, req.currentContext.bearerToken, req.body.selectedFileIds); expect(getObjectSpy).toHaveBeenCalledTimes(2); - expect(getObjectSpy).toHaveBeenNthCalledWith(1, req.headers, req.body.selectedFileIds[0]); - expect(getObjectSpy).toHaveBeenNthCalledWith(2, req.headers, req.body.selectedFileIds[1]); + expect(getObjectSpy).toHaveBeenNthCalledWith(1, req.currentContext.bearerToken, req.body.selectedFileIds[0]); + expect(getObjectSpy).toHaveBeenNthCalledWith(2, req.currentContext.bearerToken, req.body.selectedFileIds[1]); expect(emailSpy).toHaveBeenCalledTimes(0); expect(res.status).toHaveBeenCalledTimes(0); expect(next).toHaveBeenCalledTimes(1); @@ -389,10 +438,10 @@ describe('send', () => { await roadmapController.send(req as any, res as any, next); expect(getObjectsSpy).toHaveBeenCalledTimes(1); - expect(getObjectsSpy).toHaveBeenNthCalledWith(1, req.headers, req.body.selectedFileIds); + expect(getObjectsSpy).toHaveBeenNthCalledWith(1, req.currentContext.bearerToken, req.body.selectedFileIds); expect(getObjectSpy).toHaveBeenCalledTimes(2); - expect(getObjectSpy).toHaveBeenNthCalledWith(1, req.headers, req.body.selectedFileIds[0]); - expect(getObjectSpy).toHaveBeenNthCalledWith(2, req.headers, req.body.selectedFileIds[1]); + expect(getObjectSpy).toHaveBeenNthCalledWith(1, req.currentContext.bearerToken, req.body.selectedFileIds[0]); + expect(getObjectSpy).toHaveBeenNthCalledWith(2, req.currentContext.bearerToken, req.body.selectedFileIds[1]); expect(emailSpy).toHaveBeenCalledTimes(0); expect(res.status).toHaveBeenCalledTimes(0); expect(next).toHaveBeenCalledTimes(1); diff --git a/charts/pcns/Chart.yaml b/charts/pcns/Chart.yaml index 6f6aebb0..b82ee9be 100644 --- a/charts/pcns/Chart.yaml +++ b/charts/pcns/Chart.yaml @@ -3,7 +3,7 @@ name: nr-permitconnect-navigator-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.11 +version: 0.0.12 kubeVersion: ">= 1.13.0" description: PermitConnect Navigator Service # A chart can be either an 'application' or a 'library' chart. diff --git a/charts/pcns/README.md b/charts/pcns/README.md index 1ed62f7b..5e2d93f9 100644 --- a/charts/pcns/README.md +++ b/charts/pcns/README.md @@ -1,6 +1,6 @@ # nr-permitconnect-navigator-service -![Version: 0.0.11](https://img.shields.io/badge/Version-0.0.11-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.3.0](https://img.shields.io/badge/AppVersion-0.3.0-informational?style=flat-square) +![Version: 0.0.12](https://img.shields.io/badge/Version-0.0.12-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.3.0](https://img.shields.io/badge/AppVersion-0.3.0-informational?style=flat-square) PermitConnect Navigator Service @@ -35,7 +35,7 @@ Kubernetes: `>= 1.13.0` | autoscaling.targetCPUUtilizationPercentage | int | `80` | | | chesSecretOverride.password | string | `nil` | | | chesSecretOverride.username | string | `nil` | | -| config.configMap | object | `{"FRONTEND_APIPATH":"api/v1","FRONTEND_CHES_ROADMAP_BCC":null,"FRONTEND_CHES_SUBMISSION_CC":null,"FRONTEND_COMS_APIPATH":null,"FRONTEND_COMS_BUCKETID":null,"FRONTEND_GEOCODER_APIPATH":null,"FRONTEND_OIDC_AUTHORITY":null,"FRONTEND_OIDC_CLIENTID":null,"FRONTEND_OPENSTREETMAP_APIPATH":null,"FRONTEND_ORGBOOK_APIPATH":null,"SERVER_APIPATH":"/api/v1","SERVER_BODYLIMIT":"30mb","SERVER_CHEFS_APIPATH":null,"SERVER_CHES_APIPATH":null,"SERVER_CHES_TOKENURL":null,"SERVER_DB_HOST":null,"SERVER_DB_POOL_MAX":"10","SERVER_DB_POOL_MIN":"2","SERVER_DB_PORT":"5432","SERVER_ENV":null,"SERVER_LOGLEVEL":"http","SERVER_OIDC_AUTHORITY":null,"SERVER_OIDC_IDENTITYKEY":null,"SERVER_OIDC_PUBLICKEY":null,"SERVER_PORT":"8080","SERVER_SSO_APIPATH":null,"SERVER_SSO_INTEGRATION":null,"SERVER_SSO_TOKENURL":null}` | These values will be wholesale added to the configmap as is; refer to the pcns documentation for what each of these values mean and whether you need them defined. Ensure that all values are represented explicitly as strings, as non-string values will not translate over as expected into container environment variables. For configuration keys named `*_ENABLED`, either leave them commented/undefined, or set them to string value "true". | +| config.configMap | object | `{"FRONTEND_APIPATH":"api/v1","FRONTEND_CHES_ROADMAP_BCC":null,"FRONTEND_CHES_SUBMISSION_CC":null,"FRONTEND_COMS_APIPATH":null,"FRONTEND_COMS_BUCKETID":null,"FRONTEND_GEOCODER_APIPATH":null,"FRONTEND_OIDC_AUTHORITY":null,"FRONTEND_OIDC_CLIENTID":null,"FRONTEND_OPENSTREETMAP_APIPATH":null,"FRONTEND_ORGBOOK_APIPATH":null,"OBJECTSTORAGE_BUCKET":null,"OBJECTSTORAGE_ENDPOINT":null,"OBJECTSTORAGE_KEY":null,"SERVER_APIPATH":"/api/v1","SERVER_BODYLIMIT":"30mb","SERVER_CHEFS_APIPATH":null,"SERVER_CHES_APIPATH":null,"SERVER_CHES_TOKENURL":null,"SERVER_DB_HOST":null,"SERVER_DB_POOL_MAX":"10","SERVER_DB_POOL_MIN":"2","SERVER_DB_PORT":"5432","SERVER_ENV":null,"SERVER_LOGLEVEL":"http","SERVER_OIDC_AUTHORITY":null,"SERVER_OIDC_IDENTITYKEY":null,"SERVER_OIDC_PUBLICKEY":null,"SERVER_PORT":"8080","SERVER_SSO_APIPATH":null,"SERVER_SSO_INTEGRATION":null,"SERVER_SSO_TOKENURL":null}` | These values will be wholesale added to the configmap as is; refer to the pcns documentation for what each of these values mean and whether you need them defined. Ensure that all values are represented explicitly as strings, as non-string values will not translate over as expected into container environment variables. For configuration keys named `*_ENABLED`, either leave them commented/undefined, or set them to string value "true". | | config.enabled | bool | `false` | Set to true if you want to let Helm manage and overwrite your configmaps. | | config.releaseScoped | bool | `false` | This should be set to true if and only if you require configmaps and secrets to be release scoped. In the event you want all instances in the same namespace to share a similar configuration, this should be set to false | | dbSecretOverride.password | string | `nil` | | @@ -52,6 +52,8 @@ Kubernetes: `>= 1.13.0` | imagePullSecrets | list | `[]` | Specify docker-registry secret names as an array | | nameOverride | string | `nil` | String to partially override fullname | | networkPolicy.enabled | bool | `true` | Specifies whether a network policy should be created | +| objectStorageSecretOverride.password | string | `nil` | | +| objectStorageSecretOverride.username | string | `nil` | | | oidcSecretOverride.password | string | `nil` | | | oidcSecretOverride.username | string | `nil` | | | patroni.enabled | bool | `false` | | diff --git a/charts/pcns/templates/deploymentconfig.yaml b/charts/pcns/templates/deploymentconfig.yaml index 7a8b9ba7..b5342d86 100644 --- a/charts/pcns/templates/deploymentconfig.yaml +++ b/charts/pcns/templates/deploymentconfig.yaml @@ -150,6 +150,16 @@ spec: secretKeyRef: key: app-db-password name: {{ $dbSecretName }} + - name: OBJECTSTORAGE_ACCESSKEYID + valueFrom: + secretKeyRef: + key: username + name: {{ include "pcns.configname" . }}-objectstorage + - name: OBJECTSTORAGE_SECRETACCESSKEY + valueFrom: + secretKeyRef: + key: password + name: {{ include "pcns.configname" . }}-objectstorage - name: SERVER_OIDC_CLIENTID valueFrom: secretKeyRef: diff --git a/charts/pcns/templates/secret.yaml b/charts/pcns/templates/secret.yaml index b94bebd3..186a82ed 100644 --- a/charts/pcns/templates/secret.yaml +++ b/charts/pcns/templates/secret.yaml @@ -21,6 +21,8 @@ {{- $chesSecret := (lookup "v1" "Secret" .Release.Namespace $chesSecretName ) }} {{- $oSecretName := printf "%s-%s" (include "pcns.configname" .) "oidc" }} {{- $oSecret := (lookup "v1" "Secret" .Release.Namespace $oSecretName ) }} +{{- $osSecretName := printf "%s-%s" (include "pcns.configname" .) "objectstorage" }} +{{- $osSecret := (lookup "v1" "Secret" .Release.Namespace $osSecretName ) }} {{- $ssoSecretName := printf "%s-%s" (include "pcns.configname" .) "sso" }} {{- $ssoSecret := (lookup "v1" "Secret" .Release.Namespace $ssoSecretName ) }} @@ -90,6 +92,22 @@ data: password: {{ .Values.chesSecretOverride.password | default $chesPassword | b64enc | quote }} username: {{ .Values.chesSecretOverride.username | default $chesUsername | b64enc | quote }} {{- end }} +{{- if not $osSecret }} +--- +apiVersion: v1 +kind: Secret +metadata: + {{- if not .Values.config.releaseScoped }} + annotations: + "helm.sh/resource-policy": keep + {{- end }} + name: {{ $osSecretName }} + labels: {{ include "coms.labels" . | nindent 4 }} +type: kubernetes.io/basic-auth +data: + password: {{ .Values.objectStorageSecretOverride.password | b64enc | quote }} + username: {{ .Values.objectStorageSecretOverride.username | b64enc | quote }} +{{- end }} {{- if not $oSecret }} --- apiVersion: v1 diff --git a/charts/pcns/values.yaml b/charts/pcns/values.yaml index e9c4024b..b506bdb8 100644 --- a/charts/pcns/values.yaml +++ b/charts/pcns/values.yaml @@ -160,6 +160,10 @@ config: # SERVER_LOGFILE: ~ SERVER_LOGLEVEL: http + OBJECTSTORAGE_BUCKET: ~ + OBJECTSTORAGE_ENDPOINT: ~ + OBJECTSTORAGE_KEY: ~ + SERVER_OIDC_AUTHORITY: ~ SERVER_OIDC_IDENTITYKEY: ~ SERVER_OIDC_PUBLICKEY: ~ @@ -183,6 +187,9 @@ form2SecretOverride: chesSecretOverride: username: ~ password: ~ +objectStorageSecretOverride: + username: ~ + password: ~ oidcSecretOverride: username: ~ password: ~