From 8aec41a36ee897aad0057e6817a9433a545fd18d Mon Sep 17 00:00:00 2001 From: Andrii Hrachov <78734704+andriihrachov@users.noreply.github.com> Date: Mon, 11 Nov 2024 14:26:30 +0100 Subject: [PATCH] feat: redis tls support (#5884) Co-authored-by: Laurin Quast --- .changeset/early-otters-help.md | 5 +++++ docs/DEVELOPMENT.md | 17 +++++++++++++++++ packages/libraries/core/src/version.ts | 2 +- .../api/src/modules/shared/providers/redis.ts | 5 ++++- packages/services/emails/README.md | 1 + packages/services/emails/src/environment.ts | 2 ++ packages/services/emails/src/index.ts | 1 + packages/services/emails/src/scheduler.ts | 2 ++ packages/services/schema/README.md | 1 + packages/services/schema/src/environment.ts | 2 ++ packages/services/schema/src/index.ts | 1 + packages/services/server/README.md | 1 + packages/services/server/src/environment.ts | 2 ++ packages/services/tokens/README.md | 1 + packages/services/tokens/src/environment.ts | 2 ++ packages/services/tokens/src/index.ts | 1 + packages/services/webhooks/README.md | 1 + packages/services/webhooks/src/environment.ts | 2 ++ packages/services/webhooks/src/index.ts | 1 + packages/services/webhooks/src/scheduler.ts | 1 + packages/services/webhooks/src/types.ts | 1 + 21 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 .changeset/early-otters-help.md diff --git a/.changeset/early-otters-help.md b/.changeset/early-otters-help.md new file mode 100644 index 000000000..662132950 --- /dev/null +++ b/.changeset/early-otters-help.md @@ -0,0 +1,5 @@ +--- +'hive': minor +--- + +Add `REDIS_TLS_ENABLED` environment variable for enabling and disabling Redis TLS for `emails`, `schema`, `tokens`, `webhooks` and `server` services. diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 1a0060271..1e12339c3 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -22,6 +22,23 @@ ENVIRONMENT=local - Run `pnpm i` at the root to install all the dependencies and run the hooks - Run `pnpm local:setup` to run Docker compose dependencies, create databases and migrate database + +Solving permission problems on this step: + +```bash +export UID=$(id -u) +export GID=$(id -g) +``` + +Add "user" field to docker-compose.dev.yml + +``` + clickhouse: + user: '${UID}:${GID}' + db: + user: '${UID}:${GID}' +``` + - Run `pnpm generate` to generate the typings from the graphql files (use `pnpm graphql:generate` if you only need to run GraphQL Codegen) - Run `pnpm build` to build all services diff --git a/packages/libraries/core/src/version.ts b/packages/libraries/core/src/version.ts index 3cd94dc7d..21ea39227 100644 --- a/packages/libraries/core/src/version.ts +++ b/packages/libraries/core/src/version.ts @@ -1 +1 @@ -export const version = '0.8.0'; +export const version = '0.8.2'; diff --git a/packages/services/api/src/modules/shared/providers/redis.ts b/packages/services/api/src/modules/shared/providers/redis.ts index 3e0113b7b..2604fd49d 100644 --- a/packages/services/api/src/modules/shared/providers/redis.ts +++ b/packages/services/api/src/modules/shared/providers/redis.ts @@ -5,7 +5,9 @@ import { Logger } from './logger'; export type { RedisInstance as Redis }; -export type RedisConfig = Required>; +export type RedisConfig = Required> & { + tlsEnabled: boolean; +}; export const REDIS_INSTANCE = new InjectionToken('REDIS_INSTANCE'); @@ -24,6 +26,7 @@ export function createRedisClient(label: string, config: RedisConfig, logger: Lo db: 0, maxRetriesPerRequest: null, enableReadyCheck: false, + tls: config.tlsEnabled ? {} : undefined, }); redis.on('error', err => { diff --git a/packages/services/emails/README.md b/packages/services/emails/README.md index 167ac37d4..fed39c6e2 100644 --- a/packages/services/emails/README.md +++ b/packages/services/emails/README.md @@ -12,6 +12,7 @@ Service for sending Hive Emails. | `REDIS_HOST` | **Yes** | The host of your redis instance. | `"127.0.0.1"` | | `REDIS_PORT` | **Yes** | The port of your redis instance. | `6379` | | `REDIS_PASSWORD` | **Yes** | The password of your redis instance. | `"apollorocks"` | +| `REDIS_TLS_ENABLED` | **No** | Enable TLS for redis connection (rediss://). | `"0"` | | `EMAIL_FROM` | **Yes** | The email address used for sending emails | `kamil@graphql-hive.com` | | `EMAIL_PROVIDER` | **Yes** | The email provider that should be used for sending emails. | `smtp` or `postmark` or `mock` | | `EMAIL_PROVIDER_SMTP_PROTOCOL` | No (**Yes** if `EMAIL_PROVIDER` is set to `smtp`) | The protocol used for the smtp server | `smtp` or `smtps` | diff --git a/packages/services/emails/src/environment.ts b/packages/services/emails/src/environment.ts index 388dba437..0397751b8 100644 --- a/packages/services/emails/src/environment.ts +++ b/packages/services/emails/src/environment.ts @@ -40,6 +40,7 @@ const RedisModel = zod.object({ REDIS_HOST: zod.string(), REDIS_PORT: NumberFromString, REDIS_PASSWORD: emptyString(zod.string().optional()), + REDIS_TLS_ENABLED: emptyString(zod.union([zod.literal('1'), zod.literal('0')]).optional()), }); const PostmarkEmailModel = zod.object({ @@ -193,6 +194,7 @@ export const env = { host: redis.REDIS_HOST, port: redis.REDIS_PORT, password: redis.REDIS_PASSWORD ?? '', + tlsEnabled: redis.REDIS_TLS_ENABLED === '1', }, email: { provider: emailProviderConfig, diff --git a/packages/services/emails/src/index.ts b/packages/services/emails/src/index.ts index e43c0688d..caceb5650 100644 --- a/packages/services/emails/src/index.ts +++ b/packages/services/emails/src/index.ts @@ -66,6 +66,7 @@ async function main() { host: env.redis.host, port: env.redis.port, password: env.redis.password, + tlsEnabled: env.redis.tlsEnabled, }, queueName: 'emails', emailProvider, diff --git a/packages/services/emails/src/scheduler.ts b/packages/services/emails/src/scheduler.ts index 2d73939f6..4d9dc58a3 100644 --- a/packages/services/emails/src/scheduler.ts +++ b/packages/services/emails/src/scheduler.ts @@ -18,6 +18,7 @@ export function createScheduler(config: { host: string; port: number; password: string; + tlsEnabled: boolean; }; queueName: string; emailProvider: EmailProvider; @@ -126,6 +127,7 @@ export function createScheduler(config: { db: 0, maxRetriesPerRequest: null, enableReadyCheck: false, + tls: config.redis.tlsEnabled ? {} : undefined, }); redisConnection.on('error', err => { diff --git a/packages/services/schema/README.md b/packages/services/schema/README.md index bb0ae99ef..846c2b42b 100644 --- a/packages/services/schema/README.md +++ b/packages/services/schema/README.md @@ -11,6 +11,7 @@ of subschemas. | `REDIS_HOST` | **Yes** | The host of your redis instance. | `"127.0.0.1"` | | `REDIS_PORT` | **Yes** | The port of your redis instance. | `6379` | | `REDIS_PASSWORD` | **Yes** | The password of your redis instance. | `"apollorocks"` | +| `REDIS_TLS_ENABLED` | **No** | Enable TLS for redis connection (rediss://). | `"0"` | | `ENCRYPTION_SECRET` | **Yes** | Secret for encrypting stuff. | `8ebe95cg21c1fee355e9fa32c8c33141` | | `ENVIRONMENT` | No | The environment of your Hive app. (**Note:** This will be used for Sentry reporting.) | `staging` | | `BODY_LIMIT` | No | Maximum payload size in bytes. Defaults to 11 MB. | `11000000` | diff --git a/packages/services/schema/src/environment.ts b/packages/services/schema/src/environment.ts index 4008606bb..2a36b167b 100644 --- a/packages/services/schema/src/environment.ts +++ b/packages/services/schema/src/environment.ts @@ -59,6 +59,7 @@ const RedisModel = zod.object({ REDIS_HOST: zod.string(), REDIS_PORT: NumberFromString(), REDIS_PASSWORD: emptyString(zod.string().optional()), + REDIS_TLS_ENABLED: emptyString(zod.union([zod.literal('1'), zod.literal('0')]).optional()), }); const PrometheusModel = zod.object({ @@ -151,6 +152,7 @@ export const env = { host: redis.REDIS_HOST, port: redis.REDIS_PORT, password: redis.REDIS_PASSWORD ?? '', + tlsEnabled: redis.REDIS_TLS_ENABLED === '1', }, sentry: sentry.SENTRY === '1' ? { dsn: sentry.SENTRY_DSN } : null, log: { diff --git a/packages/services/schema/src/index.ts b/packages/services/schema/src/index.ts index 2d6444913..4a970acf1 100644 --- a/packages/services/schema/src/index.ts +++ b/packages/services/schema/src/index.ts @@ -98,6 +98,7 @@ async function main() { db: 0, maxRetriesPerRequest: null, enableReadyCheck: false, + tls: env.redis.tlsEnabled ? {} : undefined, }); try { diff --git a/packages/services/server/README.md b/packages/services/server/README.md index f1aab290e..74b0e978f 100644 --- a/packages/services/server/README.md +++ b/packages/services/server/README.md @@ -31,6 +31,7 @@ The GraphQL API for GraphQL Hive. | `REDIS_HOST` | **Yes** | The host of your redis instance. | `"127.0.0.1"` | | `REDIS_PORT` | **Yes** | The port of your redis instance. | `6379` | | `REDIS_PASSWORD` | **Yes** | The password of your redis instance. | `"apollorocks"` | +| `REDIS_TLS_ENABLED` | **No** | Enable TLS for redis connection (rediss://). | `"0"` | | `S3_ENDPOINT` | **Yes** | The S3 endpoint. | `http://localhost:9000` | | `S3_ACCESS_KEY_ID` | **Yes** | The S3 access key id. | `minioadmin` | | `S3_SECRET_ACCESS_KEY` | **Yes** | The S3 secret access key. | `minioadmin` | diff --git a/packages/services/server/src/environment.ts b/packages/services/server/src/environment.ts index fae24781d..986ce944e 100644 --- a/packages/services/server/src/environment.ts +++ b/packages/services/server/src/environment.ts @@ -92,6 +92,7 @@ const RedisModel = zod.object({ REDIS_HOST: zod.string(), REDIS_PORT: NumberFromString, REDIS_PASSWORD: emptyString(zod.string().optional()), + REDIS_TLS_ENABLED: emptyString(zod.union([zod.literal('1'), zod.literal('0')]).optional()), }); const SuperTokensModel = zod.object({ @@ -397,6 +398,7 @@ export const env = { host: redis.REDIS_HOST, port: redis.REDIS_PORT, password: redis.REDIS_PASSWORD ?? '', + tlsEnabled: redis.REDIS_TLS_ENABLED === '1', }, supertokens: { connectionURI: supertokens.SUPERTOKENS_CONNECTION_URI, diff --git a/packages/services/tokens/README.md b/packages/services/tokens/README.md index a21dc7f69..b7840c8b2 100644 --- a/packages/services/tokens/README.md +++ b/packages/services/tokens/README.md @@ -17,6 +17,7 @@ APIs (usage service and GraphQL API). | `REDIS_HOST` | **Yes** | The host of your redis instance. | `"127.0.0.1"` | | `REDIS_PORT` | **Yes** | The port of your redis instance. | `6379` | | `REDIS_PASSWORD` | **Yes** | The password of your redis instance. | `"apollorocks"` | +| `REDIS_TLS_ENABLED` | **No** | Enable TLS for redis connection (rediss://). | `"0"` | | `RATE_LIMIT_ENDPOINT` | **Yes** | The endpoint of the rate limiting service. | `http://127.0.0.1:4012` | | `ENVIRONMENT` | No | The environment of your Hive app. (**Note:** This will be used for Sentry reporting.) | `staging` | | `SENTRY` | No | Whether Sentry error reporting should be enabled. | `1` (enabled) or `0` (disabled) | diff --git a/packages/services/tokens/src/environment.ts b/packages/services/tokens/src/environment.ts index bf71de6d2..b26e22050 100644 --- a/packages/services/tokens/src/environment.ts +++ b/packages/services/tokens/src/environment.ts @@ -48,6 +48,7 @@ const RedisModel = zod.object({ REDIS_HOST: zod.string(), REDIS_PORT: NumberFromString, REDIS_PASSWORD: emptyString(zod.string().optional()), + REDIS_TLS_ENABLED: emptyString(zod.union([zod.literal('1'), zod.literal('0')]).optional()), }); const PrometheusModel = zod.object({ @@ -143,6 +144,7 @@ export const env = { host: redis.REDIS_HOST, port: redis.REDIS_PORT, password: redis.REDIS_PASSWORD, + tlsEnabled: redis.REDIS_TLS_ENABLED === '1', }, heartbeat: base.HEARTBEAT_ENDPOINT ? { endpoint: base.HEARTBEAT_ENDPOINT } : null, sentry: sentry.SENTRY === '1' ? { dsn: sentry.SENTRY_DSN } : null, diff --git a/packages/services/tokens/src/index.ts b/packages/services/tokens/src/index.ts index 80a3c33de..73f2ce1ac 100644 --- a/packages/services/tokens/src/index.ts +++ b/packages/services/tokens/src/index.ts @@ -80,6 +80,7 @@ export async function main() { maxRetriesPerRequest: 20, db: 0, enableReadyCheck: false, + tls: env.redis.tlsEnabled ? {} : undefined, }); const { start, stop, readiness, getStorage } = useCache( diff --git a/packages/services/webhooks/README.md b/packages/services/webhooks/README.md index bdd85dbe2..5d46535a1 100644 --- a/packages/services/webhooks/README.md +++ b/packages/services/webhooks/README.md @@ -10,6 +10,7 @@ This service takes care of delivering WebHooks. | `REDIS_HOST` | **Yes** | The host of your redis instance. | `"127.0.0.1"` | | `REDIS_PORT` | **Yes** | The port of your redis instance. | `6379` | | `REDIS_PASSWORD` | **Yes** | The password of your redis instance. | `"apollorocks"` | +| `REDIS_TLS_ENABLED` | **No** | Enable TLS for redis connection (rediss://). | `"0"` | | `ENVIRONMENT` | No | The environment of your Hive app. (**Note:** This will be used for Sentry reporting.) | `staging` | | `HEARTBEAT_ENDPOINT` | No | The endpoint for a heartbeat. | `http://127.0.0.1:6969/heartbeat` | | `SENTRY` | No | Whether Sentry error reporting should be enabled. | `1` (enabled) or `0` (disabled) | diff --git a/packages/services/webhooks/src/environment.ts b/packages/services/webhooks/src/environment.ts index 416afab65..b5a013833 100644 --- a/packages/services/webhooks/src/environment.ts +++ b/packages/services/webhooks/src/environment.ts @@ -29,6 +29,7 @@ const RedisModel = zod.object({ REDIS_HOST: zod.string(), REDIS_PORT: NumberFromString, REDIS_PASSWORD: emptyString(zod.string().optional()), + REDIS_TLS_ENABLED: emptyString(zod.union([zod.literal('1'), zod.literal('0')]).optional()), }); const RequestBrokerModel = zod.union([ @@ -137,6 +138,7 @@ export const env = { host: redis.REDIS_HOST, port: redis.REDIS_PORT, password: redis.REDIS_PASSWORD ?? '', + tlsEnabled: redis.REDIS_TLS_ENABLED === '1', }, heartbeat: base.HEARTBEAT_ENDPOINT ? { endpoint: base.HEARTBEAT_ENDPOINT } : null, sentry: sentry.SENTRY === '1' ? { dsn: sentry.SENTRY_DSN } : null, diff --git a/packages/services/webhooks/src/index.ts b/packages/services/webhooks/src/index.ts index 731a4645a..4b578036d 100644 --- a/packages/services/webhooks/src/index.ts +++ b/packages/services/webhooks/src/index.ts @@ -64,6 +64,7 @@ async function main() { host: env.redis.host, port: env.redis.port, password: env.redis.password, + tlsEnabled: env.redis.tlsEnabled, }, webhookQueueName: 'webhook', maxAttempts: 10, diff --git a/packages/services/webhooks/src/scheduler.ts b/packages/services/webhooks/src/scheduler.ts index 6e63f9ee2..95785f534 100644 --- a/packages/services/webhooks/src/scheduler.ts +++ b/packages/services/webhooks/src/scheduler.ts @@ -128,6 +128,7 @@ export function createScheduler(config: Config) { db: 0, maxRetriesPerRequest: null, enableReadyCheck: false, + tls: config.redis.tlsEnabled ? {} : undefined, }); redisConnection.on('error', err => { diff --git a/packages/services/webhooks/src/types.ts b/packages/services/webhooks/src/types.ts index 2b1517f7c..85e0267b0 100644 --- a/packages/services/webhooks/src/types.ts +++ b/packages/services/webhooks/src/types.ts @@ -8,6 +8,7 @@ export interface Config { host: string; port: number; password: string; + tlsEnabled: boolean; }; webhookQueueName: string; maxAttempts: number;