mirror of
https://github.com/Infisical/infisical.git
synced 2025-03-15 19:33:32 +00:00
Compare commits
53 Commits
infisical/
...
cypress
Author | SHA1 | Date | |
---|---|---|---|
7487b373fe | |||
9a500504a4 | |||
1510c39631 | |||
d0579b383f | |||
b4f4c1064d | |||
d72d3940e6 | |||
7217bcb3d8 | |||
2faa9222d8 | |||
589f0bc134 | |||
bd6dc3d4c0 | |||
9338babda6 | |||
6f9e8644d7 | |||
2fdb10277e | |||
15d2c536ed | |||
a304228961 | |||
c865b78b41 | |||
be80ac999e | |||
076fe58325 | |||
66bfab1994 | |||
b92c50addd | |||
8fbca05052 | |||
d99830067e | |||
cdc8ef95ab | |||
072e97b956 | |||
4f26a7cad3 | |||
7bb6ff3d0c | |||
ecccec8e35 | |||
7fd15a06e5 | |||
5d4a37004e | |||
aa61fd091d | |||
04ac54bcfa | |||
38dbf1e738 | |||
ddf9d7848c | |||
0b40de49ec | |||
b1d16cab39 | |||
fb7c7045e9 | |||
d570828e47 | |||
2a92b6c787 | |||
ee54fdabe1 | |||
136308f299 | |||
ba41244877 | |||
c4dcf334f0 | |||
66bac3ef48 | |||
e5347719c3 | |||
abe1f54aab | |||
13c1e2b349 | |||
f5a9afec61 | |||
d0a85c98b2 | |||
e0669cae7c | |||
2c011b7d53 | |||
1b24a9b6e9 | |||
00c173aead | |||
2e15ad0625 |
@ -1,2 +1,10 @@
|
||||
backend/node_modules
|
||||
frontend/node_modules
|
||||
frontend/node_modules
|
||||
backend/frontend-build
|
||||
**/node_modules
|
||||
**/.next
|
||||
.dockerignore
|
||||
.git
|
||||
README.md
|
||||
.dockerignore
|
||||
**/Dockerfile
|
||||
|
2
.github/resources/docker-compose.be-test.yml
vendored
2
.github/resources/docker-compose.be-test.yml
vendored
@ -6,7 +6,7 @@ services:
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- mongo
|
||||
image: infisical/backend:test
|
||||
image: infisical/infisical:test
|
||||
command: npm run start
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
|
36
.github/values.yaml
vendored
36
.github/values.yaml
vendored
@ -1,29 +1,3 @@
|
||||
# secretScanningGitApp:
|
||||
# enabled: false
|
||||
# deploymentAnnotations:
|
||||
# secrets.infisical.com/auto-reload: "true"
|
||||
# image:
|
||||
# repository: infisical/staging_deployment_secret-scanning-git-app
|
||||
|
||||
frontend:
|
||||
enabled: true
|
||||
name: frontend
|
||||
podAnnotations: {}
|
||||
deploymentAnnotations:
|
||||
secrets.infisical.com/auto-reload: "true"
|
||||
replicaCount: 2
|
||||
image:
|
||||
repository: infisical/staging_deployment_frontend
|
||||
tag: "latest"
|
||||
pullPolicy: Always
|
||||
kubeSecretRef: managed-secret-frontend
|
||||
service:
|
||||
annotations: {}
|
||||
type: ClusterIP
|
||||
nodePort: ""
|
||||
|
||||
frontendEnvironmentVariables: null
|
||||
|
||||
backend:
|
||||
enabled: true
|
||||
name: backend
|
||||
@ -32,7 +6,7 @@ backend:
|
||||
secrets.infisical.com/auto-reload: "true"
|
||||
replicaCount: 2
|
||||
image:
|
||||
repository: infisical/staging_deployment_backend
|
||||
repository: infisical/staging_infisical
|
||||
tag: "latest"
|
||||
pullPolicy: Always
|
||||
kubeSecretRef: managed-backend-secret
|
||||
@ -63,14 +37,8 @@ ingress:
|
||||
enabled: true
|
||||
# annotations:
|
||||
# kubernetes.io/ingress.class: "nginx"
|
||||
# cert-manager.io/issuer: letsencrypt-nginx
|
||||
# cert-manager.io/issuer: letsencrypt-nginx
|
||||
hostName: gamma.infisical.com ## <- Replace with your own domain
|
||||
frontend:
|
||||
path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
path: /api
|
||||
pathType: Prefix
|
||||
tls:
|
||||
[]
|
||||
# - secretName: letsencrypt-nginx
|
||||
|
@ -39,7 +39,7 @@ jobs:
|
||||
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||
load: true
|
||||
context: backend
|
||||
tags: infisical/backend:test
|
||||
tags: infisical/infisical:test
|
||||
- name: ⏻ Spawn backend container and dependencies
|
||||
run: |
|
||||
docker compose -f .github/resources/docker-compose.be-test.yml up --wait --quiet-pull
|
||||
|
71
.github/workflows/build-staging-img.yml
vendored
71
.github/workflows/build-staging-img.yml
vendored
@ -2,7 +2,7 @@ name: Build, Publish and Deploy to Gamma
|
||||
on: [workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
backend-image:
|
||||
infisical-image:
|
||||
name: Build backend image
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -32,8 +32,9 @@ jobs:
|
||||
project: 64mmf0n610
|
||||
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||
load: true
|
||||
context: backend
|
||||
tags: infisical/backend:test
|
||||
context: .
|
||||
file: Dockerfile.standalone-infisical
|
||||
tags: infisical/infisical:test
|
||||
- name: ⏻ Spawn backend container and dependencies
|
||||
run: |
|
||||
docker compose -f .github/resources/docker-compose.be-test.yml up --wait --quiet-pull
|
||||
@ -49,68 +50,20 @@ jobs:
|
||||
project: 64mmf0n610
|
||||
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||
push: true
|
||||
context: backend
|
||||
context: .
|
||||
file: Dockerfile.standalone-infisical
|
||||
tags: |
|
||||
infisical/staging_deployment_backend:${{ steps.commit.outputs.short }}
|
||||
infisical/staging_deployment_backend:latest
|
||||
infisical/staging_infisical:${{ steps.commit.outputs.short }}
|
||||
infisical/staging_infisical:latest
|
||||
platforms: linux/amd64,linux/arm64
|
||||
build-args: |
|
||||
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
|
||||
INFISICAL_PLATFORM_VERSION=${{ steps.extract_version.outputs.version }}
|
||||
|
||||
frontend-image:
|
||||
name: Build frontend image
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: ☁️ Checkout source
|
||||
uses: actions/checkout@v3
|
||||
- name: Save commit hashes for tag
|
||||
id: commit
|
||||
uses: pr-mpt/actions-commit-hash@v2
|
||||
- name: 🔧 Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: 🐋 Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: Set up Depot CLI
|
||||
uses: depot/setup-action@v1
|
||||
- name: 📦 Build frontend and export to Docker
|
||||
uses: depot/build-push-action@v1
|
||||
with:
|
||||
load: true
|
||||
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||
project: 64mmf0n610
|
||||
context: frontend
|
||||
tags: infisical/staging_deployment_frontend:test
|
||||
build-args: |
|
||||
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
|
||||
NEXT_INFISICAL_PLATFORM_VERSION=${{ steps.extract_version.outputs.version }}
|
||||
- name: ⏻ Spawn frontend container
|
||||
run: |
|
||||
docker run -d --rm --name infisical-frontend-test infisical/staging_deployment_frontend:test
|
||||
- name: 🧪 Test frontend image
|
||||
run: |
|
||||
./.github/resources/healthcheck.sh infisical-frontend-test
|
||||
- name: ⏻ Shut down frontend container
|
||||
run: |
|
||||
docker stop infisical-frontend-test
|
||||
- name: 🏗️ Build frontend and push
|
||||
uses: depot/build-push-action@v1
|
||||
with:
|
||||
project: 64mmf0n610
|
||||
push: true
|
||||
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||
context: frontend
|
||||
tags: |
|
||||
infisical/staging_deployment_frontend:${{ steps.commit.outputs.short }}
|
||||
infisical/staging_deployment_frontend:latest
|
||||
platforms: linux/amd64,linux/arm64
|
||||
build-args: |
|
||||
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
|
||||
NEXT_INFISICAL_PLATFORM_VERSION=${{ steps.extract_version.outputs.version }}
|
||||
gamma-deployment:
|
||||
name: Deploy to gamma
|
||||
runs-on: ubuntu-latest
|
||||
needs: [frontend-image, backend-image]
|
||||
needs: [infisical-image]
|
||||
steps:
|
||||
- name: ☁️ Checkout source
|
||||
uses: actions/checkout@v3
|
||||
|
@ -73,3 +73,6 @@ jobs:
|
||||
infisical/infisical:${{ steps.extract_version.outputs.version }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
file: Dockerfile.standalone-infisical
|
||||
build-args: |
|
||||
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
|
||||
INFISICAL_PLATFORM_VERSION=${{ steps.extract_version.outputs.version }}
|
||||
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -33,7 +33,7 @@ reports
|
||||
junit.xml
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
@ -59,4 +59,6 @@ yarn-error.log*
|
||||
.infisical.json
|
||||
|
||||
# Editor specific
|
||||
.vscode/*
|
||||
.vscode/*
|
||||
|
||||
frontend-build
|
@ -1,7 +1,13 @@
|
||||
ARG POSTHOG_HOST=https://app.posthog.com
|
||||
ARG POSTHOG_API_KEY=posthog-api-key
|
||||
ARG INTERCOM_ID=intercom-id
|
||||
|
||||
FROM node:16-alpine AS frontend-dependencies
|
||||
FROM node:16-alpine AS base
|
||||
|
||||
FROM base AS frontend-dependencies
|
||||
|
||||
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
|
||||
RUN apk add --no-cache libc6-compat
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@ -11,7 +17,7 @@ COPY frontend/package.json frontend/package-lock.json frontend/next.config.js ./
|
||||
RUN npm ci --only-production --ignore-scripts
|
||||
|
||||
# Rebuild the source code only when needed
|
||||
FROM node:16-alpine AS frontend-builder
|
||||
FROM base AS frontend-builder
|
||||
WORKDIR /app
|
||||
|
||||
# Copy dependencies
|
||||
@ -27,41 +33,38 @@ ARG POSTHOG_API_KEY
|
||||
ENV NEXT_PUBLIC_POSTHOG_API_KEY $POSTHOG_API_KEY
|
||||
ARG INTERCOM_ID
|
||||
ENV NEXT_PUBLIC_INTERCOM_ID $INTERCOM_ID
|
||||
ARG INFISICAL_PLATFORM_VERSION
|
||||
ENV NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION
|
||||
|
||||
# Build
|
||||
RUN npm run build
|
||||
|
||||
# Production image
|
||||
FROM node:16-alpine AS frontend-runner
|
||||
FROM base AS frontend-runner
|
||||
WORKDIR /app
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs
|
||||
RUN adduser --system --uid 1001 nextjs
|
||||
RUN adduser --system --uid 1001 non-root-user
|
||||
|
||||
RUN mkdir -p /app/.next/cache/images && chown nextjs:nodejs /app/.next/cache/images
|
||||
RUN mkdir -p /app/.next/cache/images && chown non-root-user:nodejs /app/.next/cache/images
|
||||
VOLUME /app/.next/cache/images
|
||||
|
||||
ARG POSTHOG_API_KEY
|
||||
ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \
|
||||
BAKED_NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY
|
||||
ARG INTERCOM_ID
|
||||
ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
|
||||
BAKED_NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID
|
||||
|
||||
COPY --chown=nextjs:nodejs --chmod=555 frontend/scripts ./scripts
|
||||
COPY --chown=non-root-user:nodejs --chmod=555 frontend/scripts ./scripts
|
||||
COPY --from=frontend-builder /app/public ./public
|
||||
RUN chown nextjs:nodejs ./public/data
|
||||
COPY --from=frontend-builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||
COPY --from=frontend-builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||
RUN chown non-root-user:nodejs ./public/data
|
||||
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/.next/standalone ./
|
||||
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/.next/static ./.next/static
|
||||
|
||||
USER nextjs
|
||||
USER non-root-user
|
||||
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
|
||||
##
|
||||
## BACKEND
|
||||
##
|
||||
FROM node:16-alpine AS backend-build
|
||||
FROM base AS backend-build
|
||||
RUN addgroup --system --gid 1001 nodejs \
|
||||
&& adduser --system --uid 1001 non-root-user
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@ -69,10 +72,11 @@ COPY backend/package*.json ./
|
||||
RUN npm ci --only-production
|
||||
|
||||
COPY /backend .
|
||||
COPY --chown=non-root-user:nodejs standalone-entrypoint.sh standalone-entrypoint.sh
|
||||
RUN npm run build
|
||||
|
||||
# Production stage
|
||||
FROM node:16-alpine AS backend-runner
|
||||
FROM base AS backend-runner
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@ -81,27 +85,44 @@ RUN npm ci --only-production
|
||||
|
||||
COPY --from=backend-build /app .
|
||||
|
||||
RUN mkdir frontend-build
|
||||
|
||||
# Production stage
|
||||
FROM node:16-alpine AS production
|
||||
FROM base AS production
|
||||
RUN addgroup --system --gid 1001 nodejs \
|
||||
&& adduser --system --uid 1001 non-root-user
|
||||
|
||||
## set pre baked keys
|
||||
ARG POSTHOG_API_KEY
|
||||
ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \
|
||||
BAKED_NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY
|
||||
ARG INTERCOM_ID=intercom-id
|
||||
ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
|
||||
BAKED_NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID
|
||||
|
||||
WORKDIR /
|
||||
|
||||
# Install PM2
|
||||
RUN npm install -g pm2
|
||||
# Copy ecosystem.config.js
|
||||
COPY ecosystem.config.js .
|
||||
|
||||
RUN apk add --no-cache nginx
|
||||
|
||||
COPY nginx/default-stand-alone-docker.conf /etc/nginx/nginx.conf
|
||||
|
||||
COPY --from=backend-runner /app /backend
|
||||
|
||||
COPY --from=frontend-runner /app/ /app/
|
||||
COPY --from=frontend-runner /app ./backend/frontend-build
|
||||
|
||||
EXPOSE 80
|
||||
ENV PORT 8080
|
||||
ENV HTTPS_ENABLED false
|
||||
ENV NODE_ENV production
|
||||
ENV STANDALONE_BUILD true
|
||||
|
||||
WORKDIR /backend
|
||||
|
||||
ENV TELEMETRY_ENABLED true
|
||||
|
||||
HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \
|
||||
CMD node healthcheck.js
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
USER non-root-user
|
||||
|
||||
CMD ["./standalone-entrypoint.sh"]
|
||||
|
||||
CMD ["pm2-runtime", "start", "ecosystem.config.js"]
|
||||
|
||||
|
||||
|
@ -476,7 +476,7 @@ export const getSecrets = async (req: Request, res: Response) => {
|
||||
|
||||
if (folderId && folderId !== "root") {
|
||||
const folder = await Folder.findOne({ workspace: workspaceId, environment });
|
||||
if (!folder) throw BadRequestError({ message: "Folder not found" });
|
||||
if (!folder) return res.send({ secrets: [] });
|
||||
|
||||
secretPath = getFolderWithPathFromId(folder.nodes, folderId).folderPath;
|
||||
}
|
||||
@ -673,6 +673,7 @@ export const updateSecretByName = async (req: Request, res: Response) => {
|
||||
secretValueCiphertext,
|
||||
secretValueTag,
|
||||
secretValueIV,
|
||||
secretId,
|
||||
type,
|
||||
environment,
|
||||
secretPath,
|
||||
@ -741,6 +742,7 @@ export const updateSecretByName = async (req: Request, res: Response) => {
|
||||
workspaceId: new Types.ObjectId(workspaceId),
|
||||
environment,
|
||||
type,
|
||||
secretId,
|
||||
authData: req.authData,
|
||||
newSecretName,
|
||||
secretValueCiphertext,
|
||||
|
@ -13,7 +13,10 @@ router.get(
|
||||
const options = {
|
||||
failureRedirect: "/",
|
||||
additionalParams: {
|
||||
RelayState: req.query.callback_port ?? ""
|
||||
RelayState: JSON.stringify({
|
||||
spInitiated: true,
|
||||
callbackPort: req.query.callback_port ?? ""
|
||||
})
|
||||
},
|
||||
};
|
||||
passport.authenticate("saml", options)(req, res, next);
|
||||
|
@ -14,7 +14,7 @@ export const initDatabaseHelper = async ({
|
||||
}) => {
|
||||
try {
|
||||
await mongoose.connect(mongoURL);
|
||||
|
||||
|
||||
// allow empty strings to pass the required validator
|
||||
mongoose.Schema.Types.String.checkRequired(v => typeof v === "string");
|
||||
|
||||
@ -31,14 +31,10 @@ export const initDatabaseHelper = async ({
|
||||
* Close database conection
|
||||
*/
|
||||
export const closeDatabaseHelper = async () => {
|
||||
return Promise.all([
|
||||
new Promise((resolve) => {
|
||||
if (mongoose.connection && mongoose.connection.readyState == 1) {
|
||||
mongoose.connection.close()
|
||||
.then(() => resolve("Database connection closed"));
|
||||
} else {
|
||||
resolve("Database connection already closed");
|
||||
}
|
||||
}),
|
||||
]);
|
||||
}
|
||||
if (mongoose.connection && mongoose.connection.readyState === 1) {
|
||||
await mongoose.connection.close();
|
||||
return "Database connection closed";
|
||||
} else {
|
||||
return "Database connection already closed";
|
||||
}
|
||||
};
|
@ -790,6 +790,7 @@ export const getSecretHelper = async ({
|
||||
export const updateSecretHelper = async ({
|
||||
secretName,
|
||||
workspaceId,
|
||||
secretId,
|
||||
environment,
|
||||
type,
|
||||
authData,
|
||||
@ -812,11 +813,20 @@ export const updateSecretHelper = async ({
|
||||
workspaceId: new Types.ObjectId(workspaceId)
|
||||
});
|
||||
|
||||
const oldSecretBlindIndex = await generateSecretBlindIndexWithSaltHelper({
|
||||
let oldSecretBlindIndex = await generateSecretBlindIndexWithSaltHelper({
|
||||
secretName,
|
||||
salt
|
||||
});
|
||||
|
||||
if (secretId) {
|
||||
const secret = await Secret.findOne({
|
||||
workspace: workspaceId,
|
||||
environment,
|
||||
_id: secretId
|
||||
}).select("secretBlindIndex");
|
||||
if (secret && secret.secretBlindIndex) oldSecretBlindIndex = secret.secretBlindIndex;
|
||||
}
|
||||
|
||||
let secret: ISecret | null = null;
|
||||
const folderId = await getFolderIdFromServiceToken(workspaceId, environment, secretPath);
|
||||
|
||||
@ -891,6 +901,9 @@ export const updateSecretHelper = async ({
|
||||
skipMultilineEncoding,
|
||||
secretBlindIndex: newSecretNameBlindIndex,
|
||||
$inc: { version: 1 }
|
||||
},
|
||||
{
|
||||
new: true
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -87,6 +87,9 @@ import { setup } from "./utils/setup";
|
||||
import { syncSecretsToThirdPartyServices } from "./queues/integrations/syncSecretsToThirdPartyServices";
|
||||
import { githubPushEventSecretScan } from "./queues/secret-scanning/githubScanPushEvent";
|
||||
const SmeeClient = require("smee-client"); // eslint-disable-line
|
||||
import path from "path";
|
||||
|
||||
let handler: null | any = null;
|
||||
|
||||
const main = async () => {
|
||||
await setup();
|
||||
@ -147,6 +150,27 @@ const main = async () => {
|
||||
next();
|
||||
});
|
||||
|
||||
if ((await getNodeEnv()) === "production" && process.env.STANDALONE_BUILD === "true") {
|
||||
const nextJsBuildPath = path.join(__dirname, "../frontend-build");
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const conf = require("../frontend-build/.next/required-server-files.json").config;
|
||||
const NextServer =
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require("../frontend-build/node_modules/next/dist/server/next-server").default;
|
||||
const nextApp = new NextServer({
|
||||
dev: false,
|
||||
dir: nextJsBuildPath,
|
||||
port: await getPort(),
|
||||
conf,
|
||||
hostname: "local",
|
||||
customServer: false
|
||||
});
|
||||
|
||||
handler = nextApp.getRequestHandler();
|
||||
}
|
||||
|
||||
// (EE) routes
|
||||
app.use("/api/v1/secret", eeSecretRouter);
|
||||
app.use("/api/v1/secret-snapshot", eeSecretSnapshotRouter);
|
||||
@ -209,6 +233,12 @@ const main = async () => {
|
||||
// server status
|
||||
app.use("/api", healthCheck);
|
||||
|
||||
if (handler) {
|
||||
app.all("*", (req, res) => {
|
||||
return handler(req, res);
|
||||
});
|
||||
}
|
||||
|
||||
//* Handle unrouted requests and respond with proper error message as well as status code
|
||||
app.use((req, res, next) => {
|
||||
if (res.headersSent) return next();
|
||||
|
@ -44,6 +44,7 @@ export interface GetSecretParams {
|
||||
export interface UpdateSecretParams {
|
||||
secretName: string;
|
||||
newSecretName?: string;
|
||||
secretId?: string;
|
||||
secretKeyCiphertext?: string;
|
||||
secretKeyIV?: string;
|
||||
secretKeyTag?: string;
|
||||
|
@ -40,9 +40,9 @@ syncSecretsToThirdPartyServices.process(async (job: Job) => {
|
||||
const prefix = (integration.metadata?.secretPrefix || "");
|
||||
const suffix = (integration.metadata?.secretSuffix || "");
|
||||
const newKey = prefix + key + suffix;
|
||||
|
||||
|
||||
suffixedSecrets[newKey] = secrets[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const integrationAuth = await IntegrationAuth.findById(integration.integrationAuth);
|
||||
@ -67,7 +67,7 @@ syncSecretsToThirdPartyServices.process(async (job: Job) => {
|
||||
})
|
||||
|
||||
syncSecretsToThirdPartyServices.on("error", (error) => {
|
||||
console.log("QUEUE ERROR:", error) // eslint-disable-line
|
||||
// console.log("QUEUE ERROR:", error) // eslint-disable-line
|
||||
})
|
||||
|
||||
export const syncSecretsToActiveIntegrationsQueue = (jobDetails: TSyncSecretsToThirdPartyServices) => {
|
||||
|
@ -7,7 +7,7 @@ import { AuthMode } from "../../variables";
|
||||
router.post(
|
||||
"/",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN]
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY]
|
||||
}),
|
||||
secretImpsController.createSecretImp
|
||||
);
|
||||
@ -15,7 +15,7 @@ router.post(
|
||||
router.put(
|
||||
"/:id",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN]
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY]
|
||||
}),
|
||||
secretImpsController.updateSecretImport
|
||||
);
|
||||
@ -23,7 +23,7 @@ router.put(
|
||||
router.delete(
|
||||
"/:id",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN]
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY]
|
||||
}),
|
||||
secretImpsController.deleteSecretImport
|
||||
);
|
||||
@ -31,7 +31,7 @@ router.delete(
|
||||
router.get(
|
||||
"/",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN]
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY]
|
||||
}),
|
||||
secretImpsController.getSecretImports
|
||||
);
|
||||
@ -39,7 +39,7 @@ router.get(
|
||||
router.get(
|
||||
"/secrets",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN]
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY]
|
||||
}),
|
||||
secretImpsController.getAllSecretsFromImport
|
||||
);
|
||||
|
@ -12,7 +12,7 @@ import { AuthMode } from "../../variables";
|
||||
router.post(
|
||||
"/",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN]
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY]
|
||||
}),
|
||||
createFolder
|
||||
);
|
||||
@ -20,7 +20,7 @@ router.post(
|
||||
router.patch(
|
||||
"/:folderName",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN]
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY]
|
||||
}),
|
||||
updateFolderById
|
||||
);
|
||||
@ -28,7 +28,7 @@ router.patch(
|
||||
router.delete(
|
||||
"/:folderName",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN]
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY]
|
||||
}),
|
||||
deleteFolder
|
||||
);
|
||||
@ -36,7 +36,7 @@ router.delete(
|
||||
router.get(
|
||||
"/",
|
||||
requireAuth({
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN]
|
||||
acceptedAuthModes: [AuthMode.JWT, AuthMode.SERVICE_TOKEN, AuthMode.API_KEY]
|
||||
}),
|
||||
getFolders
|
||||
);
|
||||
|
@ -291,8 +291,7 @@ const initializePassport = async () => {
|
||||
});
|
||||
|
||||
interface ISAMLConfig {
|
||||
path: string;
|
||||
callbackURL: string;
|
||||
callbackUrl: string;
|
||||
entryPoint: string;
|
||||
issuer: string;
|
||||
cert: string;
|
||||
@ -301,8 +300,7 @@ const initializePassport = async () => {
|
||||
}
|
||||
|
||||
const samlConfig: ISAMLConfig = ({
|
||||
path: `${await getSiteURL()}/api/v1/sso/saml2/${ssoIdentifier}`,
|
||||
callbackURL: `${await getSiteURL()}/api/v1/sso/saml2${ssoIdentifier}`,
|
||||
callbackUrl: `${await getSiteURL()}/api/v1/sso/saml2/${ssoIdentifier}`,
|
||||
entryPoint: ssoConfig.entryPoint,
|
||||
issuer: ssoConfig.issuer,
|
||||
cert: ssoConfig.cert,
|
||||
@ -313,6 +311,12 @@ const initializePassport = async () => {
|
||||
samlConfig.wantAuthnResponseSigned = false;
|
||||
}
|
||||
|
||||
if (ssoConfig.authProvider.toString() === AuthMethod.AZURE_SAML.toString()) {
|
||||
if (req.body.RelayState && JSON.parse(req.body.RelayState).spInitiated) {
|
||||
samlConfig.audience = `spn:${ssoConfig.issuer}`;
|
||||
}
|
||||
}
|
||||
|
||||
req.ssoConfig = ssoConfig;
|
||||
|
||||
done(null, samlConfig);
|
||||
@ -405,7 +409,7 @@ const initializePassport = async () => {
|
||||
authMethod: req.ssoConfig.authProvider,
|
||||
isUserCompleted,
|
||||
...(req.body.RelayState ? {
|
||||
callbackPort: req.body.RelayState as string
|
||||
callbackPort: JSON.parse(req.body.RelayState).callbackPort as string
|
||||
} : {})
|
||||
},
|
||||
expiresIn: await getJwtProviderAuthLifetime(),
|
||||
|
@ -55,9 +55,6 @@ export const setup = async () => {
|
||||
// initializing global feature set
|
||||
await EELicenseService.initGlobalFeatureSet();
|
||||
|
||||
// initializing the database connection
|
||||
await DatabaseService.initDatabase(await getMongoURL());
|
||||
|
||||
await initializePassport();
|
||||
|
||||
// re-encrypt any data previously encrypted under server hex 128-bit ENCRYPTION_KEY
|
||||
|
@ -353,6 +353,7 @@ export const UpdateSecretByNameV3 = z.object({
|
||||
body: z.object({
|
||||
workspaceId: z.string().trim(),
|
||||
environment: z.string().trim(),
|
||||
secretId: z.string().trim().optional(),
|
||||
type: z.enum([SECRET_SHARED, SECRET_PERSONAL]),
|
||||
secretPath: z.string().trim().default("/"),
|
||||
secretValueCiphertext: z.string().trim(),
|
||||
|
7
cypress.config.js
Normal file
7
cypress.config.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
e2e: {
|
||||
baseUrl: 'http://localhost:8080',
|
||||
viewportWidth: 1480,
|
||||
viewportHeight: 920,
|
||||
},
|
||||
};
|
47
cypress/e2e/org-overview.cy.js
Normal file
47
cypress/e2e/org-overview.cy.js
Normal file
@ -0,0 +1,47 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
describe('organization Overview', () => {
|
||||
beforeEach(() => {
|
||||
cy.login(`test@localhost.local`, `testInfisical1`)
|
||||
})
|
||||
|
||||
const projectName = "projectY"
|
||||
|
||||
it('can`t create projects with empty names', () => {
|
||||
cy.get('.button').click()
|
||||
cy.get('input[placeholder="Type your project name"]').type('abc').clear()
|
||||
cy.intercept('*').as('anyRequest');
|
||||
cy.get('@anyRequest').should('not.exist');
|
||||
})
|
||||
|
||||
it('can delete a newly-created project', () => {
|
||||
// Create a project
|
||||
cy.get('.button').click()
|
||||
cy.get('input[placeholder="Type your project name"]').type(`${projectName}`)
|
||||
cy.contains('button', 'Create Project').click()
|
||||
cy.url().should('include', '/project')
|
||||
|
||||
// Delete a project
|
||||
cy.get(`[href^="/project/"][href$="/settings"] > a > .group`).click()
|
||||
cy.contains('button', `Delete ${projectName}`).click()
|
||||
cy.contains('button', 'Delete Project').should('have.attr', 'disabled')
|
||||
cy.get('input[placeholder="Type to delete..."]').type('confirm')
|
||||
cy.contains('button', 'Delete Project').should('not.have.attr', 'disabled')
|
||||
cy.url().then((currentUrl) => {
|
||||
let projectId = currentUrl.split("/")[4]
|
||||
cy.intercept('DELETE', `/api/v1/workspace/${projectId}`).as('deleteProject');
|
||||
cy.contains('button', 'Delete Project').click();
|
||||
cy.get('@deleteProject').should('have.property', 'response').and('have.property', 'statusCode', 200);
|
||||
})
|
||||
})
|
||||
|
||||
it('can display no projects', () => {
|
||||
cy.intercept('/api/v1/workspace', {
|
||||
body: {
|
||||
"workspaces": []
|
||||
},
|
||||
})
|
||||
cy.get('.border-mineshaft-700 > :nth-child(2)').should('have.text', 'You are not part of any projects in this organization yet. When you are, they will appear here.')
|
||||
})
|
||||
|
||||
})
|
24
cypress/e2e/org-settings.cy.js
Normal file
24
cypress/e2e/org-settings.cy.js
Normal file
@ -0,0 +1,24 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
describe('Organization Settings', () => {
|
||||
let orgId;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login(`test@localhost.local`, `testInfisical1`)
|
||||
cy.url().then((currentUrl) => {
|
||||
orgId = currentUrl.split("/")[4]
|
||||
cy.visit(`org/${orgId}/settings`)
|
||||
})
|
||||
})
|
||||
|
||||
it('can rename org', () => {
|
||||
cy.get('input[placeholder="Acme Corp"]').clear().type('ABC')
|
||||
|
||||
cy.intercept('PATCH', `/api/v1/organization/${orgId}/name`).as('renameOrg');
|
||||
cy.get('form.p-4 > .button').click()
|
||||
cy.get('@renameOrg').should('have.property', 'response').and('have.property', 'statusCode', 200);
|
||||
|
||||
cy.get('.pl-3').should("have.text", "ABC ")
|
||||
})
|
||||
|
||||
})
|
84
cypress/e2e/project-overview.cy.js
Normal file
84
cypress/e2e/project-overview.cy.js
Normal file
@ -0,0 +1,84 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
describe('Project Overview', () => {
|
||||
const projectName = "projectY"
|
||||
let projectId;
|
||||
let isFirstTest = true;
|
||||
|
||||
before(() => {
|
||||
cy.login(`test@localhost.local`, `testInfisical1`)
|
||||
|
||||
// Create a project
|
||||
cy.get('.button').click()
|
||||
cy.get('input[placeholder="Type your project name"]').type(`${projectName}`)
|
||||
cy.contains('button', 'Create Project').click()
|
||||
cy.url().should('include', '/project').then((currentUrl) => {
|
||||
projectId = currentUrl.split("/")[4]
|
||||
})
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
if (isFirstTest) {
|
||||
isFirstTest = false;
|
||||
return; // Skip the rest of the beforeEach for the first test
|
||||
}
|
||||
cy.login(`test@localhost.local`, `testInfisical1`)
|
||||
cy.visit(`/project/${projectId}/secrets/overview`)
|
||||
})
|
||||
|
||||
it('can create secrets', () => {
|
||||
cy.contains('button', 'Go to Development').click()
|
||||
cy.contains('button', 'Add a new secret').click()
|
||||
cy.get('input[placeholder="Type your secret name"]').type('SECRET_A')
|
||||
cy.contains('button', 'Create Secret').click()
|
||||
cy.get('.w-80 > .inline-flex > .input').should('have.value', 'SECRET_A')
|
||||
cy.get(':nth-child(6) > .button > .w-min').should('have.text', '1 Commit')
|
||||
})
|
||||
|
||||
it('can update secrets', () => {
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
cy.get('.overflow-auto > .relative > .absolute').type('VALUE_A')
|
||||
cy.get('.button.text-primary > .svg-inline--fa').click()
|
||||
cy.get(':nth-child(6) > .button > .w-min').should('have.text', '2 Commits')
|
||||
})
|
||||
|
||||
it('can`t create duplicate-name secrets', () => {
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
cy.contains('button', 'Add Secret').click()
|
||||
cy.get('input[placeholder="Type your secret name"]').type('SECRET_A')
|
||||
cy.intercept('POST', `/api/v3/secrets/SECRET_A`).as('createSecret');
|
||||
cy.contains('button', 'Create Secret').click()
|
||||
cy.get('@createSecret').should('have.property', 'response').and('have.property', 'statusCode', 400);
|
||||
})
|
||||
|
||||
it('can add another secret', () => {
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
cy.contains('button', 'Add Secret').click()
|
||||
cy.get('input[placeholder="Type your secret name"]').type('SECRET_B')
|
||||
cy.contains('button', 'Create Secret').click()
|
||||
cy.get(':nth-child(6) > .button > .w-min').should('have.text', '3 Commits')
|
||||
})
|
||||
|
||||
it('can delete a secret', () => {
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
// cy.get(':nth-child(3) > .shadow-none').trigger('mouseover')
|
||||
cy.get(':nth-child(3) > .shadow-none > .group > .h-10 > .border-red').click()
|
||||
cy.contains('button', 'Delete Secret').should('have.attr', 'disabled')
|
||||
cy.get('input[placeholder="Type to delete..."]').type('SECRET_B')
|
||||
cy.intercept('DELETE', `/api/v3/secrets/SECRET_B`).as('deleteSecret');
|
||||
cy.contains('button', 'Delete Secret').should('not.have.attr', 'disabled')
|
||||
cy.contains('button', 'Delete Secret').click();
|
||||
cy.get('@deleteSecret').should('have.property', 'response').and('have.property', 'statusCode', 200);
|
||||
})
|
||||
|
||||
it('can add a comment', () => {
|
||||
return;
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
// for some reason this hover does not want to work
|
||||
cy.get('.overflow-auto').trigger('mouseover').then(() => {
|
||||
cy.get('.shadow-none > .group > .pl-4 > .h-8 > button[aria-label="add-comment"]').should('be.visible').click()
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
})
|
5
cypress/fixtures/example.json
Normal file
5
cypress/fixtures/example.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
51
cypress/support/commands.js
Normal file
51
cypress/support/commands.js
Normal file
@ -0,0 +1,51 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
|
||||
Cypress.Commands.add('login', (username, password) => {
|
||||
cy.visit('/login')
|
||||
cy.get('input[placeholder="Enter your email..."]').type(username)
|
||||
cy.get('input[placeholder="Enter your password..."]').type(password)
|
||||
cy.contains('Continue with Email').click()
|
||||
cy.url().should('include', '/overview')
|
||||
|
||||
// Need to make this work for CSRF tokens; Cypress has an example in the docs
|
||||
// cy.session(
|
||||
// username,
|
||||
// () => {
|
||||
// cy.visit('/login')
|
||||
// cy.get('input[placeholder="Enter your email..."]').type(username)
|
||||
// cy.get('input[placeholder="Enter your password..."]').type(password)
|
||||
// cy.contains('Continue with Email').click()
|
||||
// cy.url().should('include', '/overview')
|
||||
// },
|
||||
// {
|
||||
// validate: () => {
|
||||
// cy.getCookie('jid').should('exist')
|
||||
// },
|
||||
// }
|
||||
// )
|
||||
})
|
||||
|
20
cypress/support/e2e.js
Normal file
20
cypress/support/e2e.js
Normal file
@ -0,0 +1,20 @@
|
||||
// ***********************************************************
|
||||
// This example support/e2e.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
@ -1,46 +1,20 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
nginx:
|
||||
container_name: infisical-nginx
|
||||
image: nginx
|
||||
restart: always
|
||||
ports:
|
||||
- 80:80
|
||||
- 443:443
|
||||
volumes:
|
||||
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
depends_on:
|
||||
- frontend
|
||||
- backend
|
||||
networks:
|
||||
- infisical
|
||||
|
||||
backend:
|
||||
container_name: infisical-backend
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- mongo
|
||||
image: infisical/backend
|
||||
image: infisical/infisical:latest
|
||||
env_file: .env
|
||||
ports:
|
||||
- 80:8080
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
networks:
|
||||
- infisical
|
||||
|
||||
frontend:
|
||||
container_name: infisical-frontend
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- backend
|
||||
image: infisical/frontend
|
||||
env_file: .env
|
||||
environment:
|
||||
# - NEXT_PUBLIC_POSTHOG_API_KEY=${POSTHOG_PROJECT_API_KEY}
|
||||
- INFISICAL_TELEMETRY_ENABLED=${TELEMETRY_ENABLED}
|
||||
networks:
|
||||
- infisical
|
||||
|
||||
redis:
|
||||
image: redis
|
||||
container_name: infisical-dev-redis
|
||||
|
@ -63,12 +63,17 @@ description: "Configure Azure SAML for Infisical SSO"
|
||||
|
||||
7. Get IdP values:
|
||||
|
||||
Back in the **Set up Single Sign-On with SAML** screen, copy the **Login URL**, **Azure AD Identifier** and **SAML Certificate** to use when finishing configuring Azure SAML in Infisical.
|
||||
In the **Set up Single Sign-On with SAML** screen, copy the **Login URL** and **SAML Certificate** to use when finishing configuring Azure SAML in Infisical.
|
||||
|
||||
Back in Infisical, set **Login URL** and **Azure AD Identifier** from above. Once you've done that, press **Update** to complete the required configuration.
|
||||

|
||||
|
||||

|
||||

|
||||
In the **Properties** screen, copy the **Application ID** to use when finishing configuring Azure SAML in Infisical.
|
||||
|
||||

|
||||
|
||||
Back in Infisical, set **Login URL**, **Azure Application ID**, and **SAML Certificate** from above. Once you've done that, press **Update** to complete the required configuration.
|
||||
|
||||

|
||||
|
||||
<Note>
|
||||
When pasting the certificate into Infisical, you'll want to retain `-----BEGIN
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 521 KiB After Width: | Height: | Size: 1.1 MiB |
BIN
docs/images/sso/azure/idp-values-3.png
Normal file
BIN
docs/images/sso/azure/idp-values-3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 MiB |
@ -3,7 +3,7 @@ title: "All environment variables"
|
||||
description: "Configure your environment variables when self-hosting Infisical."
|
||||
---
|
||||
|
||||
## Backend environment variables
|
||||
## Environment variables
|
||||
|
||||
Depending on your chosen self hosted deployment method, you may need to configured at least the required environment variable listed below.
|
||||
Other environment variables are listed below to increase the functionality of your self hosted instance based on your use case.
|
||||
@ -232,12 +232,3 @@ Infisical uses Sentry to report error logs
|
||||
<ParamField query="TELEMETRY_ENABLED" type="string" default="true" optional></ParamField>
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## Frontend environment variables
|
||||
|
||||
<ParamField
|
||||
query="TELEMETRY_ENABLED"
|
||||
type="string"
|
||||
default="true"
|
||||
optional
|
||||
></ParamField>
|
||||
|
@ -31,7 +31,7 @@ primary_region = "iad"
|
||||
MONGO_URL = <>
|
||||
|
||||
[http_service]
|
||||
internal_port = 80
|
||||
internal_port = 8080
|
||||
|
||||
```
|
||||
|
||||
|
@ -23,40 +23,27 @@ helm repo update
|
||||
|
||||
## Add Helm values
|
||||
|
||||
Create a values.yaml file to configure various installation settings, such as the docker image tags and environment variables for both the frontend and backend. To explore all configurable properties for your values file, [visit this page](https://github.com/Infisical/infisical/tree/main/helm-charts/infisical).
|
||||
Create a values.yaml file to configure various installation settings, such as the docker image tags and environment variables. To explore all configurable properties for your values file, [visit this page](https://github.com/Infisical/infisical/tree/main/helm-charts/infisical).
|
||||
|
||||
#### Set image tags
|
||||
|
||||
By default, the application will use the latest tag to retrieve the required Docker images, which may be appropriate for most cases.
|
||||
However, it's important to specify a particular version of Infisical during installation to prevent any significant updates from disrupting your deployment.
|
||||
View [properties for frontend and backend](https://github.com/Infisical/infisical/tree/main/helm-charts/infisical#parameters).
|
||||
|
||||
By default, the application will use the `latest` docker image tag. This is okay for test environments; however, for production deployments it is important to pin your deployment to a particular docker image tag to prevent receiving unintended changes.
|
||||
<Tip>
|
||||
To find the latest version number of Infisical, follow the links below
|
||||
- [frontend Docker image](https://hub.docker.com/r/infisical/frontend/tags)
|
||||
- [backend Docker image](https://hub.docker.com/r/infisical/backend/tags)
|
||||
To find the latest version number of Infisical, click [here](https://hub.docker.com/r/infisical/infisical/tags)
|
||||
</Tip>
|
||||
|
||||
```yaml simple-values-example.yaml
|
||||
frontend:
|
||||
name: frontend
|
||||
replicaCount: 2
|
||||
image:
|
||||
repository: infisical/frontend
|
||||
tag: "v0.34.2" # <--- frontend version
|
||||
pullPolicy: Always
|
||||
|
||||
backend:
|
||||
replicaCount: 2
|
||||
image:
|
||||
repository: infisical/backend
|
||||
tag: "v0.34.2" # <--- backend version
|
||||
repository: infisical/infisical
|
||||
tag: "v0.39.5"
|
||||
pullPolicy: Always
|
||||
```
|
||||
|
||||
#### Configure environment variables
|
||||
|
||||
You can configure environment variables for the frontend and backend in your Helm values file under the property `frontendEnvironmentVariables` and `backendEnvironmentVariables` respectively. View configurable [environment variables](../configuration/envars).
|
||||
You can configure environment variables for your instance of Infisical though the Helm values file under the property `backendEnvironmentVariables`. View configurable [environment variables](../configuration/envars).
|
||||
|
||||
Infisical requires the following backend environment variables to be defined: _`ENCRYPTION_KEY`_, _`JWT_SIGNUP_SECRET`_, _`JWT_REFRESH_SECRET`_, _`JWT_AUTH_SECRET`_, _`JWT_MFA_SECRET`_ and _`JWT_SERVICE_SECRET`_.
|
||||
|
||||
@ -87,38 +74,30 @@ Infisical uses Nginx to route external traffic. You can install Nginx along with
|
||||
...
|
||||
ingress:
|
||||
nginx:
|
||||
enabled: false #<-- if you would like to install nginx along with Infisical
|
||||
enabled: true #<-- if you would like to install nginx along with Infisical
|
||||
```
|
||||
|
||||
#### Database
|
||||
Infisical uses a document database as its persistence layer. With this Helm chart, you spin up a MongoDB instance power by Bitnami along side other Infisical services in your cluster.
|
||||
Infisical uses a MongoDB as its persistence layer. With this Helm chart, a MongoDB instance is automatically spun up for use with Infisical.
|
||||
When persistence is enabled, the data will be stored as Kubernetes Persistence Volume. View all [properties for mongodb](https://github.com/Infisical/infisical/tree/main/helm-charts/infisical).
|
||||
|
||||
```yaml simple-values-example.yaml
|
||||
mongodb:
|
||||
enabled: false
|
||||
enabled: true
|
||||
persistence:
|
||||
enabled: false
|
||||
```
|
||||
|
||||
To increase data redundancy, we recommend that you use a managed document database service such as AWS Document DB, MongoDB or similar services instead.
|
||||
To achieve high availability and data redundancy, we recommend that you use a managed document database service such as AWS Document DB, MongoDB or similar services instead of the in cluster database.
|
||||
Managed database connection string can be set in the `backendEnvironmentVariables`.
|
||||
|
||||
#### Example helm values
|
||||
```yaml simple-values-example.yaml
|
||||
frontend:
|
||||
name: frontend
|
||||
replicaCount: 2
|
||||
image:
|
||||
repository: infisical/frontend
|
||||
tag: "v0.34.2" # <--- frontend version
|
||||
pullPolicy: Always
|
||||
|
||||
backend:
|
||||
replicaCount: 2
|
||||
image:
|
||||
repository: infisical/backend
|
||||
tag: "v0.34.2" # <--- backend version
|
||||
repository: infisical/infisical
|
||||
tag: "v0.39.5"
|
||||
pullPolicy: Always
|
||||
|
||||
backendEnvironmentVariables:
|
||||
@ -126,7 +105,7 @@ backendEnvironmentVariables:
|
||||
|
||||
ingress:
|
||||
nginx:
|
||||
enabled: true #<-- if you would like to install nginx along with Infisical
|
||||
enabled: true
|
||||
|
||||
```
|
||||
|
||||
@ -136,22 +115,6 @@ ingress:
|
||||
nginx:
|
||||
enabled: true
|
||||
|
||||
frontend:
|
||||
enabled: true
|
||||
name: frontend
|
||||
podAnnotations: {}
|
||||
deploymentAnnotations: {}
|
||||
replicaCount: 4
|
||||
image:
|
||||
repository: infisical/frontend
|
||||
tag: "v0.34.2" # <--- frontend version
|
||||
pullPolicy: IfNotPresent
|
||||
kubeSecretRef: null
|
||||
service:
|
||||
annotations: {}
|
||||
type: ClusterIP
|
||||
nodePort: ""
|
||||
|
||||
backend:
|
||||
enabled: true
|
||||
name: backend
|
||||
@ -159,8 +122,8 @@ ingress:
|
||||
deploymentAnnotations: {}
|
||||
replicaCount: 4
|
||||
image:
|
||||
repository: infisical/backend
|
||||
tag: "v0.34.2" # <--- backend version
|
||||
repository: infisical/infisical
|
||||
tag: "v0.39.5"
|
||||
pullPolicy: IfNotPresent
|
||||
kubeSecretRef: null
|
||||
service:
|
||||
@ -176,26 +139,9 @@ ingress:
|
||||
|
||||
## Mongo DB persistence
|
||||
mongodb:
|
||||
enabled: false
|
||||
persistence:
|
||||
enabled: false
|
||||
|
||||
ingress:
|
||||
enabled: true
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: "letsencrypt-prod" # <-- if you are setting up HTTPS
|
||||
hostName: app.infisical.com ## <- Replace with your own domain
|
||||
frontend:
|
||||
path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
path: /api
|
||||
pathType: Prefix
|
||||
tls: # <-- if you are setting up HTTPS
|
||||
- secretName: echo-tls
|
||||
hosts:
|
||||
- app.infisical.com
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
|
@ -58,7 +58,7 @@ Add the required environment variables listed below to your docker run command.
|
||||
Once you have added the required environment variables to your docker run command, execute it in your terminal.
|
||||
|
||||
```bash
|
||||
docker run -p 80:80 \
|
||||
docker run -p 80:8080 \
|
||||
-e ENCRYPTION_KEY=f40c9178624764ad85a6830b37ce239a \
|
||||
-e JWT_SIGNUP_SECRET=38ea90fb7998b92176080f457d890392 \
|
||||
-e JWT_REFRESH_SECRET=7764c7bbf3928ad501591a3e005eb364 \
|
||||
|
@ -1,32 +0,0 @@
|
||||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: 'frontend',
|
||||
script: "./scripts/start.sh",
|
||||
instances: 1,
|
||||
cwd: "./app",
|
||||
interpreter: 'sh',
|
||||
exec_mode: "fork",
|
||||
autorestart: true,
|
||||
watch: false,
|
||||
max_memory_restart: '500M',
|
||||
},
|
||||
{
|
||||
name: 'backend',
|
||||
script: 'npm',
|
||||
args: 'run start',
|
||||
cwd: "./backend",
|
||||
instances: 1,
|
||||
exec_mode: "fork",
|
||||
autorestart: true,
|
||||
watch: false,
|
||||
max_memory_restart: '500M',
|
||||
},
|
||||
{
|
||||
name: "nginx",
|
||||
script: "nginx",
|
||||
args: "-g 'daemon off;'",
|
||||
exec_interpreter: "none",
|
||||
},
|
||||
],
|
||||
};
|
@ -96,7 +96,7 @@ module.exports = {
|
||||
}
|
||||
]
|
||||
},
|
||||
ignorePatterns: ["next.config.js"],
|
||||
ignorePatterns: ["next.config.js", "cypress/**/*.js", "cypress.config.js"],
|
||||
settings: {
|
||||
"import/resolver": {
|
||||
typescript: {
|
||||
|
7
frontend/cypress.config.js
Normal file
7
frontend/cypress.config.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
e2e: {
|
||||
baseUrl: 'http://localhost:8080',
|
||||
viewportWidth: 1480,
|
||||
viewportHeight: 920,
|
||||
},
|
||||
};
|
47
frontend/cypress/e2e/org-overview.cy.js
Normal file
47
frontend/cypress/e2e/org-overview.cy.js
Normal file
@ -0,0 +1,47 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
describe('organization Overview', () => {
|
||||
beforeEach(() => {
|
||||
cy.login(`test@localhost.local`, `testInfisical1`)
|
||||
})
|
||||
|
||||
const projectName = "projectY"
|
||||
|
||||
it('can`t create projects with empty names', () => {
|
||||
cy.get('.button').click()
|
||||
cy.get('input[placeholder="Type your project name"]').type('abc').clear()
|
||||
cy.intercept('*').as('anyRequest');
|
||||
cy.get('@anyRequest').should('not.exist');
|
||||
})
|
||||
|
||||
it('can delete a newly-created project', () => {
|
||||
// Create a project
|
||||
cy.get('.button').click()
|
||||
cy.get('input[placeholder="Type your project name"]').type(`${projectName}`)
|
||||
cy.contains('button', 'Create Project').click()
|
||||
cy.url().should('include', '/project')
|
||||
|
||||
// Delete a project
|
||||
cy.get(`[href^="/project/"][href$="/settings"] > a > .group`).click()
|
||||
cy.contains('button', `Delete ${projectName}`).click()
|
||||
cy.contains('button', 'Delete Project').should('have.attr', 'disabled')
|
||||
cy.get('input[placeholder="Type to delete..."]').type('confirm')
|
||||
cy.contains('button', 'Delete Project').should('not.have.attr', 'disabled')
|
||||
cy.url().then((currentUrl) => {
|
||||
let projectId = currentUrl.split("/")[4]
|
||||
cy.intercept('DELETE', `/api/v1/workspace/${projectId}`).as('deleteProject');
|
||||
cy.contains('button', 'Delete Project').click();
|
||||
cy.get('@deleteProject').should('have.property', 'response').and('have.property', 'statusCode', 200);
|
||||
})
|
||||
})
|
||||
|
||||
it('can display no projects', () => {
|
||||
cy.intercept('/api/v1/workspace', {
|
||||
body: {
|
||||
"workspaces": []
|
||||
},
|
||||
})
|
||||
cy.get('.border-mineshaft-700 > :nth-child(2)').should('have.text', 'You are not part of any projects in this organization yet. When you are, they will appear here.')
|
||||
})
|
||||
|
||||
})
|
24
frontend/cypress/e2e/org-settings.cy.js
Normal file
24
frontend/cypress/e2e/org-settings.cy.js
Normal file
@ -0,0 +1,24 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
describe('Organization Settings', () => {
|
||||
let orgId;
|
||||
|
||||
beforeEach(() => {
|
||||
cy.login(`test@localhost.local`, `testInfisical1`)
|
||||
cy.url().then((currentUrl) => {
|
||||
orgId = currentUrl.split("/")[4]
|
||||
cy.visit(`org/${orgId}/settings`)
|
||||
})
|
||||
})
|
||||
|
||||
it('can rename org', () => {
|
||||
cy.get('input[placeholder="Acme Corp"]').clear().type('ABC')
|
||||
|
||||
cy.intercept('PATCH', `/api/v1/organization/${orgId}/name`).as('renameOrg');
|
||||
cy.get('form.p-4 > .button').click()
|
||||
cy.get('@renameOrg').should('have.property', 'response').and('have.property', 'statusCode', 200);
|
||||
|
||||
cy.get('.pl-3').should("have.text", "ABC ")
|
||||
})
|
||||
|
||||
})
|
84
frontend/cypress/e2e/project-secret-operations.cy.js
Normal file
84
frontend/cypress/e2e/project-secret-operations.cy.js
Normal file
@ -0,0 +1,84 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
describe('Project Overview', () => {
|
||||
const projectName = "projectY"
|
||||
let projectId;
|
||||
let isFirstTest = true;
|
||||
|
||||
before(() => {
|
||||
cy.login(`test@localhost.local`, `testInfisical1`)
|
||||
|
||||
// Create a project
|
||||
cy.get('.button').click()
|
||||
cy.get('input[placeholder="Type your project name"]').type(`${projectName}`)
|
||||
cy.contains('button', 'Create Project').click()
|
||||
cy.url().should('include', '/project').then((currentUrl) => {
|
||||
projectId = currentUrl.split("/")[4]
|
||||
})
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
if (isFirstTest) {
|
||||
isFirstTest = false;
|
||||
return; // Skip the rest of the beforeEach for the first test
|
||||
}
|
||||
cy.login(`test@localhost.local`, `testInfisical1`)
|
||||
cy.visit(`/project/${projectId}/secrets/overview`)
|
||||
})
|
||||
|
||||
it('can create secrets', () => {
|
||||
cy.contains('button', 'Go to Development').click()
|
||||
cy.contains('button', 'Add a new secret').click()
|
||||
cy.get('input[placeholder="Type your secret name"]').type('SECRET_A')
|
||||
cy.contains('button', 'Create Secret').click()
|
||||
cy.get('.w-80 > .inline-flex > .input').should('have.value', 'SECRET_A')
|
||||
cy.get(':nth-child(6) > .button > .w-min').should('have.text', '1 Commit')
|
||||
})
|
||||
|
||||
it('can update secrets', () => {
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
cy.get('.overflow-auto > .relative > .absolute').type('VALUE_A')
|
||||
cy.get('.button.text-primary > .svg-inline--fa').click()
|
||||
cy.get(':nth-child(6) > .button > .w-min').should('have.text', '2 Commits')
|
||||
})
|
||||
|
||||
it('can`t create duplicate-name secrets', () => {
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
cy.contains('button', 'Add Secret').click()
|
||||
cy.get('input[placeholder="Type your secret name"]').type('SECRET_A')
|
||||
cy.intercept('POST', `/api/v3/secrets/SECRET_A`).as('createSecret');
|
||||
cy.contains('button', 'Create Secret').click()
|
||||
cy.get('@createSecret').should('have.property', 'response').and('have.property', 'statusCode', 400);
|
||||
})
|
||||
|
||||
it('can add another secret', () => {
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
cy.contains('button', 'Add Secret').click()
|
||||
cy.get('input[placeholder="Type your secret name"]').type('SECRET_B')
|
||||
cy.contains('button', 'Create Secret').click()
|
||||
cy.get(':nth-child(6) > .button > .w-min').should('have.text', '3 Commits')
|
||||
})
|
||||
|
||||
it('can delete a secret', () => {
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
// cy.get(':nth-child(3) > .shadow-none').trigger('mouseover')
|
||||
cy.get(':nth-child(3) > .shadow-none > .group > .h-10 > .border-red').click()
|
||||
cy.contains('button', 'Delete Secret').should('have.attr', 'disabled')
|
||||
cy.get('input[placeholder="Type to delete..."]').type('SECRET_B')
|
||||
cy.intercept('DELETE', `/api/v3/secrets/SECRET_B`).as('deleteSecret');
|
||||
cy.contains('button', 'Delete Secret').should('not.have.attr', 'disabled')
|
||||
cy.contains('button', 'Delete Secret').click();
|
||||
cy.get('@deleteSecret').should('have.property', 'response').and('have.property', 'statusCode', 200);
|
||||
})
|
||||
|
||||
it('can add a comment', () => {
|
||||
return;
|
||||
cy.get(':nth-child(2) > .flex > .button').click()
|
||||
// for some reason this hover does not want to work
|
||||
cy.get('.overflow-auto').trigger('mouseover').then(() => {
|
||||
cy.get('.shadow-none > .group > .pl-4 > .h-8 > button[aria-label="add-comment"]').should('be.visible').click()
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
})
|
5
frontend/cypress/fixtures/example.json
Normal file
5
frontend/cypress/fixtures/example.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
19
frontend/cypress/support/commands.js
Normal file
19
frontend/cypress/support/commands.js
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
Cypress.Commands.add('login', (username, password) => {
|
||||
cy.visit('/login')
|
||||
cy.get('input[placeholder="Enter your email..."]').type(username)
|
||||
cy.get('input[placeholder="Enter your password..."]').type(password)
|
||||
cy.contains('Continue with Email').click()
|
||||
cy.url().should('include', '/overview')
|
||||
})
|
||||
|
||||
// Cypress.Commands.add('login', (username, password) => {
|
||||
// cy.session([username, password], () => {
|
||||
// cy.visit('/login')
|
||||
// cy.get('input[placeholder="Enter your email..."]').type(username)
|
||||
// cy.get('input[placeholder="Enter your password..."]').type(password)
|
||||
// cy.contains('Continue with Email').click()
|
||||
// cy.url().should('include', '/overview')
|
||||
// cy.wait(2000);
|
||||
// })
|
||||
// })
|
20
frontend/cypress/support/e2e.js
Normal file
20
frontend/cypress/support/e2e.js
Normal file
@ -0,0 +1,20 @@
|
||||
// ***********************************************************
|
||||
// This example support/e2e.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
@ -1,8 +1,4 @@
|
||||
// @ts-check
|
||||
|
||||
/**
|
||||
* @type {import('next').NextConfig}
|
||||
**/
|
||||
const path = require("path");
|
||||
|
||||
const ContentSecurityPolicy = `
|
||||
@ -53,7 +49,9 @@ const securityHeaders = [
|
||||
value: ContentSecurityPolicy.replace(/\s{2,}/g, " ").trim()
|
||||
}
|
||||
];
|
||||
|
||||
/**
|
||||
* @type {import('next').NextConfig}
|
||||
**/
|
||||
module.exports = {
|
||||
output: "standalone",
|
||||
i18n: {
|
||||
|
1922
frontend/package-lock.json
generated
1922
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -124,6 +124,7 @@
|
||||
"@typescript-eslint/eslint-plugin": "^5.48.1",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"cypress": "^13.3.2",
|
||||
"eslint": "^8.32.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-airbnb-typescript": "^17.0.0",
|
||||
|
13
frontend/scripts/initialize-standalone-build.sh
Executable file
13
frontend/scripts/initialize-standalone-build.sh
Executable file
@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
scripts/replace-standalone-build-variable.sh "$BAKED_NEXT_PUBLIC_POSTHOG_API_KEY" "$NEXT_PUBLIC_POSTHOG_API_KEY"
|
||||
|
||||
scripts/replace-standalone-build-variable.sh "$BAKED_NEXT_PUBLIC_INTERCOM_ID" "$NEXT_PUBLIC_INTERCOM_ID"
|
||||
|
||||
if [ "$TELEMETRY_ENABLED" != "false" ]; then
|
||||
echo "Telemetry is enabled"
|
||||
scripts/set-standalone-build-telemetry.sh true
|
||||
else
|
||||
echo "Client opted out of telemetry"
|
||||
scripts/set-standalone-build-telemetry.sh false
|
||||
fi
|
16
frontend/scripts/replace-standalone-build-variable.sh
Executable file
16
frontend/scripts/replace-standalone-build-variable.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
ORIGINAL=$1
|
||||
REPLACEMENT=$2
|
||||
|
||||
if [ "${ORIGINAL}" = "${REPLACEMENT}" ]; then
|
||||
echo "Environment variable replacement is the same, skipping.."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Replacing pre-baked value.."
|
||||
|
||||
find public .next -type f -name "*.js" |
|
||||
while read file; do
|
||||
sed -i "s|$ORIGINAL|$REPLACEMENT|g" "$file"
|
||||
done
|
0
frontend/scripts/replace-variable.sh
Normal file → Executable file
0
frontend/scripts/replace-variable.sh
Normal file → Executable file
8
frontend/scripts/set-standalone-build-telemetry.sh
Normal file
8
frontend/scripts/set-standalone-build-telemetry.sh
Normal file
@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
VALUE=$1
|
||||
|
||||
find public .next -type f -name "*.js" |
|
||||
while read file; do
|
||||
sed -i "s|TELEMETRY_CAPTURING_ENABLED|$VALUE|g" "$file"
|
||||
done
|
0
frontend/scripts/set-telemetry.sh
Normal file → Executable file
0
frontend/scripts/set-telemetry.sh
Normal file → Executable file
@ -10,7 +10,7 @@ export const initPostHog = () => {
|
||||
try {
|
||||
if (typeof window !== "undefined") {
|
||||
// @ts-ignore
|
||||
if (ENV === "production" && TELEMETRY_CAPTURING_ENABLED) {
|
||||
if (ENV === "production" && TELEMETRY_CAPTURING_ENABLED === "true") {
|
||||
posthog.init(POSTHOG_API_KEY, {
|
||||
api_host: POSTHOG_HOST
|
||||
});
|
||||
|
@ -13,7 +13,7 @@ class Capturer {
|
||||
}
|
||||
|
||||
capture(item: string) {
|
||||
if (ENV === 'production' && TELEMETRY_CAPTURING_ENABLED) {
|
||||
if (ENV === 'production' && TELEMETRY_CAPTURING_ENABLED === "true") {
|
||||
try {
|
||||
this.api.capture(item);
|
||||
} catch (error) {
|
||||
@ -23,7 +23,7 @@ class Capturer {
|
||||
}
|
||||
|
||||
identify(id: string, email?: string) {
|
||||
if (ENV === 'production' && TELEMETRY_CAPTURING_ENABLED) {
|
||||
if (ENV === 'production' && TELEMETRY_CAPTURING_ENABLED === "true") {
|
||||
try {
|
||||
this.api.identify(id, {
|
||||
email: email
|
||||
|
@ -15,6 +15,7 @@ type Props = {
|
||||
title: string;
|
||||
subTitle?: string;
|
||||
onDeleteApproved: () => Promise<void>;
|
||||
buttonText?: string;
|
||||
};
|
||||
|
||||
export const DeleteActionModal = ({
|
||||
@ -24,7 +25,8 @@ export const DeleteActionModal = ({
|
||||
deleteKey,
|
||||
onDeleteApproved,
|
||||
title,
|
||||
subTitle = "This action is irreversible!"
|
||||
subTitle = "This action is irreversible!",
|
||||
buttonText = "Delete"
|
||||
}: Props): JSX.Element => {
|
||||
const [inputData, setInputData] = useState("");
|
||||
const [isLoading, setIsLoading] = useToggle();
|
||||
@ -56,7 +58,7 @@ export const DeleteActionModal = ({
|
||||
title={title}
|
||||
subTitle={subTitle}
|
||||
footerContent={
|
||||
<div className="flex items-center">
|
||||
<div className="flex items-center mx-2">
|
||||
<Button
|
||||
className="mr-4"
|
||||
colorSchema="danger"
|
||||
@ -64,7 +66,7 @@ export const DeleteActionModal = ({
|
||||
onClick={onDelete}
|
||||
isLoading={isLoading}
|
||||
>
|
||||
Delete
|
||||
{buttonText}
|
||||
</Button>
|
||||
<ModalClose asChild>
|
||||
<Button variant="plain" colorSchema="secondary" onClick={onClose}>
|
||||
@ -87,9 +89,9 @@ export const DeleteActionModal = ({
|
||||
Type <span className="font-bold">{deleteKey}</span> to delete the resource
|
||||
</div>
|
||||
}
|
||||
className="mb-4"
|
||||
className="mb-0"
|
||||
>
|
||||
<Input value={inputData} onChange={(e) => setInputData(e.target.value)} />
|
||||
<Input value={inputData} onChange={(e) => setInputData(e.target.value)} placeholder="Type to delete..." />
|
||||
</FormControl>
|
||||
</form>
|
||||
</ModalContent>
|
||||
|
@ -131,6 +131,7 @@ export const useUpdateSecretV3 = ({
|
||||
mutationFn: async ({
|
||||
secretPath = "/",
|
||||
type,
|
||||
secretId,
|
||||
environment,
|
||||
workspaceId,
|
||||
secretName,
|
||||
@ -157,6 +158,7 @@ export const useUpdateSecretV3 = ({
|
||||
environment,
|
||||
type,
|
||||
secretPath,
|
||||
secretId,
|
||||
...encryptSecret(randomBytes, newSecretName ?? secretName, secretValue, secretComment),
|
||||
tags,
|
||||
skipMultilineEncoding,
|
||||
|
@ -109,6 +109,7 @@ export type TUpdateSecretsV3DTO = {
|
||||
skipMultilineEncoding?: boolean;
|
||||
newSecretName?: string;
|
||||
secretName: string;
|
||||
secretId?: string;
|
||||
secretValue: string;
|
||||
secretComment?: string;
|
||||
tags?: string[];
|
||||
|
@ -692,7 +692,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
|
||||
{infisicalPlatformVersion && (
|
||||
<div className="mb-2 w-full pl-5 duration-200 hover:text-mineshaft-200">
|
||||
<FontAwesomeIcon icon={faInfo} className="mr-4 px-[0.1rem]" />
|
||||
Platform Version: {infisicalPlatformVersion}
|
||||
Version: {infisicalPlatformVersion}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -239,7 +239,7 @@ export const SecretMainPage = () => {
|
||||
onClickRollbackMode={() => handlePopUpToggle("snapshots", true)}
|
||||
/>
|
||||
<div className="mt-3 overflow-y-auto overflow-x-hidden thin-scrollbar bg-mineshaft-800 text-left text-bunker-300 rounded-md text-sm">
|
||||
<div className="flex flex-col ">
|
||||
<div className="flex flex-col" id="dashboard">
|
||||
{isNotEmtpy && (
|
||||
<div className="flex font-medium border-b border-mineshaft-600">
|
||||
<div style={{ width: "2.8rem" }} className="px-4 py-3 flex-shrink-0" />
|
||||
|
@ -289,7 +289,7 @@ export const ActionBar = ({
|
||||
className="h-10"
|
||||
isDisabled={!isAllowed}
|
||||
>
|
||||
{snapshotCount} Commits
|
||||
{`${snapshotCount} ${snapshotCount === 1 ? "Commit" : "Commits"}`}
|
||||
</Button>
|
||||
)}
|
||||
</ProjectPermissionCan>
|
||||
|
@ -105,7 +105,7 @@ export const CreateSecretForm = ({
|
||||
>
|
||||
<SecretInput
|
||||
{...field}
|
||||
containerClassName="text-bunker-300 hover:border-primary-400/50 border border-mineshaft-600 bg-mineshaft-900 px-2 py-1.5"
|
||||
containerClassName="text-bunker-300 hover:border-primary-400/50 border border-mineshaft-600 bg-mineshaft-900 px-2 py-1.5"
|
||||
/>
|
||||
</FormControl>
|
||||
)}
|
||||
|
@ -153,6 +153,7 @@ export const SecretListView = ({
|
||||
workspaceId,
|
||||
secretPath,
|
||||
secretName: key,
|
||||
secretId,
|
||||
secretValue: value || "",
|
||||
type,
|
||||
latestFileKey: decryptFileKey,
|
||||
@ -201,11 +202,14 @@ export const SecretListView = ({
|
||||
try {
|
||||
// personal secret change
|
||||
if (overrideAction === "deleted") {
|
||||
await handleSecretOperation("delete", "personal", oldKey);
|
||||
await handleSecretOperation("delete", "personal", oldKey, {
|
||||
secretId: orgSecret.idOverride
|
||||
});
|
||||
} else if (overrideAction && idOverride) {
|
||||
await handleSecretOperation("update", "personal", oldKey, {
|
||||
value: valueOverride,
|
||||
newKey: hasKeyChanged ? key : undefined,
|
||||
secretId: orgSecret.idOverride,
|
||||
skipMultilineEncoding: modSecret.skipMultilineEncoding
|
||||
});
|
||||
} else if (overrideAction) {
|
||||
@ -218,6 +222,7 @@ export const SecretListView = ({
|
||||
value,
|
||||
tags: tagIds,
|
||||
comment,
|
||||
secretId: orgSecret._id,
|
||||
newKey: hasKeyChanged ? key : undefined,
|
||||
skipMultilineEncoding: modSecret.skipMultilineEncoding
|
||||
});
|
||||
@ -308,7 +313,6 @@ export const SecretListView = ({
|
||||
>
|
||||
{namespace}
|
||||
</div>
|
||||
|
||||
{filteredSecrets.map((secret) => (
|
||||
<SecretItem
|
||||
environment={environment}
|
||||
@ -335,6 +339,7 @@ export const SecretListView = ({
|
||||
title="Do you want to delete this secret?"
|
||||
onChange={(isOpen) => handlePopUpToggle("deleteSecret", isOpen)}
|
||||
onDeleteApproved={handleSecretDelete}
|
||||
buttonText="Delete Secret"
|
||||
/>
|
||||
<SecretDetailSidebar
|
||||
environment={environment}
|
||||
|
@ -146,12 +146,13 @@ export const SecretOverviewPage = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleSecretUpdate = async (env: string, key: string, value: string) => {
|
||||
const handleSecretUpdate = async (env: string, key: string, value: string, secretId?: string) => {
|
||||
try {
|
||||
await updateSecretV3({
|
||||
environment: env,
|
||||
workspaceId,
|
||||
secretPath,
|
||||
secretId,
|
||||
secretName: key,
|
||||
secretValue: value,
|
||||
type: "shared",
|
||||
@ -242,7 +243,6 @@ export const SecretOverviewPage = () => {
|
||||
);
|
||||
|
||||
const canViewOverviewPage = Boolean(userAvailableEnvs.length);
|
||||
|
||||
const filteredSecretNames = secKeys
|
||||
?.filter((name) => name.toUpperCase().includes(searchFilter.toUpperCase()))
|
||||
.sort((a, b) => (sortDir === "asc" ? a.localeCompare(b) : b.localeCompare(a)));
|
||||
|
@ -18,7 +18,7 @@ type Props = {
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
onSecretCreate: (env: string, key: string, value: string) => Promise<void>;
|
||||
onSecretUpdate: (env: string, key: string, value: string) => Promise<void>;
|
||||
onSecretUpdate: (env: string, key: string, value: string, secretId?: string) => Promise<void>;
|
||||
onSecretDelete: (env: string, key: string, secretId?: string) => Promise<void>;
|
||||
};
|
||||
|
||||
@ -42,7 +42,7 @@ export const SecretEditRow = ({
|
||||
formState: { isDirty, isSubmitting }
|
||||
} = useForm({
|
||||
values: {
|
||||
value: defaultValue
|
||||
value: defaultValue || null
|
||||
}
|
||||
});
|
||||
const [isDeleting, setIsDeleting] = useToggle();
|
||||
@ -70,7 +70,7 @@ export const SecretEditRow = ({
|
||||
if (isCreatable) {
|
||||
await onSecretCreate(environment, secretName, value);
|
||||
} else {
|
||||
await onSecretUpdate(environment, secretName, value);
|
||||
await onSecretUpdate(environment, secretName, value, secretId);
|
||||
}
|
||||
}
|
||||
reset({ value });
|
||||
@ -80,7 +80,7 @@ export const SecretEditRow = ({
|
||||
setIsDeleting.on();
|
||||
try {
|
||||
await onSecretDelete(environment, secretName, secretId);
|
||||
reset({ value: undefined });
|
||||
reset({ value: null });
|
||||
} finally {
|
||||
setIsDeleting.off();
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ type Props = {
|
||||
expandableColWidth: number;
|
||||
getSecretByKey: (slug: string, key: string) => DecryptedSecret | undefined;
|
||||
onSecretCreate: (env: string, key: string, value: string) => Promise<void>;
|
||||
onSecretUpdate: (env: string, key: string, value: string) => Promise<void>;
|
||||
onSecretUpdate: (env: string, key: string, value: string, secretId?: string) => Promise<void>;
|
||||
onSecretDelete: (env: string, key: string, secretId?: string) => Promise<void>;
|
||||
};
|
||||
|
||||
|
@ -143,8 +143,8 @@ export const SSOModal = ({
|
||||
entityId: "Identifier (Entity ID)",
|
||||
entryPoint: "Login URL",
|
||||
entryPointPlaceholder: "https://login.microsoftonline.com/xxx/saml2",
|
||||
issuer: "Azure AD Identifier",
|
||||
issuerPlaceholder: "https://sts.windows.net/xxx/"
|
||||
issuer: "Azure Application ID",
|
||||
issuerPlaceholder: "abc-def-ghi-jkl-mno"
|
||||
});
|
||||
case AuthProvider.JUMPCLOUD_SAML:
|
||||
return ({
|
||||
|
@ -10,7 +10,7 @@ export const OrgGeneralTab = () => {
|
||||
const { user } = useUser();
|
||||
const { data: members } = useGetOrgUsers(currentOrg?._id ?? "");
|
||||
|
||||
const membershipOrg = members?.find((member) => member.user._id === user._id);
|
||||
const membershipOrg = members?.find((member) => member.user._id === user?._id);
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -77,9 +77,10 @@ export const DeleteProjectSection = () => {
|
||||
<DeleteActionModal
|
||||
isOpen={popUp.deleteWorkspace.isOpen}
|
||||
title="Are you sure want to delete this project?"
|
||||
subTitle={`Permanently remove ${currentWorkspace?.name} and all of its data. This action is not reversible, so please be careful.`}
|
||||
subTitle={`Permanently delete ${currentWorkspace?.name} and all of its data. This action is not reversible, so please be careful.`}
|
||||
onChange={(isOpen) => handlePopUpToggle("deleteWorkspace", isOpen)}
|
||||
deleteKey="confirm"
|
||||
buttonText="Delete Project"
|
||||
onDeleteApproved={handleDeleteWorkspaceSubmit}
|
||||
/>
|
||||
</div>
|
||||
|
@ -7,7 +7,7 @@ type: application
|
||||
# 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.3.5
|
||||
version: 0.4.1
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
|
@ -4,7 +4,6 @@ This is the Infisical application Helm chart. This chart includes the following
|
||||
|
||||
| Service | Description |
|
||||
| ---------- | ----------------------------------- |
|
||||
| `frontend` | Infisical's Web UI |
|
||||
| `backend` | Infisical's API |
|
||||
| `mongodb` | Infisical's database |
|
||||
| `redis` | Infisical's cache service |
|
||||
@ -59,28 +58,6 @@ kubectl get secrets -n <namespace> <secret-name> \
|
||||
| `nameOverride` | Override release name | `""` |
|
||||
| `fullnameOverride` | Override release fullname | `""` |
|
||||
|
||||
### Infisical frontend parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
||||
| `frontend.enabled` | Enable frontend | `true` |
|
||||
| `frontend.name` | Frontend name | `frontend` |
|
||||
| `frontend.fullnameOverride` | Frontend fullnameOverride | `""` |
|
||||
| `frontend.podAnnotations` | Frontend pod annotations | `{}` |
|
||||
| `frontend.deploymentAnnotations` | Frontend deployment annotations | `{}` |
|
||||
| `frontend.replicaCount` | Frontend replica count | `2` |
|
||||
| `frontend.image.repository` | Frontend image repository | `infisical/frontend` |
|
||||
| `frontend.image.tag` | Frontend image tag | `latest` |
|
||||
| `frontend.image.pullPolicy` | Frontend image pullPolicy | `IfNotPresent` |
|
||||
| `frontend.resources.limits.memory` | container memory limit [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) | `100Mi` |
|
||||
| `frontend.resources.requests.cpu` | container CPU request [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) | `100m` |
|
||||
| `frontend.affinity` | Frontend pod affinity | `{}` |
|
||||
| `frontend.kubeSecretRef` | Backend secret resource reference name (containing required [frontend configuration variables](https://infisical.com/docs/self-hosting/configuration/envars)) | `""` |
|
||||
| `frontend.service.annotations` | Backend service annotations | `{}` |
|
||||
| `frontend.service.type` | Backend service type | `ClusterIP` |
|
||||
| `frontend.service.nodePort` | Backend service nodePort (used if above type is `NodePort`) | `""` |
|
||||
| `frontendEnvironmentVariables.SITE_URL` | Absolute URL including the protocol (e.g. https://app.infisical.com) | `infisical.local` |
|
||||
|
||||
### Infisical backend parameters
|
||||
|
||||
| Name | Description | Value |
|
||||
@ -91,11 +68,9 @@ kubectl get secrets -n <namespace> <secret-name> \
|
||||
| `backend.podAnnotations` | Backend pod annotations | `{}` |
|
||||
| `backend.deploymentAnnotations` | Backend deployment annotations | `{}` |
|
||||
| `backend.replicaCount` | Backend replica count | `2` |
|
||||
| `backend.image.repository` | Backend image repository | `infisical/backend` |
|
||||
| `backend.image.repository` | Backend image repository | `infisical/infisical` |
|
||||
| `backend.image.tag` | Backend image tag | `latest` |
|
||||
| `backend.image.pullPolicy` | Backend image pullPolicy | `IfNotPresent` |
|
||||
| `backend.resources.limits.memory` | container memory limit [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) | `200Mi` |
|
||||
| `backend.resources.requests.cpu` | container CPU request [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) | `150m` |
|
||||
| `backend.affinity` | Backend pod affinity | `{}` |
|
||||
| `backend.kubeSecretRef` | Backend secret resource reference name (containing required [backend configuration variables](https://infisical.com/docs/self-hosting/configuration/envars)) | `""` |
|
||||
| `backend.service.annotations` | Backend service annotations | `{}` |
|
||||
@ -197,6 +172,7 @@ kubectl get secrets -n <namespace> <secret-name> \
|
||||
|
||||
|
||||
|
||||
|
||||
## Persistence
|
||||
|
||||
The database persistence is enabled by default, your volumes will remain on your cluster even after uninstalling the chart. To disable persistence, set this value `mongodb.persistence.enabled: false`
|
||||
|
@ -2,34 +2,6 @@
|
||||
|
||||
-- Infisical Helm Chart --
|
||||
|
||||
__ __
|
||||
( _) ( _)
|
||||
/ / \\ / /\_\_
|
||||
/ / \\ / / | \ \
|
||||
/ / \\ / / |\ \ \
|
||||
/ / , \ , / / /| \ \
|
||||
/ / |\_ /| / / / \ \_\
|
||||
/ / |\/ _ '_|\ / / / \ \\
|
||||
| / |/ 0 \0\\ / | | \ \\
|
||||
| |\| \_\_ / / | \ \\
|
||||
| | |/ \.\ o\o) / \ | \\
|
||||
\ | /\\`v-v / | | \\
|
||||
| \/ /_| \\_| / | | \ \\
|
||||
| | /__/_ / _____ | | \ \\
|
||||
\| [__] \_/ |_________ \ | \ ()
|
||||
/ [___] ( \ \ |\ | | //
|
||||
| [___] |\| \| / |/
|
||||
/| [____] \ |/\ / / ||
|
||||
( \ [____ / ) _\ \ \ \| | ||
|
||||
\ \ [_____| / / __/ \ / / //
|
||||
| \ [_____/ / / \ | \/ //
|
||||
| / '----| /=\____ _/ | / //
|
||||
__ / / | / ___/ _/\ \ | ||
|
||||
(/-(/-\) / \ (/\/\)/ | / | /
|
||||
(/\/\) / / //
|
||||
_________/ / /
|
||||
\____________/ (
|
||||
|
||||
██╗███╗ ██╗███████╗██╗███████╗██╗ ██████╗ █████╗ ██╗
|
||||
██║████╗ ██║██╔════╝██║██╔════╝██║██╔════╝██╔══██╗██║
|
||||
██║██╔██╗ ██║█████╗ ██║███████╗██║██║ ███████║██║
|
||||
@ -46,7 +18,6 @@
|
||||
│ Visit < https://infisical.com/docs/self-hosting/overview > for further documentation about self-hosting!
|
||||
│
|
||||
│ Current installation (infisical) :
|
||||
│ • infisical-frontend : {{ .Values.frontend.enabled }}
|
||||
│ • infisical-backend : {{ .Values.backend.enabled }}
|
||||
│ • mongodb : {{ .Values.mongodb.enabled }}
|
||||
│ • mailhog : {{ .Values.mailhog.enabled }}
|
||||
|
@ -41,16 +41,6 @@ component: {{ .Values.backend.name | quote }}
|
||||
{{ include "infisical.common.matchLabels" . }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "infisical.frontend.labels" -}}
|
||||
{{ include "infisical.frontend.matchLabels" . }}
|
||||
{{ include "infisical.common.metaLabels" . }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "infisical.frontend.matchLabels" -}}
|
||||
component: {{ .Values.frontend.name | quote }}
|
||||
{{ include "infisical.common.matchLabels" . }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "infisical.mongodb.labels" -}}
|
||||
{{ include "infisical.mongodb.matchLabels" . }}
|
||||
{{ include "infisical.common.metaLabels" . }}
|
||||
@ -78,22 +68,6 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create a fully qualified frontend name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
*/}}
|
||||
{{- define "infisical.frontend.fullname" -}}
|
||||
{{- if .Values.frontend.fullnameOverride -}}
|
||||
{{- .Values.frontend.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- if contains $name .Release.Name -}}
|
||||
{{- printf "%s-%s" .Release.Name .Values.frontend.name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s-%s-%s" .Release.Name $name .Values.frontend.name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create a fully qualified mongodb name.
|
||||
|
@ -36,17 +36,17 @@ spec:
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /api/status
|
||||
port: 4000
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
ports:
|
||||
- containerPort: 4000
|
||||
- containerPort: 8080
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ $backend.kubeSecretRef | default (include "infisical.backend.fullname" .) }}
|
||||
{{- if $backend.resources }}
|
||||
resources: {{- toYaml $backend.resources | nindent 12 }}
|
||||
{{- end }}
|
||||
# {{- if $backend.resources }}
|
||||
# resources: {{- toYaml $backend.resources | nindent 12 }}
|
||||
# {{- end }}
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
@ -65,8 +65,8 @@ spec:
|
||||
{{- include "infisical.backend.matchLabels" . | nindent 8 }}
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 4000
|
||||
targetPort: 4000 # container port
|
||||
port: 8080
|
||||
targetPort: 8080 # container port
|
||||
{{- if eq $backend.service.type "NodePort" }}
|
||||
nodePort: {{ $backend.service.nodePort }}
|
||||
{{- end }}
|
||||
|
@ -1,94 +0,0 @@
|
||||
{{- $frontend := .Values.frontend }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "infisical.frontend.fullname" . }}
|
||||
annotations:
|
||||
updatedAt: {{ now | date "2006-01-01 MST 15:04:05" | quote }}
|
||||
{{- with .Values.frontend.deploymentAnnotations }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "infisical.frontend.labels" . | nindent 4 }}
|
||||
spec:
|
||||
replicas: {{ $frontend.replicaCount }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "infisical.frontend.matchLabels" . | nindent 6 }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "infisical.frontend.matchLabels" . | nindent 8 }}
|
||||
annotations:
|
||||
updatedAt: {{ now | date "2006-01-01 MST 15:04:05" | quote }}
|
||||
{{- with $frontend.podAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- with $frontend.affinity }}
|
||||
affinity:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
- name: {{ template "infisical.name" . }}-{{ $frontend.name }}
|
||||
image: "{{ $frontend.image.repository }}:{{ $frontend.image.tag | default "latest" }}"
|
||||
imagePullPolicy: {{ $frontend.image.pullPolicy }}
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 3000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: {{ $frontend.kubeSecretRef | default (include "infisical.frontend.fullname" .) }}
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
{{- if $frontend.resources }}
|
||||
resources: {{- toYaml $frontend.resources | nindent 12 }}
|
||||
{{- end }}
|
||||
---
|
||||
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "infisical.frontend.fullname" . }}
|
||||
labels:
|
||||
{{- include "infisical.frontend.labels" . | nindent 4 }}
|
||||
{{- with $frontend.service.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
type: {{ $frontend.service.type }}
|
||||
selector:
|
||||
{{- include "infisical.frontend.matchLabels" . | nindent 8 }}
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 3000 # service
|
||||
targetPort: 3000 # container port
|
||||
{{- if eq $frontend.service.type "NodePort" }}
|
||||
nodePort: {{ $frontend.service.nodePort }}
|
||||
{{- end }}
|
||||
|
||||
---
|
||||
|
||||
{{ if not $frontend.kubeSecretRef }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "infisical.frontend.fullname" . }}
|
||||
annotations:
|
||||
"helm.sh/resource-policy": "keep"
|
||||
type: Opaque
|
||||
stringData:
|
||||
{{- $requiredVars := dict }}
|
||||
{{- $secretObj := (lookup "v1" "Secret" .Release.Namespace (include "infisical.frontend.fullname" .)) | default dict }}
|
||||
{{- $secretData := (get $secretObj "data") | default dict }}
|
||||
{{ range $key, $value := .Values.frontendEnvironmentVariables }}
|
||||
{{- $default := get $requiredVars $key -}}
|
||||
{{- $current := get $secretData $key | b64dec -}}
|
||||
{{- $v := $value | default ($current | default $default) -}}
|
||||
{{ $key }}: {{ $v | quote }}
|
||||
{{ end -}}
|
||||
{{- end }}
|
@ -30,27 +30,20 @@ spec:
|
||||
rules:
|
||||
- http:
|
||||
paths:
|
||||
- path: {{ $ingress.frontend.path }}
|
||||
pathType: {{ $ingress.frontend.pathType }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ include "infisical.frontend.fullname" . }}
|
||||
port:
|
||||
number: 3000
|
||||
- path: {{ $ingress.backend.path }}
|
||||
pathType: {{ $ingress.backend.pathType }}
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: {{ include "infisical.backend.fullname" . }}
|
||||
port:
|
||||
number: 4000
|
||||
number: 8080
|
||||
- path: /ss-webhook
|
||||
pathType: Exact
|
||||
backend:
|
||||
service:
|
||||
name: {{ include "infisical.backend.fullname" . }}
|
||||
port:
|
||||
number: 4000
|
||||
number: 8080
|
||||
{{- if $ingress.hostName }}
|
||||
host: {{ $ingress.hostName }}
|
||||
{{- end }}
|
||||
|
@ -8,76 +8,6 @@ nameOverride: ""
|
||||
##
|
||||
fullnameOverride: ""
|
||||
|
||||
## @section Infisical frontend parameters
|
||||
## Documentation : https://infisical.com/docs/self-hosting/deployments/kubernetes
|
||||
##
|
||||
|
||||
frontend:
|
||||
## @param frontend.enabled Enable frontend
|
||||
##
|
||||
enabled: true
|
||||
## @param frontend.name Frontend name
|
||||
##
|
||||
name: frontend
|
||||
## @param frontend.fullnameOverride Frontend fullnameOverride
|
||||
##
|
||||
fullnameOverride: ""
|
||||
## @param frontend.podAnnotations Frontend pod annotations
|
||||
##
|
||||
podAnnotations: {}
|
||||
## @param frontend.deploymentAnnotations Frontend deployment annotations
|
||||
##
|
||||
deploymentAnnotations: {}
|
||||
## @param frontend.replicaCount Frontend replica count
|
||||
##
|
||||
replicaCount: 2
|
||||
## Frontend image parameters
|
||||
##
|
||||
image:
|
||||
## @param frontend.image.repository Frontend image repository
|
||||
##
|
||||
repository: infisical/frontend
|
||||
## @param frontend.image.tag Frontend image tag
|
||||
##
|
||||
tag: "latest"
|
||||
## @param frontend.image.pullPolicy Frontend image pullPolicy
|
||||
##
|
||||
pullPolicy: IfNotPresent
|
||||
## @param frontend.resources.limits.memory container memory limit [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/)
|
||||
## @param frontend.resources.requests.cpu container CPU request [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/)
|
||||
##
|
||||
resources:
|
||||
limits:
|
||||
memory: 100Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
## @param frontend.affinity Frontend pod affinity
|
||||
##
|
||||
affinity: {}
|
||||
## @param frontend.kubeSecretRef Backend secret resource reference name (containing required [frontend configuration variables](https://infisical.com/docs/self-hosting/configuration/envars))
|
||||
##
|
||||
kubeSecretRef: ""
|
||||
## Frontend service
|
||||
##
|
||||
service:
|
||||
## @param frontend.service.annotations Backend service annotations
|
||||
##
|
||||
annotations: {}
|
||||
## @param frontend.service.type Backend service type
|
||||
##
|
||||
type: ClusterIP
|
||||
## @param frontend.service.nodePort Backend service nodePort (used if above type is `NodePort`)
|
||||
##
|
||||
nodePort: ""
|
||||
|
||||
## Frontend variables configuration
|
||||
## Documentation : https://infisical.com/docs/self-hosting/configuration/envars
|
||||
##
|
||||
frontendEnvironmentVariables:
|
||||
## @param frontendEnvironmentVariables.SITE_URL Absolute URL including the protocol (e.g. https://app.infisical.com)
|
||||
##
|
||||
SITE_URL: infisical.local
|
||||
|
||||
## @section Infisical backend parameters
|
||||
## Documentation : https://infisical.com/docs/self-hosting/deployments/kubernetes
|
||||
##
|
||||
@ -106,21 +36,13 @@ backend:
|
||||
image:
|
||||
## @param backend.image.repository Backend image repository
|
||||
##
|
||||
repository: infisical/backend
|
||||
repository: infisical/infisical
|
||||
## @param backend.image.tag Backend image tag
|
||||
##
|
||||
tag: "latest"
|
||||
## @param backend.image.pullPolicy Backend image pullPolicy
|
||||
##
|
||||
pullPolicy: IfNotPresent
|
||||
## @param backend.resources.limits.memory container memory limit [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/)
|
||||
## @param backend.resources.requests.cpu container CPU request [check the offical kubernetes documentations](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/)
|
||||
##
|
||||
resources:
|
||||
limits:
|
||||
memory: 200Mi
|
||||
requests:
|
||||
cpu: 150m
|
||||
## @param backend.affinity Backend pod affinity
|
||||
##
|
||||
affinity: {}
|
||||
@ -349,16 +271,6 @@ ingress:
|
||||
## Replace with your own domain
|
||||
##
|
||||
hostName: ""
|
||||
## @skip ingress.frontend
|
||||
##
|
||||
frontend:
|
||||
path: /
|
||||
pathType: Prefix
|
||||
## @skip ingress.backend
|
||||
##
|
||||
backend:
|
||||
path: /api
|
||||
pathType: Prefix
|
||||
## @param ingress.tls Ingress TLS hosts (matching above hostName)
|
||||
## Replace with your own domain
|
||||
##
|
||||
|
@ -1,36 +0,0 @@
|
||||
events {}
|
||||
http {
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
location /api {
|
||||
proxy_set_header X-Real-RIP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
|
||||
proxy_pass http://localhost:4000; # for backend
|
||||
proxy_redirect off;
|
||||
|
||||
# proxy_cookie_path / "/; secure; HttpOnly; SameSite=strict";
|
||||
proxy_cookie_path / "/; HttpOnly; SameSite=strict";
|
||||
}
|
||||
|
||||
location / {
|
||||
include /etc/nginx/mime.types;
|
||||
|
||||
proxy_set_header X-Real-RIP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-NginX-Proxy true;
|
||||
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
|
||||
proxy_pass http://localhost:3000; # for frontend
|
||||
proxy_redirect off;
|
||||
}
|
||||
}
|
||||
}
|
8
standalone-entrypoint.sh
Executable file
8
standalone-entrypoint.sh
Executable file
@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
cd frontend-build
|
||||
scripts/initialize-standalone-build.sh
|
||||
|
||||
cd ../
|
||||
|
||||
exec node build/index.js
|
Reference in New Issue
Block a user