Initial commit for gscMy carved out as its own repo (was tracked
loosely under the monorepo's web/ which is gitignored).
What this contains:
- Auth: next-auth v5 via @gsc/web-kit createAuth (Keycloak only,
identity sourced from claims, no admin.users writes)
- Chrome: @gsc/web-kit AdminShell — replaces the legacy MyShell.
Sidebar JSON config carried over and mapped to DbMenuItem.
- Middleware: createAuthMiddleware. Public: /access-denied,
/auth/keycloak, /signed-out, /api/health, /api/pam/approve.
- RP-initiated signout at /api/auth/signout → Keycloak end_session →
/signed-out (mirrors gscAdmin).
- Phosphor-iconned access-denied + signed-out landing pages.
PAM/JIT request flow (ported from gscAdmin's pre-strip git history):
- /access page (Active + Eligible tables, request modal with
duration slider + justification + optional MFA)
- API: /api/pam/{eligible, active, audit, request, approve/:token,
revoke/:id}
- src/lib/{authz, pam, pam-mail, pam-mfa}.ts — same files as
gscAdmin had before the strip. PAM tables (admin.privilege_*)
are shared with gscAdmin; gscMy uses the same Prisma model defs.
- Top-bar widget shows active grants with countdown + revoke.
Build/Deploy: Dockerfile (monorepo-root context), k8s manifests for
my.gosec.internal, self-signed TLS placeholder, DNS A record.
Keycloak gsc-my client extended to include my.gosec.internal/* in
redirect_uris + web_origins.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
79 lines
2.9 KiB
Docker
79 lines
2.9 KiB
Docker
# GoSec My UI — Production Dockerfile
|
|
#
|
|
# Build context MUST be the monorepo root (/srv/k8s):
|
|
# podman build -f web/gscMy/Dockerfile -t gsc-my-ui /srv/k8s
|
|
# Mirrors web/gscAdmin/Dockerfile.
|
|
|
|
# Stage 1: Builder.
|
|
FROM node:22-alpine AS builder
|
|
RUN apk add --no-cache libc6-compat openssl
|
|
|
|
# @limitless/ui — build dist/ first.
|
|
COPY templates/limitless-ui /srv/k8s/templates/limitless-ui
|
|
WORKDIR /srv/k8s/templates/limitless-ui
|
|
RUN npm install --no-audit --no-fund && npm run build
|
|
|
|
# @gsc/web-kit — build dist/, drop bundled next-intl/next-auth so they
|
|
# resolve from this app's tree (React-context unity).
|
|
COPY templates/gsc-web-kit /srv/k8s/templates/gsc-web-kit
|
|
WORKDIR /srv/k8s/templates/gsc-web-kit
|
|
RUN npm install --no-audit --no-fund && npm run build && \
|
|
rm -rf node_modules/next-intl node_modules/next-auth
|
|
|
|
# @gsc/chat — dist/ is gitignored; build in place.
|
|
COPY infra/gscAICoreSystem/frontends/gscBicameralFrontend /srv/k8s/infra/gscAICoreSystem/frontends/gscBicameralFrontend
|
|
WORKDIR /srv/k8s/infra/gscAICoreSystem/frontends/gscBicameralFrontend
|
|
RUN npm install --no-audit --no-fund && npm run build
|
|
|
|
# Make @gsc/chat resolvable from inside @gsc/web-kit.
|
|
RUN mkdir -p /srv/k8s/templates/gsc-web-kit/node_modules/@gsc && \
|
|
ln -sfn ../../../../infra/gscAICoreSystem/frontends/gscBicameralFrontend \
|
|
/srv/k8s/templates/gsc-web-kit/node_modules/@gsc/chat
|
|
|
|
# gscMy — package.json + prisma schema first so postinstall finds it.
|
|
WORKDIR /srv/k8s/web/gscMy
|
|
COPY web/gscMy/package.json web/gscMy/package-lock.json* ./
|
|
COPY web/gscMy/prisma ./prisma
|
|
RUN npm install --no-audit --no-fund --no-package-lock
|
|
|
|
# Link this app's next-intl + next-auth into the kit's node_modules
|
|
# so the kit's compiled chrome shares the same module instances.
|
|
RUN ln -sfn ../../../web/gscMy/node_modules/next-intl \
|
|
/srv/k8s/templates/gsc-web-kit/node_modules/next-intl && \
|
|
ln -sfn ../../../web/gscMy/node_modules/next-auth \
|
|
/srv/k8s/templates/gsc-web-kit/node_modules/next-auth
|
|
|
|
# Rest of source.
|
|
COPY web/gscMy/. ./
|
|
|
|
ARG NEXT_PUBLIC_APP_URL=https://my.gosec.internal
|
|
ENV NEXT_PUBLIC_APP_URL=$NEXT_PUBLIC_APP_URL
|
|
ENV NEXT_TELEMETRY_DISABLED=1
|
|
|
|
# Strip local-dev env so it doesn't bake into the image (esp. AUTH_URL
|
|
# pointing at my.gosec.cloud:3000).
|
|
RUN rm -f .env .env.local .env.development.local .env.production.local
|
|
|
|
RUN npm run build
|
|
|
|
# Stage 2: Runtime
|
|
FROM node:22-alpine AS runner
|
|
RUN apk add --no-cache openssl
|
|
|
|
WORKDIR /app
|
|
ENV NODE_ENV=production
|
|
ENV NEXT_TELEMETRY_DISABLED=1
|
|
|
|
# outputFileTracingRoot=/srv/k8s preserves the web/gscMy subtree in the
|
|
# standalone bundle, so server.js lands at /app/web/gscMy/server.js.
|
|
COPY --from=builder --chown=node:node /srv/k8s/web/gscMy/.next/standalone ./
|
|
COPY --from=builder --chown=node:node /srv/k8s/web/gscMy/public ./web/gscMy/public
|
|
COPY --from=builder --chown=node:node /srv/k8s/web/gscMy/.next/static ./web/gscMy/.next/static
|
|
|
|
USER node
|
|
|
|
EXPOSE 3000
|
|
ENV PORT=3000 HOSTNAME=0.0.0.0
|
|
|
|
ENTRYPOINT ["node", "web/gscMy/server.js"]
|