Skip to content

Commit 015a632

Browse files
committed
self-hosted fixes
console: allow plain CONSOLE_AUTH_TOKENS
1 parent d0f8a91 commit 015a632

File tree

9 files changed

+155
-110
lines changed

9 files changed

+155
-110
lines changed

docker-start-console.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ main() {
8686
if [ -z "$cmd" ]; then
8787
if [ "$UPDATE_DB" = "1" ] || [ "$UPDATE_DB" = "yes" ] || [ "$UPDATE_DB" = "true" ]; then
8888
echo "UPDATE_DB is set, updating database schema..."
89-
prisma --skip-generate --schema schema.prisma
89+
prisma db push --skip-generate --schema schema.prisma
9090
fi
9191
echo "Starting the app"
9292
healthcheck $$ &
@@ -97,7 +97,7 @@ main() {
9797

9898

9999
elif [ "$cmd" = "db-prepare" ]; then
100-
prisma --skip-generate --schema schema.prisma
100+
prisma db push --skip-generate --schema schema.prisma
101101
else
102102
echo "ERROR! Unknown command '$cmd'"
103103
fi

docker/.env.example

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
1-
# Required
1+
### Required ###
22
GITHUB_CLIENT_ID=
33
GITHUB_CLIENT_SECRET=
4+
# Domain name of your Jitsu server where events will be sent. E.g. jitsu.mycompany.com
5+
INGEST_DOMAIN=localhost
6+
# Public URL of your Jitsu UI is available. E.g. https://jitsu.mycompany.com:3000 or http://localhost:3000
7+
JITSU_PUBLIC_URL=http://localhost:3000
48

5-
# Secrets
6-
9+
#### Secrets ###
10+
CONSOLE_PASSWORD=change_me
711
POSTGRES_PASSWORD=change_me
812
REDIS_PASSWORD=change_me
913

10-
# Optional
11-
JITSU_PORT=3000
12-
JITSU_PUBLIC_URL=
14+
### Optional ###
15+
JITSU_UI_PORT=3000
16+
JITSU_INGEST_PORT=8080
17+
# comma-separated list of test user credentials in format email:password, e.g.: email1@example.com:password1,email2@example.com:password2
18+
TEST_CREDENTIALS=
1319

14-
# Connectors specific
20+
### Connectors specific ###
1521
SYNCS_ENABLED=false
1622
# Source Connectors License
1723
# Jitsu is licensed under MIT license, but some source connectors may use other licenses.
@@ -20,8 +26,6 @@ SYNCS_ENABLED=false
2026
# You can enable all source connectors by setting this variable to false
2127
# All source connectors will be enabled, but particular connectors license may conflict with license of your product
2228
MIT_COMPLIANT=true
23-
24-
2529
# bulker host how it is reachable from k8s cluster
2630
EXTERNAL_BULKER_HOST=
2731
#postgres host how it is reachable from k8s cluster

docker/docker-compose.yml

Lines changed: 121 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
version: "3.8"
22
services:
3+
kafka:
4+
tty: true
5+
image: "bitnami/kafka:3.6.0"
6+
environment:
7+
TERM: "xterm-256color"
8+
KAFKA_CFG_NODE_ID: 0
9+
KAFKA_CFG_PROCESS_ROLES: controller,broker
10+
KAFKA_CFG_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093
11+
KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
12+
KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 0@kafka:9093
13+
KAFKA_CFG_CONTROLLER_LISTENER_NAMES: CONTROLLER
14+
healthcheck:
15+
test: ["CMD-SHELL", "kafka-topics.sh --bootstrap-server 127.0.0.1:9092 --describe"]
16+
interval: 5s
17+
timeout: 3s
18+
retries: 30
19+
volumes:
20+
- ./data/kafka:/bitnami/kafka
21+
322
redis:
423
tty: true
524
image: redis:6.2-alpine
@@ -25,128 +44,147 @@ services:
2544
interval: 1s
2645
timeout: 10s
2746
retries: 10
28-
# volumes:
29-
# - ./data/postgres:/var/lib/postgresql/data
30-
zookeeper:
47+
# volumes:
48+
# - ./data/postgres:/var/lib/postgresql/data
49+
50+
51+
console:
3152
tty: true
53+
image: jitsucom/console:beta
54+
restart: "unless-stopped"
3255
platform: linux/amd64
33-
image: wurstmeister/zookeeper:latest
34-
kafka:
35-
tty: true
36-
image: wurstmeister/kafka:latest
37-
depends_on:
38-
- zookeeper
3956
environment:
40-
TERM: "xterm-256color"
41-
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
42-
KAFKA_LISTENERS: INTERNAL://0.0.0.0:19093,OUTSIDE://0.0.0.0:19092
43-
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:19093,OUTSIDE://localhost:19092
44-
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,OUTSIDE:PLAINTEXT
45-
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
57+
DATA_DOMAIN: ${INGEST_DOMAIN}
58+
ROTOR_URL: "http://rotor:3401"
59+
BULKER_URL: "http://bulker:3042"
60+
CONSOLE_AUTH_TOKENS: ${CONSOLE_PASSWORD}
61+
BULKER_AUTH_KEY: ${BULKER_PASSWORD}
62+
MIT_COMPLIANT: ${MIT_COMPLIANT:-true}
63+
DATABASE_URL: "postgresql://postgres:${POSTGRES_PASSWORD:-default}@postgres:5432/postgres?schema=newjitsu"
64+
REDIS_URL: "redis://default:${REDIS_PASSWORD:-default}@redis:6379"
65+
TEST_CREDENTIALS: ${TEST_CREDENTIALS}
66+
TEST_CREDENTIALS_SHOW_LOGIN: "true"
67+
GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID}
68+
GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET}
69+
SYNCS_ENABLED: ${SYNCS_ENABLED:-false}
70+
SYNCCTL_URL: "http://syncctl:3043"
71+
SYNCCTL_AUTH_KEY: ${SYNCCTL_PASSWORD}
72+
GOOGLE_SCHEDULER_KEY: ${GOOGLE_SCHEDULER_KEY}
73+
GOOGLE_SCHEDULER_LOCATION: ${GOOGLE_SCHEDULER_LOCATION:-us-central1}
74+
NEXTAUTH_URL: "${JITSU_PUBLIC_URL:-${NEXTAUTH_URL:-http://localhost:${JITSU_UI_PORT:-3000}/}}"
75+
UPDATE_DB: "true"
4676
healthcheck:
47-
test: ["CMD-SHELL", "kafka-topics.sh --bootstrap-server 127.0.0.1:19092 --describe"]
48-
interval: 5s
49-
timeout: 3s
77+
test: [ "CMD", "curl", "-f", "http://console:3000/api/healthcheck" ]
78+
interval: 2s
79+
timeout: 10s
5080
retries: 30
81+
depends_on:
82+
redis:
83+
condition: service_started
84+
postgres:
85+
condition: service_healthy
86+
ports:
87+
- "${JITSU_UI_PORT:-3000}:3000"
5188

5289
bulker:
5390
tty: true
54-
image: jitsucom/bulker:latest
91+
image: jitsucom/bulker:beta
5592
platform: linux/amd64
5693
restart: "unless-stopped"
5794
environment:
58-
BULKER_HTTP_PORT: "3042"
5995
TERM: "xterm-256color"
60-
BULKER_KAFKA_BOOTSTRAP_SERVERS: "kafka:19093"
96+
BULKER_KAFKA_BOOTSTRAP_SERVERS: "kafka:9092"
6197
BULKER_AUTH_TOKENS: ${BULKER_PASSWORD}
62-
BULKER_CONFIG_SOURCE: "redis"
98+
BULKER_CONFIG_SOURCE: "http://console:3000/api/admin/export/bulker-connections"
99+
BULKER_CONFIG_SOURCE_HTTP_AUTH_TOKEN: "service-admin-account:${CONSOLE_PASSWORD}"
100+
BULKER_CACHE_DIR: "/tmp/cache"
63101
REDIS_URL: "redis://default:${REDIS_PASSWORD:-default}@redis:6379"
64102
BULKER_INTERNAL_TASK_LOG: '{"id":"task_log","metricsKeyPrefix":"syncs","usesBulker":true,"type":"postgres","options":{"mode":"stream"},"credentials":{"host":"postgres","port":5432,"sslMode":"disable","database":"postgres","password":"${POSTGRES_PASSWORD:-default}","username":"postgres","defaultSchema":"public"}}'
65103
healthcheck:
66-
test: ["CMD", "curl", "-f", "http://localhost:3042/ready"]
104+
test: ["CMD", "curl", "-f", "http://bulker:3042/health"]
67105
interval: 2s
68106
timeout: 10s
69107
retries: 15
70108
depends_on:
71-
redis:
72-
condition: service_started
73-
kafka:
74-
condition: service_healthy
75-
syncctl:
76-
tty: true
77-
image: jitsucom/syncctl:latest
78-
platform: linux/amd64
79-
restart: "on-failure"
80-
environment:
81-
HTTP_PORT: "3043"
82-
TERM: "xterm-256color"
83-
SYNCCTL_SYNCS_ENABLED: ${SYNCS_ENABLED:-false}
84-
SYNCCTL_AUTH_TOKENS: ${SYNCCTL_PASSWORD}
85-
SYNCCTL_DATABASE_URL: "postgresql://postgres:${POSTGRES_PASSWORD:-default}@postgres:5432/postgres"
86-
SYNCCTL_SIDECAR_DATABASE_URL: "postgresql://postgres:${POSTGRES_PASSWORD:-default}@${EXTERNAL_DATABASE_HOST}:${PG_PORT:-5437}/postgres"
87-
SYNCCTL_BULKER_URL: "http://${EXTERNAL_BULKER_HOST}:${BULKER_PORT:-3045}"
88-
SYNCCTL_BULKER_AUTH_TOKEN: ${BULKER_PASSWORD}
89-
SYNCCTL_BULKER_LOGS_CONNECTION_ID: task_log
90-
SYNCCTL_KUBERNETES_CLIENT_CONFIG: "${SYNCCTL_KUBERNETES_CLIENT_CONFIG:-local}"
91-
SYNCCTL_KUBERNETES_CONTEXT: "${SYNCCTL_KUBERNETES_CONTEXT}"
92-
volumes:
93-
- ./data/syncctl:/etc/syncctl
94-
extra_hosts:
95-
- "kubernetes:host-gateway"
96-
depends_on:
97-
bulker:
109+
console:
98110
condition: service_healthy
99-
postgres:
111+
kafka:
100112
condition: service_healthy
113+
101114
rotor:
102115
tty: true
103-
image: jitsucom/rotor:latest
116+
image: jitsucom/rotor:beta
104117
platform: linux/amd64
105118
restart: "unless-stopped"
106119
environment:
107120
DISABLE_SERVICE_prisma: "true"
108121
DISABLE_SERVICE_pg: "true"
109122
BULKER_URL: "http://bulker:3042"
110123
BULKER_AUTH_KEY: ${BULKER_PASSWORD}
111-
KAFKA_BOOTSTRAP_SERVERS: "kafka:19093"
124+
KAFKA_BOOTSTRAP_SERVERS: "kafka:9092"
112125
REDIS_URL: "redis://default:${REDIS_PASSWORD:-default}@redis:6379"
113-
CONFIG_STORE_DATABASE_URL: "postgresql://postgres:${POSTGRES_PASSWORD:-default}@postgres:5432/postgres"
126+
REPOSITORY_BASE_URL: "http://console:3000/api/admin/export/"
127+
REPOSITORY_AUTH_TOKEN: "service-admin-account:${CONSOLE_PASSWORD}"
128+
REPOSITORY_CACHE_DIR: "/tmp/cache"
129+
healthcheck:
130+
test: [ "CMD", "curl", "-f", "http://rotor:3401/health" ]
131+
interval: 2s
132+
timeout: 10s
133+
retries: 15
114134
depends_on:
115-
bulker:
135+
console:
116136
condition: service_healthy
117-
kafka:
137+
bulker:
118138
condition: service_healthy
119-
redis:
120-
condition: service_started
121-
console:
139+
140+
ingest:
122141
tty: true
123-
image: jitsucom/console:latest
124-
restart: "unless-stopped"
142+
image: jitsucom/ingest:beta
125143
platform: linux/amd64
144+
restart: "unless-stopped"
126145
environment:
127-
ROTOR_URL: "http://rotor:3401"
128-
BULKER_URL: "http://bulker:3042"
129-
BULKER_AUTH_KEY: ${BULKER_PASSWORD}
130-
MIT_COMPLIANT: ${MIT_COMPLIANT:-true}
131-
DATABASE_URL: "postgresql://postgres:${POSTGRES_PASSWORD:-default}@postgres:5432/postgres"
132-
REDIS_URL: "redis://default:${REDIS_PASSWORD:-default}@redis:6379"
133-
TEST_CREDENTIALS: ${TEST_CREDENTIALS}
134-
TEST_CREDENTIALS_SHOW_LOGIN: "true"
135-
GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID}
136-
GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET}
137-
SYNCS_ENABLED: ${SYNCS_ENABLED:-false}
138-
SYNCCTL_URL: "http://syncctl:3043"
139-
SYNCCTL_AUTH_KEY: ${SYNCCTL_PASSWORD}
140-
GOOGLE_SCHEDULER_KEY: ${GOOGLE_SCHEDULER_KEY}
141-
GOOGLE_SCHEDULER_LOCATION: ${GOOGLE_SCHEDULER_LOCATION:-us-central1}
142-
NEXTAUTH_URL: "${JITSU_PUBLIC_URL:-${NEXTAUTH_URL:-http://localhost:${JITSU_PORT:-3000}/}}"
143-
UPDATE_DB: "true"
146+
TERM: "xterm-256color"
147+
INGEST_DATA_DOMAIN: ${INGEST_DOMAIN}
148+
INGEST_KAFKA_BOOTSTRAP_SERVERS: "kafka:9092"
149+
INGEST_AUTH_TOKENS: ${BULKER_PASSWORD}
150+
INGEST_REPOSITORY_URL: "http://console:3000/api/admin/export/streams-with-destinations"
151+
INGEST_REPOSITORY_AUTH_TOKENS: "service-admin-account:${CONSOLE_PASSWORD}"
152+
INGEST_CACHE_DIR: "/tmp/cache"
153+
INGEST_REDIS_URL: "redis://default:${REDIS_PASSWORD:-default}@redis:6379"
154+
INGEST_ROTOR_URL: "http://rotor:3401"
155+
healthcheck:
156+
test: [ "CMD", "curl", "-f", "http://ingest:3049/health" ]
157+
interval: 2s
158+
timeout: 10s
159+
retries: 15
144160
depends_on:
145-
redis:
146-
condition: service_started
147-
bulker:
161+
console:
148162
condition: service_healthy
149-
postgres:
163+
rotor:
150164
condition: service_healthy
151165
ports:
152-
- "${JITSU_PORT:-3000}:3000"
166+
- "${JITSU_INGEST_PORT:-8080}:3049"
167+
168+
syncctl:
169+
tty: true
170+
image: jitsucom/syncctl:beta
171+
platform: linux/amd64
172+
restart: "on-failure"
173+
environment:
174+
TERM: "xterm-256color"
175+
SYNCCTL_SYNCS_ENABLED: ${SYNCS_ENABLED:-false}
176+
SYNCCTL_AUTH_TOKENS: ${SYNCCTL_PASSWORD}
177+
SYNCCTL_DATABASE_URL: "postgresql://postgres:${POSTGRES_PASSWORD:-default}@postgres:5432/postgres?search_path=newjitsu"
178+
SYNCCTL_SIDECAR_DATABASE_URL: "postgresql://postgres:${POSTGRES_PASSWORD:-default}@${EXTERNAL_DATABASE_HOST}:${PG_PORT:-5437}/postgres?search_path=newjitsu"
179+
SYNCCTL_BULKER_URL: "http://${EXTERNAL_BULKER_HOST}:${BULKER_PORT:-3045}"
180+
SYNCCTL_BULKER_AUTH_TOKEN: ${BULKER_PASSWORD}
181+
SYNCCTL_BULKER_LOGS_CONNECTION_ID: task_log
182+
SYNCCTL_KUBERNETES_CLIENT_CONFIG: "${SYNCCTL_KUBERNETES_CLIENT_CONFIG:-local}"
183+
SYNCCTL_KUBERNETES_CONTEXT: "${SYNCCTL_KUBERNETES_CONTEXT}"
184+
volumes:
185+
- ./data/syncctl:/etc/syncctl
186+
extra_hosts:
187+
- "kubernetes:host-gateway"
188+
depends_on:
189+
bulker:
190+
condition: service_healthy

libs/juava/__tests__/id.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { checkHash, createHash, randomId } from "../src";
1+
import { randomId } from "../src";
22

33
test("id test", () => {
44
const id1 = randomId();

libs/juava/__tests__/security.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import { createHash, checkHash, createAuthorized } from "../src/security";
1+
import { createHash, checkToken, createAuthorized } from "../src/security";
22

33
test("security", () => {
44
const password = "secretPassword";
55
const hashResult = createHash(password);
66
console.log("Hash result = " + hashResult);
7-
expect(checkHash(hashResult, password)).toBe(true);
8-
expect(checkHash(hashResult.substring(2), password)).toBe(false);
7+
expect(checkToken(hashResult, password)).toBe(true);
8+
expect(checkToken(hashResult.substring(2), password)).toBe(false);
99
});
1010

1111
test("authorizer", () => {

libs/juava/src/security.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ export function createHash(secret: string): string {
2323
return hashInternal(secret, randomSeed, globalSeed[0]);
2424
}
2525

26+
export function checkToken(hashOrPlain: string, secret: string): boolean {
27+
if (hashOrPlain.indexOf(".") === -1) {
28+
return secret === hashOrPlain;
29+
}
30+
return checkHash(hashOrPlain, secret);
31+
}
32+
2633
export function checkHash(hash: string, secret: string): boolean {
2734
const [randomSeed] = hash.split(".");
2835
return globalSeed.find(seed => hash === hashInternal(secret, randomSeed, seed)) !== undefined;
@@ -43,11 +50,7 @@ export function createAuthorized(tokens: string): Authorizer {
4350
const authorizers = tokens
4451
.split(",")
4552
.map(tok => tok.trim())
46-
.map(hashOrPlain =>
47-
hashOrPlain.indexOf(".") === -1
48-
? (secret: string) => secret === hashOrPlain
49-
: (secret: string) => checkHash(hashOrPlain, secret)
50-
);
53+
.map(hashOrPlain => (secret: string) => checkToken(hashOrPlain, secret));
5154
return (secret: string) => authorizers.find(auth => auth(secret)) !== undefined;
5255
}
5356

services/rotor/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ async function main() {
4242
errorTypes.forEach(type => {
4343
process.once(type, err => {
4444
log.atError().withCause(err).log(`process.on ${type}`);
45-
process.exit(1);
45+
// process.exit(1);
4646
});
4747
});
4848

webapps/console/lib/api.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ZodType } from "zod";
22
import { NextApiHandler, NextApiRequest, NextApiResponse } from "next";
3-
import { assertDefined, checkHash, getErrorMessage, requireDefined, tryJson } from "juava";
3+
import { assertDefined, checkToken, getErrorMessage, requireDefined, tryJson } from "juava";
44
import { getServerSession, Session } from "next-auth";
55
import { nextAuthConfig } from "./nextauth.config";
66
import { SessionUser } from "./schema";
@@ -87,8 +87,8 @@ export function getAuthBearerToken(req: NextApiRequest): string | undefined {
8787
function findServiceAccount({ keyId, secret }): SessionUser | undefined {
8888
if (process.env.CONSOLE_AUTH_TOKENS) {
8989
const tokens = process.env.CONSOLE_AUTH_TOKENS.split(",");
90-
for (const tokenHash of tokens) {
91-
if (checkHash(tokenHash, secret)) {
90+
for (const tokenHashOrPlain of tokens) {
91+
if (checkToken(tokenHashOrPlain, secret)) {
9292
return {
9393
internalId: adminServiceAccountEmail,
9494
externalUsername: adminServiceAccountEmail,
@@ -120,7 +120,7 @@ export async function getUser(
120120
if (!token) {
121121
throw new ApiError(`Invalid API key id ${keyId}`, { keyId }, { status: 401 });
122122
}
123-
if (!checkHash(token.hash, secret)) {
123+
if (!checkToken(token.hash, secret)) {
124124
throw new ApiError(`Invalid API key secret for ${keyId}`, { keyId }, { status: 401 });
125125
}
126126
const user = requireDefined(

0 commit comments

Comments
 (0)