mirror of
https://github.com/Infisical/infisical.git
synced 2025-06-29 04:31:59 +00:00
Compare commits
352 Commits
patch-4
...
infisical/
Author | SHA1 | Date | |
---|---|---|---|
bbf2634e73 | |||
1980f802fa | |||
6ecd289e6c | |||
b8a6f5dc54 | |||
dedbc4fd60 | |||
d14099990f | |||
3f5ab2a09e | |||
a191f437e9 | |||
1a375ec45b | |||
81f3a6a7a8 | |||
dc8b64708a | |||
dd3790c995 | |||
a91b6ebc03 | |||
e68d1d06a8 | |||
8f754d659a | |||
bef28fea2d | |||
28f15de8df | |||
66d258f02b | |||
d13eafcef7 | |||
6db47499de | |||
1cefb036e0 | |||
af77ad8b2f | |||
dd0f9f5216 | |||
29df6f067e | |||
4dc9a3692e | |||
49bb2121b9 | |||
07679d9318 | |||
fb271726fe | |||
f9e7d4ddd2 | |||
442c454932 | |||
8b22ee1fac | |||
8a10dc8983 | |||
d57920706a | |||
425611b409 | |||
b20489982d | |||
4b569ee4b4 | |||
af9661b221 | |||
53f16f01b8 | |||
f519d1cffc | |||
b8b28d2710 | |||
deab700716 | |||
4d184003a8 | |||
9849312317 | |||
79454a6aea | |||
8e0fb9fe9b | |||
a729114376 | |||
0c20cb0f91 | |||
d1597ed8da | |||
6cee8dc7e5 | |||
13040439c3 | |||
9a4f294749 | |||
2436a572f0 | |||
7cd21e3a93 | |||
e28416b50b | |||
9677836b76 | |||
ca858f8e13 | |||
c2beff493f | |||
34fafd815c | |||
c05ebbb864 | |||
372f2be2f3 | |||
23e621f557 | |||
464b80140f | |||
01cd496afe | |||
6094940a8b | |||
30b959babb | |||
cec14efe86 | |||
b3f090d87e | |||
1deb6827cf | |||
24dbf11962 | |||
20fb3906aa | |||
e7e2ca0f45 | |||
caabf2c952 | |||
35eade0206 | |||
6d1b79430d | |||
7864524944 | |||
adc90e91fe | |||
db7db0cc04 | |||
aa4d9ad267 | |||
27fd857120 | |||
205e46571a | |||
70a6a7cfa1 | |||
558315c24b | |||
a2bd808196 | |||
cfb0d4ee96 | |||
15fc4fd609 | |||
83bff9ae14 | |||
86ba6355cf | |||
6b427adfe0 | |||
01f711ad19 | |||
fa572f7ee0 | |||
249edf98e9 | |||
753a4daf69 | |||
b9320ed9bd | |||
8eace5528f | |||
9407c16e83 | |||
dcdcc40a4a | |||
edd78eaeba | |||
c21ea6fb75 | |||
a60dbe523b | |||
bb9a6b4272 | |||
eaca1b694a | |||
0afb44af29 | |||
3b39e38c89 | |||
4189d1028d | |||
f227824fb8 | |||
49d6918297 | |||
00212f1c72 | |||
987f0c9081 | |||
e4f00f74e9 | |||
ce580f417e | |||
c1662d6db5 | |||
2dae59c6be | |||
9bd764e535 | |||
e4f32f092a | |||
e02c082c7a | |||
80b6c4ad94 | |||
42eb01e1e2 | |||
b8157122e6 | |||
4f66749430 | |||
bfe5ee672b | |||
32a1a0a9e5 | |||
f7e1da65d5 | |||
6bf9bc1d2c | |||
59c747cf72 | |||
b04030a060 | |||
e8fd693da3 | |||
6c2803da93 | |||
4031f4a559 | |||
8ab89bc420 | |||
e46e87d758 | |||
9c2ef15314 | |||
3213dafba9 | |||
33c3c5ecc5 | |||
627c8711dc | |||
8d3d4f222f | |||
65d3038414 | |||
6b7b888fb4 | |||
bf059e0fe5 | |||
28fdf4ed4b | |||
2606e42079 | |||
b1285b401b | |||
3afafbb885 | |||
257547ff4d | |||
da4ae3c503 | |||
fb79e9e6fb | |||
5373cb6afb | |||
31c0bf6831 | |||
67618046c0 | |||
df642179ba | |||
c7d0f2325c | |||
bb6d482ff9 | |||
4f619d7e48 | |||
295c1e5d4a | |||
0be3ad9517 | |||
606ed25104 | |||
c880a48749 | |||
92f7b45e01 | |||
5fe8bdc00b | |||
9f813d72f2 | |||
d90fdac5ce | |||
87709dc86f | |||
deb8e74749 | |||
3519412639 | |||
0506389ada | |||
dd7c449483 | |||
c7572a3374 | |||
fe416556f2 | |||
20fb99f042 | |||
daa94db874 | |||
850e7bff98 | |||
bfaf87c4c2 | |||
55f1392faf | |||
0bf658e501 | |||
aed94ff5bb | |||
0d3f09d668 | |||
16f0ac6d43 | |||
6e6a1c87f2 | |||
b5aa6c0000 | |||
784cdb4201 | |||
17e61bfc68 | |||
a6a60b7bbb | |||
d154f68a59 | |||
f5159583ae | |||
771bec6d6d | |||
010963a80c | |||
0e1191f2ea | |||
8a6ab7f2f6 | |||
4f3582a98b | |||
498a90c484 | |||
76e5d61da5 | |||
53bb3bc610 | |||
1df7b88abf | |||
3670b16657 | |||
9a4b2f7d81 | |||
fadb36edb8 | |||
fbe5a1adb0 | |||
d0695a8998 | |||
a19e8ad016 | |||
15b57de0ed | |||
aaba4a0895 | |||
f3b37de3f3 | |||
fcfd6b3fb2 | |||
05205d1eff | |||
2243bcb3a4 | |||
356e981401 | |||
5b41fb0ff5 | |||
8893aec213 | |||
c4cb8f8008 | |||
046557c97f | |||
a15ba28c18 | |||
8386f4dcbd | |||
ada0fd9c5b | |||
6376c29e49 | |||
402692614e | |||
34de6d4e29 | |||
829e906650 | |||
b7cbb0f1a8 | |||
a50ffbb59d | |||
48eda0c684 | |||
ed89413689 | |||
0c94f77a6d | |||
e6068826f8 | |||
cfa0a2044e | |||
134b503c28 | |||
efcbf1aa88 | |||
284c18db07 | |||
1410a44610 | |||
746ffb3840 | |||
f9f12eafdf | |||
11470a5a0e | |||
9fe2190115 | |||
9e2bd31833 | |||
e88b0ad3c4 | |||
74644fd8bb | |||
2069ac1554 | |||
5a2516e0a7 | |||
b52bc3bed7 | |||
4a153e5658 | |||
7324822be5 | |||
766f301aea | |||
8fbc930012 | |||
0e5190a920 | |||
b815e3eb56 | |||
31231cfcca | |||
ee772e4a77 | |||
7bc29c5981 | |||
e9a89930da | |||
b85499859c | |||
7f17194c0f | |||
1e1ad450d2 | |||
5287b322d8 | |||
45d96be1ff | |||
12840bfdbd | |||
fef5369738 | |||
c94b7d63f6 | |||
485ddc5c50 | |||
edd9c66e49 | |||
0a3b85534b | |||
ec2cc5162e | |||
7ce472957c | |||
8529e0da3d | |||
e5a5433f10 | |||
ee6e518ff8 | |||
15a7222505 | |||
25d482cc62 | |||
785a2bec6a | |||
449466f326 | |||
4131e9c3f1 | |||
310595256f | |||
1737880e58 | |||
b72483f5f2 | |||
ee14bda706 | |||
e56463d52b | |||
ebd3d7c7c4 | |||
9ecbfe201b | |||
ba2a03897f | |||
304f14c0ed | |||
51e5c25e16 | |||
0f6490b1e7 | |||
f894e48fcb | |||
37cfa22619 | |||
94557344b7 | |||
d5063018eb | |||
51d68505d3 | |||
ade27ad072 | |||
683c512bce | |||
43ff28b5fb | |||
ce41855e84 | |||
d24461b17c | |||
1797e56f9f | |||
74f3ca5356 | |||
db27beaf0b | |||
d6e55f51f2 | |||
e9b5996567 | |||
094fe73917 | |||
dc3f85e92e | |||
c463256058 | |||
8df22302fd | |||
f37fa2bbf5 | |||
597c9d6f2a | |||
24d2eea930 | |||
382cb910af | |||
6725475575 | |||
026864951b | |||
287ed05ab7 | |||
37b036e614 | |||
024914c168 | |||
19e8b6d37b | |||
b6d648f1f3 | |||
a514a62a29 | |||
2f24956651 | |||
13d058025c | |||
8ccaa7f29b | |||
b83964051c | |||
0a2b078bdc | |||
40d16fa996 | |||
a3739cfe50 | |||
a73623258e | |||
6da39f41a6 | |||
69bbbfcfd8 | |||
c9d58ec77d | |||
cb364186d8 | |||
918afe05b6 | |||
e822820151 | |||
b5ac49eefe | |||
b21d1a0ed2 | |||
70f1122362 | |||
ea03db8a2c | |||
38d9abca17 | |||
5bed2580c3 | |||
d0b899897b | |||
1861dc85de | |||
bc6bf33674 | |||
44fd35baf5 | |||
8ddfee4c36 | |||
4d0bff4377 | |||
c7b2489d0b | |||
68eb0f8dd9 | |||
5941e8e836 | |||
80e50d13ec | |||
99c8dda4e1 | |||
14c8e3fa3b | |||
7aa3cb53a2 | |||
567309e848 | |||
f264340903 | |||
51b788cc5b | |||
8e0f424249 | |||
f3767d3963 | |||
51cbfdbc46 | |||
f5a580eb72 | |||
460ebf3296 | |||
7f7f11c970 |
@ -3,6 +3,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- "infisical/v*.*.*"
|
- "infisical/v*.*.*"
|
||||||
|
- "!infisical/v*.*.*-postgres"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
backend-image:
|
backend-image:
|
||||||
|
57
.github/workflows/release-standalone-docker-img-postgres-offical.yml
vendored
Normal file
57
.github/workflows/release-standalone-docker-img-postgres-offical.yml
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
name: Release standalone docker image
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "infisical/v*.*.*-postgres"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
infisical-standalone:
|
||||||
|
name: Build infisical standalone image postgres
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Extract version from tag
|
||||||
|
id: extract_version
|
||||||
|
run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical/}"
|
||||||
|
- name: ☁️ Checkout source
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: 📦 Install dependencies to test all dependencies
|
||||||
|
run: npm ci --only-production
|
||||||
|
working-directory: backend
|
||||||
|
- name: version output
|
||||||
|
run: |
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.major }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.minor }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.patch }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.version }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.version_type }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.increment }}"
|
||||||
|
- 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 backend and export to Docker
|
||||||
|
uses: depot/build-push-action@v1
|
||||||
|
with:
|
||||||
|
project: 64mmf0n610
|
||||||
|
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||||
|
push: true
|
||||||
|
context: .
|
||||||
|
tags: |
|
||||||
|
infisical/infisical:latest-postgres
|
||||||
|
infisical/infisical:${{ steps.commit.outputs.short }}
|
||||||
|
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 }}
|
@ -3,6 +3,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- "infisical/v*.*.*"
|
- "infisical/v*.*.*"
|
||||||
|
- "!infisical/v*.*.*-postgres"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
infisical-standalone:
|
infisical-standalone:
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
# backend
|
# backend
|
||||||
node_modules
|
node_modules
|
||||||
.env
|
.env
|
||||||
|
.env.test
|
||||||
.env.dev
|
.env.dev
|
||||||
.env.gamma
|
.env.gamma
|
||||||
.env.prod
|
.env.prod
|
||||||
@ -61,4 +62,4 @@ yarn-error.log*
|
|||||||
# Editor specific
|
# Editor specific
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
|
||||||
frontend-build
|
frontend-build
|
||||||
|
@ -108,7 +108,7 @@ brews:
|
|||||||
zsh_completion.install "completions/infisical.zsh" => "_infisical"
|
zsh_completion.install "completions/infisical.zsh" => "_infisical"
|
||||||
fish_completion.install "completions/infisical.fish"
|
fish_completion.install "completions/infisical.fish"
|
||||||
man1.install "manpages/infisical.1.gz"
|
man1.install "manpages/infisical.1.gz"
|
||||||
- name: 'infisical@{{.Version}}'
|
- name: "infisical@{{.Version}}"
|
||||||
tap:
|
tap:
|
||||||
owner: Infisical
|
owner: Infisical
|
||||||
name: homebrew-get-cli
|
name: homebrew-get-cli
|
||||||
@ -186,12 +186,14 @@ aurs:
|
|||||||
# man pages
|
# man pages
|
||||||
install -Dm644 "./manpages/infisical.1.gz" "${pkgdir}/usr/share/man/man1/infisical.1.gz"
|
install -Dm644 "./manpages/infisical.1.gz" "${pkgdir}/usr/share/man/man1/infisical.1.gz"
|
||||||
|
|
||||||
# dockers:
|
dockers:
|
||||||
# - dockerfile: cli/docker/Dockerfile
|
- dockerfile: docker/alpine
|
||||||
# goos: linux
|
goos: linux
|
||||||
# goarch: amd64
|
goarch: amd64
|
||||||
# ids:
|
ids:
|
||||||
# - infisical
|
- all-other-builds
|
||||||
# image_templates:
|
image_templates:
|
||||||
# - "infisical/cli:{{ .Version }}"
|
- "infisical/cli:{{ .Version }}"
|
||||||
# - "infisical/cli:latest"
|
- "infisical/cli:{{ .Major }}.{{ .Minor }}"
|
||||||
|
- "infisical/cli:{{ .Major }}"
|
||||||
|
- "infisical/cli:latest"
|
||||||
|
@ -2,7 +2,7 @@ ARG POSTHOG_HOST=https://app.posthog.com
|
|||||||
ARG POSTHOG_API_KEY=posthog-api-key
|
ARG POSTHOG_API_KEY=posthog-api-key
|
||||||
ARG INTERCOM_ID=intercom-id
|
ARG INTERCOM_ID=intercom-id
|
||||||
|
|
||||||
FROM node:16-alpine AS base
|
FROM node:20-alpine AS base
|
||||||
|
|
||||||
FROM base AS frontend-dependencies
|
FROM base AS frontend-dependencies
|
||||||
|
|
||||||
@ -73,6 +73,7 @@ RUN npm ci --only-production
|
|||||||
|
|
||||||
COPY /backend .
|
COPY /backend .
|
||||||
COPY --chown=non-root-user:nodejs standalone-entrypoint.sh standalone-entrypoint.sh
|
COPY --chown=non-root-user:nodejs standalone-entrypoint.sh standalone-entrypoint.sh
|
||||||
|
RUN npm i -D tsconfig-paths
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# Production stage
|
# Production stage
|
||||||
@ -103,14 +104,17 @@ ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
|
|||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
COPY --from=backend-runner /app /backend
|
COPY --from=backend-runner /app /backend
|
||||||
|
COPY --from=backend-runner /app/dist/services/smtp/templates /backend/dist/templates
|
||||||
|
|
||||||
COPY --from=frontend-runner /app ./backend/frontend-build
|
COPY --from=frontend-runner /app ./backend/frontend-build
|
||||||
|
|
||||||
|
|
||||||
ENV PORT 8080
|
ENV PORT 8080
|
||||||
|
ENV HOST=0.0.0.0
|
||||||
ENV HTTPS_ENABLED false
|
ENV HTTPS_ENABLED false
|
||||||
ENV NODE_ENV production
|
ENV NODE_ENV production
|
||||||
ENV STANDALONE_BUILD true
|
ENV STANDALONE_BUILD true
|
||||||
|
ENV STANDALONE_MODE true
|
||||||
WORKDIR /backend
|
WORKDIR /backend
|
||||||
|
|
||||||
ENV TELEMETRY_ENABLED true
|
ENV TELEMETRY_ENABLED true
|
||||||
@ -119,10 +123,8 @@ HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \
|
|||||||
CMD node healthcheck.js
|
CMD node healthcheck.js
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
EXPOSE 443
|
||||||
|
|
||||||
USER non-root-user
|
USER non-root-user
|
||||||
|
|
||||||
CMD ["./standalone-entrypoint.sh"]
|
CMD ["./standalone-entrypoint.sh"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
3
Makefile
3
Makefile
@ -7,6 +7,9 @@ push:
|
|||||||
up-dev:
|
up-dev:
|
||||||
docker-compose -f docker-compose.dev.yml up --build
|
docker-compose -f docker-compose.dev.yml up --build
|
||||||
|
|
||||||
|
up-pg-dev:
|
||||||
|
docker compose -f docker-compose.pg.yml up --build
|
||||||
|
|
||||||
i-dev:
|
i-dev:
|
||||||
infisical run -- docker-compose -f docker-compose.dev.yml up --build
|
infisical run -- docker-compose -f docker-compose.dev.yml up --build
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ Note that this security address should be used only for undisclosed vulnerabilit
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Whether it's big or small, we love contributions. Check out our guide to see how to [get started](https://infisical.com/docs/contributing/overview).
|
Whether it's big or small, we love contributions. Check out our guide to see how to [get started](https://infisical.com/docs/contributing/getting-started).
|
||||||
|
|
||||||
Not sure where to get started? You can:
|
Not sure where to get started? You can:
|
||||||
|
|
||||||
|
11
backend-mongo/.dockerignore
Normal file
11
backend-mongo/.dockerignore
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
node_modules
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
Dockerfile
|
||||||
|
.dockerignore
|
||||||
|
docker-compose.*
|
||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
*~
|
2
backend-mongo/.eslintignore
Normal file
2
backend-mongo/.eslintignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
built
|
33
backend-mongo/Dockerfile
Normal file
33
backend-mongo/Dockerfile
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Build stage
|
||||||
|
FROM node:16-alpine AS build
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --only-production
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM node:16-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ENV npm_config_cache /home/node/.npm
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --only-production && npm cache clean --force
|
||||||
|
|
||||||
|
COPY --from=build /app .
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash curl && curl -1sLf \
|
||||||
|
'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash \
|
||||||
|
&& apk add infisical=0.8.1 && apk add --no-cache git
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \
|
||||||
|
CMD node healthcheck.js
|
||||||
|
|
||||||
|
EXPOSE 4000
|
||||||
|
|
||||||
|
CMD ["node", "build/index.js"]
|
Before Width: | Height: | Size: 493 KiB After Width: | Height: | Size: 493 KiB |
6
backend-mongo/nodemon.json
Normal file
6
backend-mongo/nodemon.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"watch": ["src"],
|
||||||
|
"ext": ".ts,.js",
|
||||||
|
"ignore": [],
|
||||||
|
"exec": "ts-node ./src/index.ts"
|
||||||
|
}
|
32861
backend-mongo/package-lock.json
generated
Normal file
32861
backend-mongo/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
148
backend-mongo/package.json
Normal file
148
backend-mongo/package.json
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"@aws-sdk/client-secrets-manager": "^3.319.0",
|
||||||
|
"@casl/ability": "^6.5.0",
|
||||||
|
"@casl/mongoose": "^7.2.1",
|
||||||
|
"@godaddy/terminus": "^4.12.0",
|
||||||
|
"@node-saml/passport-saml": "^4.0.4",
|
||||||
|
"@octokit/rest": "^19.0.5",
|
||||||
|
"@sentry/node": "^7.77.0",
|
||||||
|
"@sentry/tracing": "^7.48.0",
|
||||||
|
"@serdnam/pino-cloudwatch-transport": "^1.0.4",
|
||||||
|
"@types/crypto-js": "^4.1.1",
|
||||||
|
"@types/libsodium-wrappers": "^0.7.10",
|
||||||
|
"@ucast/mongo2js": "^1.3.4",
|
||||||
|
"ajv": "^8.12.0",
|
||||||
|
"argon2": "^0.30.3",
|
||||||
|
"aws-sdk": "^2.1364.0",
|
||||||
|
"axios": "^1.6.0",
|
||||||
|
"axios-retry": "^3.4.0",
|
||||||
|
"bcrypt": "^5.1.0",
|
||||||
|
"bigint-conversion": "^2.4.0",
|
||||||
|
"cookie-parser": "^1.4.6",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
|
"dotenv": "^16.0.1",
|
||||||
|
"express": "^4.18.1",
|
||||||
|
"express-async-errors": "^3.1.1",
|
||||||
|
"express-rate-limit": "^6.7.0",
|
||||||
|
"express-validator": "^6.14.2",
|
||||||
|
"handlebars": "^4.7.7",
|
||||||
|
"helmet": "^5.1.1",
|
||||||
|
"infisical-node": "^1.2.1",
|
||||||
|
"ioredis": "^5.3.2",
|
||||||
|
"jmespath": "^0.16.0",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
|
"jsonwebtoken": "^9.0.0",
|
||||||
|
"jsrp": "^0.2.4",
|
||||||
|
"libsodium-wrappers": "^0.7.10",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"mongoose": "^7.4.1",
|
||||||
|
"mysql2": "^3.6.2",
|
||||||
|
"nanoid": "^3.3.6",
|
||||||
|
"node-cache": "^5.1.2",
|
||||||
|
"nodemailer": "^6.8.0",
|
||||||
|
"ora": "^5.4.1",
|
||||||
|
"passport": "^0.6.0",
|
||||||
|
"passport-github": "^1.1.0",
|
||||||
|
"passport-gitlab2": "^5.0.0",
|
||||||
|
"passport-google-oauth20": "^2.0.0",
|
||||||
|
"pg": "^8.11.3",
|
||||||
|
"pino": "^8.16.1",
|
||||||
|
"pino-http": "^8.5.1",
|
||||||
|
"posthog-node": "^2.6.0",
|
||||||
|
"probot": "^12.3.3",
|
||||||
|
"query-string": "^7.1.3",
|
||||||
|
"rate-limit-mongo": "^2.3.2",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"swagger-ui-express": "^4.6.2",
|
||||||
|
"tweetnacl": "^1.0.3",
|
||||||
|
"tweetnacl-util": "^0.15.1",
|
||||||
|
"typescript": "^4.9.3",
|
||||||
|
"utility-types": "^3.10.0",
|
||||||
|
"zod": "^3.22.3"
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"rate-limit-mongo": {
|
||||||
|
"mongodb": "5.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "infisical-api",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "src/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node build/index.js",
|
||||||
|
"dev": "nodemon index.js",
|
||||||
|
"swagger-autogen": "node ./swagger/index.ts",
|
||||||
|
"build": "rimraf ./build && tsc && cp -R ./src/templates ./build && cp -R ./src/data ./build",
|
||||||
|
"lint": "eslint . --ext .ts",
|
||||||
|
"lint-and-fix": "eslint . --ext .ts --fix",
|
||||||
|
"lint-staged": "lint-staged",
|
||||||
|
"pretest": "docker compose -f test-resources/docker-compose.test.yml up -d",
|
||||||
|
"test": "cross-env NODE_ENV=test jest --verbose --testTimeout=10000 --detectOpenHandles; npm run posttest",
|
||||||
|
"test:ci": "npm test -- --watchAll=false --ci --reporters=default --reporters=jest-junit --reporters=github-actions --coverage --testLocationInResults --json --outputFile=coverage/report.json",
|
||||||
|
"posttest": "docker compose -f test-resources/docker-compose.test.yml down"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/Infisical/infisical-api.git"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/Infisical/infisical-api/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/Infisical/infisical-api#readme",
|
||||||
|
"description": "",
|
||||||
|
"devDependencies": {
|
||||||
|
"@jest/globals": "^29.3.1",
|
||||||
|
"@posthog/plugin-scaffold": "^1.3.4",
|
||||||
|
"@swc/core": "^1.3.99",
|
||||||
|
"@swc/helpers": "^0.5.3",
|
||||||
|
"@types/bcrypt": "^5.0.0",
|
||||||
|
"@types/bcryptjs": "^2.4.2",
|
||||||
|
"@types/bull": "^4.10.0",
|
||||||
|
"@types/cookie-parser": "^1.4.3",
|
||||||
|
"@types/cors": "^2.8.12",
|
||||||
|
"@types/express": "^4.17.14",
|
||||||
|
"@types/jest": "^29.5.0",
|
||||||
|
"@types/jmespath": "^0.15.1",
|
||||||
|
"@types/jsonwebtoken": "^8.5.9",
|
||||||
|
"@types/lodash": "^4.14.191",
|
||||||
|
"@types/node": "^18.11.3",
|
||||||
|
"@types/nodemailer": "^6.4.6",
|
||||||
|
"@types/passport": "^1.0.12",
|
||||||
|
"@types/pg": "^8.10.7",
|
||||||
|
"@types/picomatch": "^2.3.0",
|
||||||
|
"@types/pino": "^7.0.5",
|
||||||
|
"@types/supertest": "^2.0.12",
|
||||||
|
"@types/swagger-jsdoc": "^6.0.1",
|
||||||
|
"@types/swagger-ui-express": "^4.1.3",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
|
"@typescript-eslint/parser": "^5.40.1",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"eslint": "^8.26.0",
|
||||||
|
"eslint-plugin-unused-imports": "^2.0.0",
|
||||||
|
"install": "^0.13.0",
|
||||||
|
"jest": "^29.3.1",
|
||||||
|
"jest-junit": "^15.0.0",
|
||||||
|
"nodemon": "^2.0.19",
|
||||||
|
"npm": "^8.19.3",
|
||||||
|
"pino-pretty": "^10.2.3",
|
||||||
|
"regenerator-runtime": "^0.14.0",
|
||||||
|
"smee-client": "^1.2.3",
|
||||||
|
"supertest": "^6.3.3",
|
||||||
|
"swagger-autogen": "^2.23.5",
|
||||||
|
"ts-jest": "^29.0.3",
|
||||||
|
"ts-node": "^10.9.1"
|
||||||
|
},
|
||||||
|
"jest-junit": {
|
||||||
|
"outputDirectory": "reports",
|
||||||
|
"outputName": "jest-junit.xml",
|
||||||
|
"ancestorSeparator": " › ",
|
||||||
|
"uniqueOutputName": "false",
|
||||||
|
"suiteNameTemplate": "{filepath}",
|
||||||
|
"classNameTemplate": "{classname}",
|
||||||
|
"titleTemplate": "{title}"
|
||||||
|
}
|
||||||
|
}
|
@ -4962,7 +4962,8 @@
|
|||||||
},
|
},
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"apiKeyAuth": []
|
"apiKeyAuth": [],
|
||||||
|
"bearerAuth": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -6,6 +6,9 @@ export const client = new InfisicalClient({
|
|||||||
token: process.env.INFISICAL_TOKEN!
|
token: process.env.INFISICAL_TOKEN!
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const getIsMigrationMode = async () =>
|
||||||
|
(await client.getSecret("MIGRATION_MODE")).secretValue === "true";
|
||||||
|
|
||||||
export const getPort = async () => (await client.getSecret("PORT")).secretValue || 4000;
|
export const getPort = async () => (await client.getSecret("PORT")).secretValue || 4000;
|
||||||
export const getEncryptionKey = async () => {
|
export const getEncryptionKey = async () => {
|
||||||
const secretValue = (await client.getSecret("ENCRYPTION_KEY")).secretValue;
|
const secretValue = (await client.getSecret("ENCRYPTION_KEY")).secretValue;
|
@ -3,11 +3,11 @@ import { IServerConfig, ServerConfig } from "../models/serverConfig";
|
|||||||
let serverConfig: IServerConfig;
|
let serverConfig: IServerConfig;
|
||||||
|
|
||||||
export const serverConfigInit = async () => {
|
export const serverConfigInit = async () => {
|
||||||
const cfg = await ServerConfig.findOne({});
|
const cfg = await ServerConfig.findOne({}).lean();
|
||||||
if (!cfg) {
|
if (!cfg) {
|
||||||
const cfg = new ServerConfig();
|
const cfg = new ServerConfig();
|
||||||
await cfg.save();
|
await cfg.save();
|
||||||
serverConfig = cfg;
|
serverConfig = cfg.toObject();
|
||||||
} else {
|
} else {
|
||||||
serverConfig = cfg;
|
serverConfig = cfg;
|
||||||
}
|
}
|
||||||
@ -19,6 +19,6 @@ export const getServerConfig = () => serverConfig;
|
|||||||
export const updateServerConfig = async (data: Partial<IServerConfig>) => {
|
export const updateServerConfig = async (data: Partial<IServerConfig>) => {
|
||||||
const cfg = await ServerConfig.findByIdAndUpdate(serverConfig._id, data, { new: true });
|
const cfg = await ServerConfig.findByIdAndUpdate(serverConfig._id, data, { new: true });
|
||||||
if (!cfg) throw new Error("Failed to update server config");
|
if (!cfg) throw new Error("Failed to update server config");
|
||||||
serverConfig = cfg;
|
serverConfig = cfg.toObject();
|
||||||
return serverConfig;
|
return serverConfig;
|
||||||
};
|
};
|
@ -1,5 +1,5 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import { getHttpsEnabled } from "../../config";
|
import { getHttpsEnabled, getIsMigrationMode } from "../../config";
|
||||||
import { getServerConfig, updateServerConfig as setServerConfig } from "../../config/serverConfig";
|
import { getServerConfig, updateServerConfig as setServerConfig } from "../../config/serverConfig";
|
||||||
import { initializeDefaultOrg, issueAuthTokens } from "../../helpers";
|
import { initializeDefaultOrg, issueAuthTokens } from "../../helpers";
|
||||||
import { validateRequest } from "../../helpers/validation";
|
import { validateRequest } from "../../helpers/validation";
|
||||||
@ -8,9 +8,10 @@ import { TelemetryService } from "../../services";
|
|||||||
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
|
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
|
||||||
import * as reqValidator from "../../validation/admin";
|
import * as reqValidator from "../../validation/admin";
|
||||||
|
|
||||||
export const getServerConfigInfo = (_req: Request, res: Response) => {
|
export const getServerConfigInfo = async (_req: Request, res: Response) => {
|
||||||
const config = getServerConfig();
|
const config = getServerConfig();
|
||||||
return res.send({ config });
|
const isMigrationModeOn = await getIsMigrationMode();
|
||||||
|
return res.send({ config: { ...config, isMigrationModeOn } });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateServerConfig = async (req: Request, res: Response) => {
|
export const updateServerConfig = async (req: Request, res: Response) => {
|
@ -2,7 +2,7 @@ import { Request, Response } from "express";
|
|||||||
import { Types } from "mongoose";
|
import { Types } from "mongoose";
|
||||||
import { standardRequest } from "../../config/request";
|
import { standardRequest } from "../../config/request";
|
||||||
import { getApps, getTeams, revokeAccess } from "../../integrations";
|
import { getApps, getTeams, revokeAccess } from "../../integrations";
|
||||||
import { Bot, IntegrationAuth, Workspace } from "../../models";
|
import { Bot, IIntegrationAuth, Integration, IntegrationAuth, Workspace } from "../../models";
|
||||||
import { EventType } from "../../ee/models";
|
import { EventType } from "../../ee/models";
|
||||||
import { IntegrationService } from "../../services";
|
import { IntegrationService } from "../../services";
|
||||||
import { EEAuditLogService } from "../../ee/services";
|
import { EEAuditLogService } from "../../ee/services";
|
||||||
@ -130,7 +130,6 @@ export const oAuthExchange = async (req: Request, res: Response) => {
|
|||||||
export const saveIntegrationToken = async (req: Request, res: Response) => {
|
export const saveIntegrationToken = async (req: Request, res: Response) => {
|
||||||
// TODO: refactor
|
// TODO: refactor
|
||||||
// TODO: check if access token is valid for each integration
|
// TODO: check if access token is valid for each integration
|
||||||
let integrationAuth;
|
|
||||||
const {
|
const {
|
||||||
body: { workspaceId, integration, url, accessId, namespace, accessToken, refreshToken }
|
body: { workspaceId, integration, url, accessId, namespace, accessToken, refreshToken }
|
||||||
} = await validateRequest(reqValidator.SaveIntegrationAccessTokenV1, req);
|
} = await validateRequest(reqValidator.SaveIntegrationAccessTokenV1, req);
|
||||||
@ -152,31 +151,21 @@ export const saveIntegrationToken = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
if (!bot) throw new Error("Bot must be enabled to save integration access token");
|
if (!bot) throw new Error("Bot must be enabled to save integration access token");
|
||||||
|
|
||||||
integrationAuth = await IntegrationAuth.findOneAndUpdate(
|
let integrationAuth = await new IntegrationAuth({
|
||||||
{
|
workspace: new Types.ObjectId(workspaceId),
|
||||||
workspace: new Types.ObjectId(workspaceId),
|
integration,
|
||||||
integration
|
url,
|
||||||
},
|
namespace,
|
||||||
{
|
algorithm: ALGORITHM_AES_256_GCM,
|
||||||
workspace: new Types.ObjectId(workspaceId),
|
keyEncoding: ENCODING_SCHEME_UTF8,
|
||||||
integration,
|
...(integration === INTEGRATION_GCP_SECRET_MANAGER
|
||||||
url,
|
? {
|
||||||
namespace,
|
metadata: {
|
||||||
algorithm: ALGORITHM_AES_256_GCM,
|
authMethod: "serviceAccount"
|
||||||
keyEncoding: ENCODING_SCHEME_UTF8,
|
|
||||||
...(integration === INTEGRATION_GCP_SECRET_MANAGER
|
|
||||||
? {
|
|
||||||
metadata: {
|
|
||||||
authMethod: "serviceAccount"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
: {})
|
}
|
||||||
},
|
: {})
|
||||||
{
|
}).save();
|
||||||
new: true,
|
|
||||||
upsert: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// encrypt and save integration access details
|
// encrypt and save integration access details
|
||||||
if (refreshToken) {
|
if (refreshToken) {
|
||||||
@ -188,12 +177,12 @@ export const saveIntegrationToken = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
// encrypt and save integration access details
|
// encrypt and save integration access details
|
||||||
if (accessId || accessToken) {
|
if (accessId || accessToken) {
|
||||||
integrationAuth = await IntegrationService.setIntegrationAuthAccess({
|
integrationAuth = (await IntegrationService.setIntegrationAuthAccess({
|
||||||
integrationAuthId: integrationAuth._id.toString(),
|
integrationAuthId: integrationAuth._id.toString(),
|
||||||
accessId,
|
accessId,
|
||||||
accessToken,
|
accessToken,
|
||||||
accessExpiresAt: undefined
|
accessExpiresAt: undefined
|
||||||
});
|
})) as IIntegrationAuth;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!integrationAuth) throw new Error("Failed to save integration access token");
|
if (!integrationAuth) throw new Error("Failed to save integration access token");
|
||||||
@ -1208,13 +1197,64 @@ export const getIntegrationAuthTeamCityBuildConfigs = async (req: Request, res:
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all integration authorizations and integrations for workspace with id [workspaceId]
|
||||||
|
* with integration name [integration]
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const deleteIntegrationAuths = async (req: Request, res: Response) => {
|
||||||
|
const {
|
||||||
|
query: { integration, workspaceId }
|
||||||
|
} = await validateRequest(reqValidator.DeleteIntegrationAuthsV1, req);
|
||||||
|
|
||||||
|
const { permission } = await getAuthDataProjectPermissions({
|
||||||
|
authData: req.authData,
|
||||||
|
workspaceId: new Types.ObjectId(workspaceId)
|
||||||
|
});
|
||||||
|
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Delete,
|
||||||
|
ProjectPermissionSub.Integrations
|
||||||
|
);
|
||||||
|
|
||||||
|
const integrationAuths = await IntegrationAuth.deleteMany({
|
||||||
|
integration,
|
||||||
|
workspace: new Types.ObjectId(workspaceId)
|
||||||
|
});
|
||||||
|
|
||||||
|
const integrations = await Integration.deleteMany({
|
||||||
|
integration,
|
||||||
|
workspace: new Types.ObjectId(workspaceId)
|
||||||
|
});
|
||||||
|
|
||||||
|
await EEAuditLogService.createAuditLog(
|
||||||
|
req.authData,
|
||||||
|
{
|
||||||
|
type: EventType.UNAUTHORIZE_INTEGRATION,
|
||||||
|
metadata: {
|
||||||
|
integration
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
workspaceId: new Types.ObjectId(workspaceId)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
integrationAuths,
|
||||||
|
integrations
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete integration authorization with id [integrationAuthId]
|
* Delete integration authorization with id [integrationAuthId]
|
||||||
* @param req
|
* @param req
|
||||||
* @param res
|
* @param res
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const deleteIntegrationAuth = async (req: Request, res: Response) => {
|
export const deleteIntegrationAuthById = async (req: Request, res: Response) => {
|
||||||
const {
|
const {
|
||||||
params: { integrationAuthId }
|
params: { integrationAuthId }
|
||||||
} = await validateRequest(reqValidator.DeleteIntegrationAuthV1, req);
|
} = await validateRequest(reqValidator.DeleteIntegrationAuthV1, req);
|
@ -251,6 +251,21 @@ export const deleteIntegration = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!deletedIntegration) throw new Error("Failed to find integration");
|
if (!deletedIntegration) throw new Error("Failed to find integration");
|
||||||
|
|
||||||
|
const numOtherIntegrationsUsingSameAuth = await Integration.countDocuments({
|
||||||
|
integrationAuth: deletedIntegration.integrationAuth,
|
||||||
|
_id: {
|
||||||
|
$nin: [deletedIntegration._id]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (numOtherIntegrationsUsingSameAuth === 0) {
|
||||||
|
// no other integrations are using the same integration auth
|
||||||
|
// -> delete integration auth associated with the integration being deleted
|
||||||
|
await IntegrationAuth.deleteOne({
|
||||||
|
_id: deletedIntegration.integrationAuth
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await EEAuditLogService.createAuditLog(
|
await EEAuditLogService.createAuditLog(
|
||||||
req.authData,
|
req.authData,
|
@ -111,11 +111,17 @@ export const createSecretImp = async (req: Request, res: Response) => {
|
|||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
workspaceId: new Types.ObjectId(workspaceId)
|
workspaceId: new Types.ObjectId(workspaceId)
|
||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Create,
|
ProjectPermissionActions.Create,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: directory })
|
subject(ProjectPermissionSub.Secrets, { environment, secretPath: directory })
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Create,
|
||||||
|
subject(ProjectPermissionSub.Secrets, { environment: secretImport.environment, secretPath: secretImport.secretPath })
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const folders = await Folder.findOne({
|
const folders = await Folder.findOne({
|
||||||
@ -323,7 +329,7 @@ export const updateSecretImport = async (req: Request, res: Response) => {
|
|||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
workspaceId: importSecDoc.workspace
|
workspaceId: importSecDoc.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionActions.Edit,
|
||||||
subject(ProjectPermissionSub.Secrets, {
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
@ -331,6 +337,13 @@ export const updateSecretImport = async (req: Request, res: Response) => {
|
|||||||
secretPath
|
secretPath
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
secretImports.forEach(({ environment, secretPath }) => {
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Create,
|
||||||
|
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
|
||||||
|
);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const orderBefore = importSecDoc.imports;
|
const orderBefore = importSecDoc.imports;
|
||||||
@ -453,7 +466,7 @@ export const deleteSecretImport = async (req: Request, res: Response) => {
|
|||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
workspaceId: importSecDoc.workspace
|
workspaceId: importSecDoc.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Delete,
|
ProjectPermissionActions.Delete,
|
||||||
subject(ProjectPermissionSub.Secrets, {
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
@ -620,7 +633,7 @@ export const getAllSecretsFromImport = async (req: Request, res: Response) => {
|
|||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
workspaceId: new Types.ObjectId(workspaceId)
|
workspaceId: new Types.ObjectId(workspaceId)
|
||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionActions.Read,
|
||||||
subject(ProjectPermissionSub.Secrets, {
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
@ -677,7 +690,7 @@ export const getAllSecretsFromImport = async (req: Request, res: Response) => {
|
|||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
workspaceId: importSecDoc.workspace
|
workspaceId: importSecDoc.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionActions.Read,
|
||||||
subject(ProjectPermissionSub.Secrets, {
|
subject(ProjectPermissionSub.Secrets, {
|
@ -129,9 +129,14 @@ export const renewAccessToken = async (req: Request, res: Response) => {
|
|||||||
accessTokenTTL,
|
accessTokenTTL,
|
||||||
accessTokenLastRenewedAt,
|
accessTokenLastRenewedAt,
|
||||||
accessTokenMaxTTL,
|
accessTokenMaxTTL,
|
||||||
createdAt: accessTokenCreatedAt
|
createdAt: accessTokenCreatedAt,
|
||||||
|
accessTokenNumUses,
|
||||||
|
accessTokenNumUsesLimit
|
||||||
} = identityAccessToken;
|
} = identityAccessToken;
|
||||||
|
|
||||||
|
if (accessTokenNumUses >= accessTokenNumUsesLimit) {
|
||||||
|
throw BadRequestError({ message: "Unable to renew because access token number of uses limit reached" })
|
||||||
|
}
|
||||||
|
|
||||||
// ttl check
|
// ttl check
|
||||||
if (accessTokenTTL > 0) {
|
if (accessTokenTTL > 0) {
|
||||||
@ -545,7 +550,7 @@ export const attachIdentityUniversalAuth = async (req: Request, res: Response) =
|
|||||||
|
|
||||||
// validate trusted ips
|
// validate trusted ips
|
||||||
const reformattedClientSecretTrustedIps = clientSecretTrustedIps.map((clientSecretTrustedIp) => {
|
const reformattedClientSecretTrustedIps = clientSecretTrustedIps.map((clientSecretTrustedIp) => {
|
||||||
if (!plan.ipAllowlisting && clientSecretTrustedIp.ipAddress !== "0.0.0.0/0") return res.status(400).send({
|
if (!plan.ipAllowlisting && (clientSecretTrustedIp.ipAddress !== "0.0.0.0/0" && clientSecretTrustedIp.ipAddress !== "::/0")) return res.status(400).send({
|
||||||
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -559,7 +564,7 @@ export const attachIdentityUniversalAuth = async (req: Request, res: Response) =
|
|||||||
});
|
});
|
||||||
|
|
||||||
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
|
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
|
||||||
if (!plan.ipAllowlisting && accessTokenTrustedIp.ipAddress !== "0.0.0.0/0") return res.status(400).send({
|
if (!plan.ipAllowlisting && (accessTokenTrustedIp.ipAddress !== "0.0.0.0/0" && accessTokenTrustedIp.ipAddress !== "::/0")) return res.status(400).send({
|
||||||
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -745,7 +750,7 @@ export const updateIdentityUniversalAuth = async (req: Request, res: Response) =
|
|||||||
let reformattedClientSecretTrustedIps;
|
let reformattedClientSecretTrustedIps;
|
||||||
if (clientSecretTrustedIps) {
|
if (clientSecretTrustedIps) {
|
||||||
reformattedClientSecretTrustedIps = clientSecretTrustedIps.map((clientSecretTrustedIp) => {
|
reformattedClientSecretTrustedIps = clientSecretTrustedIps.map((clientSecretTrustedIp) => {
|
||||||
if (!plan.ipAllowlisting && clientSecretTrustedIp.ipAddress !== "0.0.0.0/0") return res.status(400).send({
|
if (!plan.ipAllowlisting && (clientSecretTrustedIp.ipAddress !== "0.0.0.0/0" && clientSecretTrustedIp.ipAddress !== "::/0")) return res.status(400).send({
|
||||||
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -762,7 +767,7 @@ export const updateIdentityUniversalAuth = async (req: Request, res: Response) =
|
|||||||
let reformattedAccessTokenTrustedIps;
|
let reformattedAccessTokenTrustedIps;
|
||||||
if (accessTokenTrustedIps) {
|
if (accessTokenTrustedIps) {
|
||||||
reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
|
reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
|
||||||
if (!plan.ipAllowlisting && accessTokenTrustedIp.ipAddress !== "0.0.0.0/0") return res.status(400).send({
|
if (!plan.ipAllowlisting && (accessTokenTrustedIp.ipAddress !== "0.0.0.0/0" && accessTokenTrustedIp.ipAddress !== "::/0")) return res.status(400).send({
|
||||||
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
||||||
});
|
});
|
||||||
|
|
@ -1,9 +1,13 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import { Types } from "mongoose";
|
import { Types } from "mongoose";
|
||||||
import {
|
import {
|
||||||
IdentityMembershipOrg,
|
IWorkspace,
|
||||||
Membership,
|
Identity,
|
||||||
|
IdentityMembership,
|
||||||
|
IdentityMembershipOrg,
|
||||||
|
Membership,
|
||||||
MembershipOrg,
|
MembershipOrg,
|
||||||
|
User,
|
||||||
Workspace
|
Workspace
|
||||||
} from "../../models";
|
} from "../../models";
|
||||||
import { Role } from "../../ee/models";
|
import { Role } from "../../ee/models";
|
||||||
@ -298,7 +302,8 @@ export const getOrganizationWorkspaces = async (req: Request, res: Response) =>
|
|||||||
#swagger.description = 'Return projects in organization that user is part of'
|
#swagger.description = 'Return projects in organization that user is part of'
|
||||||
|
|
||||||
#swagger.security = [{
|
#swagger.security = [{
|
||||||
"apiKeyAuth": []
|
"apiKeyAuth": [],
|
||||||
|
"bearerAuth": []
|
||||||
}]
|
}]
|
||||||
|
|
||||||
#swagger.parameters['organizationId'] = {
|
#swagger.parameters['organizationId'] = {
|
||||||
@ -326,6 +331,7 @@ export const getOrganizationWorkspaces = async (req: Request, res: Response) =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const {
|
const {
|
||||||
params: { organizationId }
|
params: { organizationId }
|
||||||
} = await validateRequest(reqValidator.GetOrgWorkspacesv2, req);
|
} = await validateRequest(reqValidator.GetOrgWorkspacesv2, req);
|
||||||
@ -351,13 +357,27 @@ export const getOrganizationWorkspaces = async (req: Request, res: Response) =>
|
|||||||
).map((w) => w._id.toString())
|
).map((w) => w._id.toString())
|
||||||
);
|
);
|
||||||
|
|
||||||
const workspaces = (
|
let workspaces: IWorkspace[] = [];
|
||||||
await Membership.find({
|
|
||||||
user: req.user._id
|
if (req.authData.authPayload instanceof Identity) {
|
||||||
}).populate("workspace")
|
workspaces = (
|
||||||
)
|
await IdentityMembership.find({
|
||||||
.filter((m) => workspacesSet.has(m.workspace._id.toString()))
|
identity: req.authData.authPayload._id
|
||||||
.map((m) => m.workspace);
|
}).populate<{ workspace: IWorkspace }>("workspace")
|
||||||
|
)
|
||||||
|
.filter((m) => workspacesSet.has(m.workspace._id.toString()))
|
||||||
|
.map((m) => m.workspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.authData.authPayload instanceof User) {
|
||||||
|
workspaces = (
|
||||||
|
await Membership.find({
|
||||||
|
user: req.authData.authPayload._id
|
||||||
|
}).populate<{ workspace: IWorkspace }>("workspace")
|
||||||
|
)
|
||||||
|
.filter((m) => workspacesSet.has(m.workspace._id.toString()))
|
||||||
|
.map((m) => m.workspace);
|
||||||
|
}
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
workspaces
|
workspaces
|
@ -13,7 +13,7 @@ import {
|
|||||||
ProjectPermissionSub,
|
ProjectPermissionSub,
|
||||||
getAuthDataProjectPermissions
|
getAuthDataProjectPermissions
|
||||||
} from "../../ee/services/ProjectRoleService";
|
} from "../../ee/services/ProjectRoleService";
|
||||||
import { ForbiddenError } from "@casl/ability";
|
import { ForbiddenError, subject } from "@casl/ability";
|
||||||
import { Types } from "mongoose";
|
import { Types } from "mongoose";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,6 +86,14 @@ export const createServiceTokenData = async (req: Request, res: Response) => {
|
|||||||
ProjectPermissionSub.ServiceTokens
|
ProjectPermissionSub.ServiceTokens
|
||||||
);
|
);
|
||||||
|
|
||||||
|
scopes.forEach(({ environment, secretPath }) => {
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Create,
|
||||||
|
subject(ProjectPermissionSub.Secrets, { environment, secretPath: secretPath })
|
||||||
|
);
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
const secret = crypto.randomBytes(16).toString("hex");
|
const secret = crypto.randomBytes(16).toString("hex");
|
||||||
const secretHash = await bcrypt.hash(secret, await getSaltRounds());
|
const secretHash = await bcrypt.hash(secret, await getSaltRounds());
|
||||||
|
|
@ -348,7 +348,7 @@ export const getSecretByNameRaw = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
const {
|
const {
|
||||||
query: { secretPath, environment, workspaceId, type, include_imports },
|
query: { secretPath, environment, workspaceId, type, include_imports, version },
|
||||||
params: { secretName }
|
params: { secretName }
|
||||||
} = await validateRequest(reqValidator.GetSecretByNameRawV3, req);
|
} = await validateRequest(reqValidator.GetSecretByNameRawV3, req);
|
||||||
|
|
||||||
@ -371,7 +371,8 @@ export const getSecretByNameRaw = async (req: Request, res: Response) => {
|
|||||||
type,
|
type,
|
||||||
secretPath,
|
secretPath,
|
||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
include_imports
|
include_imports,
|
||||||
|
version
|
||||||
});
|
});
|
||||||
|
|
||||||
const key = await BotService.getWorkspaceKeyWithBot({
|
const key = await BotService.getWorkspaceKeyWithBot({
|
||||||
@ -865,7 +866,7 @@ export const getSecrets = async (req: Request, res: Response) => {
|
|||||||
*/
|
*/
|
||||||
export const getSecretByName = async (req: Request, res: Response) => {
|
export const getSecretByName = async (req: Request, res: Response) => {
|
||||||
const {
|
const {
|
||||||
query: { secretPath, environment, workspaceId, type, include_imports },
|
query: { secretPath, environment, workspaceId, type, include_imports, version },
|
||||||
params: { secretName }
|
params: { secretName }
|
||||||
} = await validateRequest(reqValidator.GetSecretByNameV3, req);
|
} = await validateRequest(reqValidator.GetSecretByNameV3, req);
|
||||||
|
|
||||||
@ -888,7 +889,8 @@ export const getSecretByName = async (req: Request, res: Response) => {
|
|||||||
type,
|
type,
|
||||||
secretPath,
|
secretPath,
|
||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
include_imports
|
include_imports,
|
||||||
|
version
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
@ -17,12 +17,12 @@ export const getSecretApprovalRequestCount = async (req: Request, res: Response)
|
|||||||
} = await validateRequest(reqValidator.getSecretApprovalRequestCount, req);
|
} = await validateRequest(reqValidator.getSecretApprovalRequestCount, req);
|
||||||
|
|
||||||
if (!(req.authData.authPayload instanceof User)) return;
|
if (!(req.authData.authPayload instanceof User)) return;
|
||||||
|
|
||||||
const membership = await Membership.findOne({
|
const membership = await Membership.findOne({
|
||||||
user: req.authData.authPayload._id,
|
user: req.authData.authPayload._id,
|
||||||
workspace: new Types.ObjectId(workspaceId)
|
workspace: new Types.ObjectId(workspaceId)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!membership) throw UnauthorizedRequestError();
|
if (!membership) throw UnauthorizedRequestError();
|
||||||
|
|
||||||
const approvalRequestCount = await SecretApprovalRequest.aggregate([
|
const approvalRequestCount = await SecretApprovalRequest.aggregate([
|
||||||
@ -73,12 +73,12 @@ export const getSecretApprovalRequests = async (req: Request, res: Response) =>
|
|||||||
} = await validateRequest(reqValidator.getSecretApprovalRequests, req);
|
} = await validateRequest(reqValidator.getSecretApprovalRequests, req);
|
||||||
|
|
||||||
if (!(req.authData.authPayload instanceof User)) return;
|
if (!(req.authData.authPayload instanceof User)) return;
|
||||||
|
|
||||||
const membership = await Membership.findOne({
|
const membership = await Membership.findOne({
|
||||||
user: req.authData.authPayload._id,
|
user: req.authData.authPayload._id,
|
||||||
workspace: new Types.ObjectId(workspaceId)
|
workspace: new Types.ObjectId(workspaceId)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!membership) throw UnauthorizedRequestError();
|
if (!membership) throw UnauthorizedRequestError();
|
||||||
|
|
||||||
const query = {
|
const query = {
|
||||||
@ -168,13 +168,13 @@ export const getSecretApprovalRequestDetails = async (req: Request, res: Respons
|
|||||||
user: req.authData.authPayload._id,
|
user: req.authData.authPayload._id,
|
||||||
workspace: secretApprovalRequest.workspace
|
workspace: secretApprovalRequest.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!membership) throw UnauthorizedRequestError();
|
if (!membership) throw UnauthorizedRequestError();
|
||||||
|
|
||||||
// allow to fetch only if its admin or is the committer or approver
|
// allow to fetch only if its admin or is the committer or approver
|
||||||
if (
|
if (
|
||||||
membership.role !== "admin" &&
|
membership.role !== "admin" &&
|
||||||
secretApprovalRequest.committer !== membership.id &&
|
!secretApprovalRequest.committer.equals(membership.id) &&
|
||||||
!secretApprovalRequest.policy.approvers.find(
|
!secretApprovalRequest.policy.approvers.find(
|
||||||
(approverId) => approverId.toString() === membership._id.toString()
|
(approverId) => approverId.toString() === membership._id.toString()
|
||||||
)
|
)
|
||||||
@ -215,7 +215,7 @@ export const updateSecretApprovalReviewStatus = async (req: Request, res: Respon
|
|||||||
user: req.authData.authPayload._id,
|
user: req.authData.authPayload._id,
|
||||||
workspace: secretApprovalRequest.workspace
|
workspace: secretApprovalRequest.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!membership) throw UnauthorizedRequestError();
|
if (!membership) throw UnauthorizedRequestError();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -257,7 +257,7 @@ export const mergeSecretApprovalRequest = async (req: Request, res: Response) =>
|
|||||||
user: req.authData.authPayload._id,
|
user: req.authData.authPayload._id,
|
||||||
workspace: secretApprovalRequest.workspace
|
workspace: secretApprovalRequest.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!membership) throw UnauthorizedRequestError();
|
if (!membership) throw UnauthorizedRequestError();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -307,7 +307,7 @@ export const updateSecretApprovalRequestStatus = async (req: Request, res: Respo
|
|||||||
user: req.authData.authPayload._id,
|
user: req.authData.authPayload._id,
|
||||||
workspace: secretApprovalRequest.workspace
|
workspace: secretApprovalRequest.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!membership) throw UnauthorizedRequestError();
|
if (!membership) throw UnauthorizedRequestError();
|
||||||
|
|
||||||
if (
|
if (
|
@ -8,7 +8,10 @@ export enum UserAgentType {
|
|||||||
WEB = "web",
|
WEB = "web",
|
||||||
CLI = "cli",
|
CLI = "cli",
|
||||||
K8_OPERATOR = "k8-operator",
|
K8_OPERATOR = "k8-operator",
|
||||||
OTHER = "other"
|
TERRAFORM = "terraform",
|
||||||
|
OTHER = "other",
|
||||||
|
PYTHON_SDK = "InfisicalPythonSDK",
|
||||||
|
NODE_SDK = "InfisicalNodeSDK"
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EventType {
|
export enum EventType {
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user