diff --git a/.env.dev.example.env b/.env.dev.example.env index 7a9c36e60a..85c575906b 100644 --- a/.env.dev.example.env +++ b/.env.dev.example.env @@ -5,3 +5,4 @@ DOMIFA_ENV_ID=dev POSTGRES_USERNAME=domifa_user POSTGRES_PASSWORD=xxxxxxxxxxxxxxxxxxx POSTGRES_DATABASE=domifa_dev +POSTGRES_SSL=false \ No newline at end of file diff --git a/.kontinuous/config.yaml b/.kontinuous/config.yaml index f78f560f22..d3d7e1e51a 100644 --- a/.kontinuous/config.yaml +++ b/.kontinuous/config.yaml @@ -2,6 +2,8 @@ projectName: domifa dependencies: fabrique: import: socialgouv/kontinuous/plugins/fabrique + extends: + - name: buildkit-service dependencies: contrib: preDeploy: diff --git a/.kontinuous/env/dev/templates/backend.configmap.yaml b/.kontinuous/env/dev/templates/backend.configmap.yaml index d2c95b5569..0e04ee9421 100644 --- a/.kontinuous/env/dev/templates/backend.configmap.yaml +++ b/.kontinuous/env/dev/templates/backend.configmap.yaml @@ -12,6 +12,7 @@ data: DOMIFA_EMAILS_ENABLE: "true" DOMIFA_SMS_ENABLED: "false" POSTGRES_LOGGING: "schema,migration" + POSTGRES_SSL: "true" DOMIFA_FRONTEND_META_ROBOTS: noindex,nofollow DOMIFA_SENTRY_ENABLED: "true" DOMIFA_LOG_HTTP_REQUESTS: "true" diff --git a/.kontinuous/env/dev/values.yaml b/.kontinuous/env/dev/values.yaml index f25b2c238b..9e5d251c3a 100644 --- a/.kontinuous/env/dev/values.yaml +++ b/.kontinuous/env/dev/values.yaml @@ -1,3 +1,13 @@ +global: + pgSecretName: pg-app + +pg: + # this force ce PG cluster to be destroyed on redeploys + ~preDeploy.cleaner: + match: + kind: Cluster + value: true + jobs: runs: build-backend: @@ -7,25 +17,14 @@ jobs: DOMIFA_PORTAIL_ADMINS_URL: https://admin-{{ .Values.global.host }}/ DOMIFA_PORTAIL_USAGERS_URL: https://mon-{{ .Values.global.host }}/ DOMIFA_FRONTEND_URL: https://{{ .Values.global.host }}/ - - drop-db: - use: drop-db - with: - pgAdminUserSecretRefName: azure-pg-admin-user-devflex - create-db: - ~needs: [drop-db] - use: create-db - with: - pgAdminUserSecretRefName: azure-pg-admin-user-devflex - useAzureFlex: "true" seed: - ~needs: [backend] + ~needs: [backend] # need backend to run migrations use: seed-db with: seedPath: _scripts/db/dumps/domifa_test.postgres.truncate-restore-data-only.sql backend: - ~needs: [create-db, build-backend] + ~needs: [build-backend, pg] volumes: - name: files emptyDir: {} @@ -34,4 +33,4 @@ backend: name: files backend-cron: - ~needs: [create-db, build-backend] + ~needs: [backend] diff --git a/.kontinuous/env/preprod/templates/backend.configmap.yaml b/.kontinuous/env/preprod/templates/backend.configmap.yaml index 764817c6aa..9793b2c0ef 100644 --- a/.kontinuous/env/preprod/templates/backend.configmap.yaml +++ b/.kontinuous/env/preprod/templates/backend.configmap.yaml @@ -11,6 +11,7 @@ data: # emails redirigés vers l'adresse configurée pour DOMIFA_EMAIL_ADDRESS_REDIRECT_ALL_TO DOMIFA_EMAILS_ENABLE: "true" DOMIFA_SMS_ENABLED: "true" + POSTGRES_SSL: "true" # 50 connexions en tout à partager entre la preprod + les environnements de dev : # https://docs.microsoft.com/fr-fr/azure/postgresql/concepts-limits POSTGRES_POOL_MAX_CONNEXIONS: "50" diff --git a/.kontinuous/env/preprod/values.yaml b/.kontinuous/env/preprod/values.yaml index 05072af0a1..222eff4ab6 100644 --- a/.kontinuous/env/preprod/values.yaml +++ b/.kontinuous/env/preprod/values.yaml @@ -1,10 +1,17 @@ +global: + pgSecretName: pg-app + +pg-metabase: + ~chart: pg + backend: host: "api-{{ .Values.global.host }}" + ~needs: [build-backend, pg] addVolumes: - files envFrom: - secretRef: - name: pg-user-devflex + name: pg-app - secretRef: name: backend-sealed-secret - configMapRef: @@ -15,9 +22,10 @@ backend: name: domifa-encryption-key backend-cron: + ~needs: [backend] envFrom: - secretRef: - name: pg-user-devflex + name: pg-app - secretRef: name: backend-sealed-secret - configMapRef: @@ -34,11 +42,13 @@ portail-usagers: metabase: enabled: true + ~chart: metabase + ~needs: [pg-metabase] ingress: enabled: false envFrom: - secretRef: - name: metabase + name: pg-metabase-app oauth2-proxy: enabled: true diff --git a/.kontinuous/env/prod/templates/backend.configmap.yaml b/.kontinuous/env/prod/templates/backend.configmap.yaml index 7ce06b74a5..2919bff92d 100644 --- a/.kontinuous/env/prod/templates/backend.configmap.yaml +++ b/.kontinuous/env/prod/templates/backend.configmap.yaml @@ -10,6 +10,7 @@ data: DOMIFA_PRINT_CONFIG: "false" DOMIFA_EMAILS_ENABLE: "true" DOMIFA_SMS_ENABLED: "true" + POSTGRES_SSL: "true" # 50 connexions max : https://docs.microsoft.com/fr-fr/azure/postgresql/concepts-limits POSTGRES_POOL_MAX_CONNEXIONS: "100" DOMIFA_FRONTEND_META_ROBOTS: index,follow diff --git a/.kontinuous/env/prod/values.yaml b/.kontinuous/env/prod/values.yaml index 9ffc106152..15bd2cccd8 100644 --- a/.kontinuous/env/prod/values.yaml +++ b/.kontinuous/env/prod/values.yaml @@ -26,6 +26,12 @@ jobs: PRODUCTION: "true" DOMIFA_FRONTEND_META_ROBOTS: index,follow +pg: + ~chart: pg + cnpg-cluster: + persistence: + size: "50Gi" + backend-cron: replicas: 1 addVolumes: diff --git a/.kontinuous/values.yaml b/.kontinuous/values.yaml index 36d7c19ffe..7dd5d396db 100644 --- a/.kontinuous/values.yaml +++ b/.kontinuous/values.yaml @@ -1,3 +1,6 @@ +pg: + ~chart: pg + backend: ~chart: app ~needs: [build-backend] @@ -221,10 +224,3 @@ jobs: DOMIFA_BACKEND_URL: "https://api-{{ .Values.global.host }}/" DOMIFA_SENTRY_DSN_PORTAIL: "https://904877ea9ec4454aa1be7b629a6ea340@sentry.fabrique.social.gouv.fr/58" DOMIFA_FRONTEND_META_ROBOTS: noindex,nofollow - -deactivate: - jobs-deactivate: - runs: - deactivate: - with: - db: true diff --git a/docker-compose.local.yml b/docker-compose.local.yml index afdf30697b..52c88055e8 100644 --- a/docker-compose.local.yml +++ b/docker-compose.local.yml @@ -23,6 +23,7 @@ services: POSTGRES_DB: ${POSTGRES_DATABASE} POSTGRES_USER: ${POSTGRES_USERNAME} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + POSTGRES_SSL: "false" env_file: - ./.env healthcheck: diff --git a/docker-compose.tests.yml b/docker-compose.tests.yml index dbfefe47f1..bc2820dc0b 100644 --- a/docker-compose.tests.yml +++ b/docker-compose.tests.yml @@ -14,6 +14,7 @@ services: POSTGRES_DB: domifa_test POSTGRES_USER: domifa_user POSTGRES_PASSWORD: xxxxxxxxxxxxxxxxxxx + POSTGRES_SSL: "false" env_file: ./.env.dev.example.env healthcheck: retries: 5 diff --git a/packages/backend/.env.backend.dev.example.env b/packages/backend/.env.backend.dev.example.env index fa4239ba25..8fd6817d4f 100644 --- a/packages/backend/.env.backend.dev.example.env +++ b/packages/backend/.env.backend.dev.example.env @@ -9,6 +9,7 @@ DOMIFA_ENV_PRESET=local-dev.preset.env POSTGRES_USERNAME=domifa_user POSTGRES_PASSWORD=xxxxxxxxxxxxxxxxxxx POSTGRES_DATABASE=domifa_dev +POSTGRES_SSL=false # POSTGRES_LOGGING=warn # POSTGRES_LOGGING=query,schema,migration diff --git a/packages/backend/.env.backend.test.local.example.env b/packages/backend/.env.backend.test.local.example.env index 8dcece5994..279620ddc2 100644 --- a/packages/backend/.env.backend.test.local.example.env +++ b/packages/backend/.env.backend.test.local.example.env @@ -7,6 +7,7 @@ DOMIFA_ENV_PRESET=local-test.preset.env POSTGRES_USERNAME=domifa_user POSTGRES_PASSWORD=xxxxxxxxxxxxxxxxxxx POSTGRES_DATABASE=domifa_test +POSTGRES_SSL=false # JWT SECRET: DOMIFA_SECURITY_JWT_SECRET=9Ibl1P3XxNJOqaWTnvBpCVw8o1kFoSwiUwL8NETPfMMZY0f2BG0tgZNdTbYRwLfwRjfaqaHISvOqhQL7nGpmES73V0vgR3tUQeyvnI8gsKTFFJJPYqLIbBCLiXT8LKx5Q3tJirYI0zM4Joby2SkYv9QxqwaMKZGxYjJrU5WHTmUnk6c4GL6w1rk5sI diff --git a/packages/backend/src/config/domifaConfig.service.spec.ts b/packages/backend/src/config/domifaConfig.service.spec.ts index 601b6d39cb..bd072a0707 100644 --- a/packages/backend/src/config/domifaConfig.service.spec.ts +++ b/packages/backend/src/config/domifaConfig.service.spec.ts @@ -8,6 +8,7 @@ describe("loadConfig", () => { POSTGRES_USERNAME: "value POSTGRES_USERNAME", POSTGRES_PASSWORD: "value POSTGRES_PASSWORD", POSTGRES_DATABASE: "value POSTGRES_DATABASE", + POSTGRES_SSL: false, DOMIFA_SECURITY_JWT_SECRET: "******************", }; const env = loadEnvWithPreset({ defaultEnv }); @@ -28,6 +29,7 @@ describe("loadConfig", () => { expect(config.postgres.username).toEqual(env.POSTGRES_USERNAME); expect(config.postgres.password).toEqual(env.POSTGRES_PASSWORD); expect(config.postgres.database).toEqual(env.POSTGRES_DATABASE); + expect(config.postgres.ssl).toEqual(env.POSTGRES_SSL); expect(config.upload.basePath).toBeDefined(); @@ -43,6 +45,7 @@ describe("loadConfig", () => { POSTGRES_USERNAME: "value POSTGRES_USERNAME", POSTGRES_PASSWORD: "value POSTGRES_PASSWORD", POSTGRES_DATABASE: "value POSTGRES_DATABASE", + POSTGRES_SSL: false, DOMIFA_SECURITY_JWT_SECRET: "******************", }; const env = loadEnvWithPreset({ defaultEnv }); @@ -61,6 +64,7 @@ describe("loadConfig", () => { expect(config.postgres.username).toEqual(env.POSTGRES_USERNAME); expect(config.postgres.password).toEqual(env.POSTGRES_PASSWORD); expect(config.postgres.database).toEqual(env.POSTGRES_DATABASE); + expect(config.postgres.ssl).toEqual(env.POSTGRES_SSL); expect(config.upload.basePath).toBeDefined(); @@ -80,6 +84,7 @@ describe("loadConfig", () => { POSTGRES_USERNAME: "value POSTGRES_USERNAME", POSTGRES_PASSWORD: "value POSTGRES_PASSWORD", POSTGRES_DATABASE: "value POSTGRES_DATABASE", + POSTGRES_SSL: false, DOMIFA_SECURITY_JWT_SECRET: "******************", DOMIFA_FRONTEND_URL: "https://domifa.xxx", DOMIFA_PORTAIL_USAGERS_URL: "https://mon-domifa.xxx", @@ -108,6 +113,7 @@ describe("loadConfig", () => { expect(config.postgres.username).toEqual(env.POSTGRES_USERNAME); expect(config.postgres.password).toEqual(env.POSTGRES_PASSWORD); expect(config.postgres.database).toEqual(env.POSTGRES_DATABASE); + expect(config.postgres.ssl).toEqual(env.POSTGRES_SSL); expect(config.upload.basePath).toBeDefined(); diff --git a/packages/backend/src/config/domifaConfig.service.ts b/packages/backend/src/config/domifaConfig.service.ts index b155ed727f..2dd6998871 100644 --- a/packages/backend/src/config/domifaConfig.service.ts +++ b/packages/backend/src/config/domifaConfig.service.ts @@ -133,6 +133,10 @@ export function loadConfig(x: Partial): DomifaConfig { username: configParser.parseString(x, "POSTGRES_USERNAME"), password: configParser.parseString(x, "POSTGRES_PASSWORD"), database: configParser.parseString(x, "POSTGRES_DATABASE"), + ssl: configParser.parseBoolean(x, "POSTGRES_SSL", { + required: false, + defaultValue: false, + }), logging: configTypeOrmLoggerParser.getTypeormLoggerOptions( x, "POSTGRES_LOGGING" diff --git a/packages/backend/src/config/model/DomifaConfigPostgres.type.ts b/packages/backend/src/config/model/DomifaConfigPostgres.type.ts index 3e4df85e3f..b6351676be 100644 --- a/packages/backend/src/config/model/DomifaConfigPostgres.type.ts +++ b/packages/backend/src/config/model/DomifaConfigPostgres.type.ts @@ -6,6 +6,7 @@ export type DomifaConfigPostgres = { username: string; // POSTGRES_USERNAME password: string; // POSTGRES_PASSWORD database: string; // POSTGRES_DATABASE + ssl: boolean; // POSTGRES_SSL logging: LoggerOptions; // POSTGRES_LOGGING poolMaxConnections: number; // POSTGRES_POOL_MAX_CONNEXIONS }; diff --git a/packages/backend/src/config/model/DomifaEnv.type.ts b/packages/backend/src/config/model/DomifaEnv.type.ts index 69d1db2f7a..06a4eeaba7 100644 --- a/packages/backend/src/config/model/DomifaEnv.type.ts +++ b/packages/backend/src/config/model/DomifaEnv.type.ts @@ -33,6 +33,7 @@ export type DomifaEnv = { POSTGRES_USERNAME: string; POSTGRES_PASSWORD: string; POSTGRES_DATABASE: string; + POSTGRES_SSL: boolean; POSTGRES_LOGGING: string; POSTGRES_POOL_MAX_CONNEXIONS: string; DOMIFA_TYPEORM_RUN_ON_STARTUP: string; diff --git a/packages/backend/src/database/services/_postgres/PG_CONNECT_OPTIONS.const.ts b/packages/backend/src/database/services/_postgres/PG_CONNECT_OPTIONS.const.ts index 2ddbd63333..405f6cc70d 100644 --- a/packages/backend/src/database/services/_postgres/PG_CONNECT_OPTIONS.const.ts +++ b/packages/backend/src/database/services/_postgres/PG_CONNECT_OPTIONS.const.ts @@ -42,6 +42,11 @@ export const PG_CONNECT_OPTIONS: PostgresConnectionOptions = { username: domifaConfig().postgres.username, password: domifaConfig().postgres.password, database: domifaConfig().postgres.database, + ssl: domifaConfig().postgres.ssl + ? { + rejectUnauthorized: false, + } + : false, logger: new CustomTypeOrmLogger( domifaConfig().envId !== "test" ? domifaConfig().logger.logSqlRequests