mirror of
https://github.com/Infisical/infisical.git
synced 2025-07-15 09:42:14 +00:00
Compare commits
185 Commits
feat/awsSe
...
daniel/kms
Author | SHA1 | Date | |
---|---|---|---|
e6c4c27a87 | |||
ba94b91974 | |||
b65f62fda8 | |||
9138a9e71d | |||
8e4ad8baf8 | |||
9f158d5b3f | |||
0e1cb4ebb2 | |||
8f07f43fbd | |||
023f5d1286 | |||
72b03d4bdf | |||
e870e35002 | |||
4544f621af | |||
ddb5098eda | |||
35749e8d12 | |||
85965184f8 | |||
a1bbd50c0b | |||
f9c936865a | |||
2be10b5f9d | |||
3b6e35e13c | |||
fcf984965e | |||
6bca854475 | |||
a69ce50da9 | |||
1b798bd5d5 | |||
bd3ebe75c9 | |||
0f2b8e4266 | |||
c4ae8f2987 | |||
b50a022d11 | |||
8a035c8d82 | |||
4fa7ba2ec7 | |||
03d7f9f786 | |||
1b3e8b0a1c | |||
6a26a11cbb | |||
d673c8d8e9 | |||
b39c7070b5 | |||
fa3dd03074 | |||
ee40ffd304 | |||
d3d76467ac | |||
58940f31e3 | |||
6d2175cf9f | |||
dbb0b28453 | |||
225862aed8 | |||
8d1bd6aabb | |||
740c650441 | |||
78ccb5acb7 | |||
e9aa8b317b | |||
7b42f666f9 | |||
8a0cfa34d2 | |||
ca9825c1fe | |||
1dfc9511c1 | |||
694ab35f53 | |||
44ae0519d1 | |||
3d89a7f45d | |||
de63c8cb6c | |||
632572f7c3 | |||
0a5f6274f5 | |||
11ee13676d | |||
e7783fe6cc | |||
a524690d01 | |||
c229d6888c | |||
2e459c161d | |||
680f1a2230 | |||
68e21ba8ce | |||
1e9722474f | |||
f93edbb37f | |||
fa8154ecdd | |||
d977092502 | |||
f460acf9b4 | |||
cceb29b93a | |||
02b44365f1 | |||
204269a10d | |||
cf1f83aaa3 | |||
7894181234 | |||
0c214a2f26 | |||
f5862cbb9a | |||
bb699ecb5f | |||
04b20ed11d | |||
cd1e2af9bf | |||
178acc412d | |||
b0288c49c0 | |||
3de5fa066b | |||
f5bb0d4a86 | |||
7699705334 | |||
7c49f6e302 | |||
b329b5aa4b | |||
0882c181d0 | |||
8672dd641a | |||
c613bb642e | |||
90fdba0b77 | |||
795ce11062 | |||
2d4adfc651 | |||
cb826f1a77 | |||
55f6a06440 | |||
a19e5ff905 | |||
dccada8a12 | |||
68bbff455f | |||
fcb59a1482 | |||
b92bc2183a | |||
aff318cf3c | |||
c97a3f07a7 | |||
e0dc2dd6d8 | |||
8bf5b0f457 | |||
4973447676 | |||
bd2e2b7931 | |||
13b7729af8 | |||
e25c1199bc | |||
b377d2a6b1 | |||
6b3726957a | |||
c64e6310a6 | |||
aa893a40a9 | |||
350272aa57 | |||
0e488d840f | |||
95489e1b0a | |||
d6186f1fe8 | |||
cd199f9d3e | |||
71258b6ea7 | |||
56b3e7a76d | |||
49c90c801e | |||
d019011822 | |||
8bd21ffa63 | |||
024a1891d3 | |||
ac7ac79463 | |||
23df78eff8 | |||
84255d1b26 | |||
3a6b2a593b | |||
d3ee30f5e6 | |||
317b15157d | |||
9ea6eca560 | |||
f145a00ef5 | |||
2e34167a24 | |||
0fc7d04455 | |||
af12518f54 | |||
cc193b9a9f | |||
0e95600db3 | |||
b60172f2be | |||
33dea34061 | |||
bc1cce62ab | |||
da68073e86 | |||
7bd312a287 | |||
d61e6752d6 | |||
636aee2ea9 | |||
b20e6a9265 | |||
5de9bf25e0 | |||
d5888f9de7 | |||
1590b528bf | |||
a838f84601 | |||
a32b590dc5 | |||
b330fdbc58 | |||
75f1ce7b86 | |||
4e10f51e50 | |||
778d6b9bbf | |||
8bfbac153c | |||
ddd46acbde | |||
e6165f7790 | |||
ac12f9fc66 | |||
7408d38065 | |||
e0c458df4b | |||
6a751e720c | |||
a80520e425 | |||
4aa3552060 | |||
40781949a6 | |||
2ee423174a | |||
649f7b560f | |||
7219ba3b46 | |||
ca1f7d3448 | |||
4d569d70d6 | |||
5fccc62213 | |||
6e65656360 | |||
e0491c2056 | |||
b8db15563a | |||
9982ade219 | |||
9032bbe514 | |||
1ea8e5a81e | |||
39ff7fddee | |||
a0014230f9 | |||
60d0bc827c | |||
6e9651d188 | |||
42aa3c3d46 | |||
184d353de5 | |||
b2360f9cc8 | |||
846a5a6e19 | |||
c6cd3a8cc0 | |||
796f5510ca | |||
0265665e83 | |||
79e425d807 | |||
c1570930a9 |
474
backend/package-lock.json
generated
474
backend/package-lock.json
generated
@ -33,6 +33,7 @@
|
|||||||
"@infisical/quic": "^1.0.8",
|
"@infisical/quic": "^1.0.8",
|
||||||
"@node-saml/passport-saml": "^5.0.1",
|
"@node-saml/passport-saml": "^5.0.1",
|
||||||
"@octokit/auth-app": "^7.1.1",
|
"@octokit/auth-app": "^7.1.1",
|
||||||
|
"@octokit/plugin-paginate-graphql": "^5.2.4",
|
||||||
"@octokit/plugin-retry": "^5.0.5",
|
"@octokit/plugin-retry": "^5.0.5",
|
||||||
"@octokit/rest": "^20.0.2",
|
"@octokit/rest": "^20.0.2",
|
||||||
"@octokit/webhooks-types": "^7.3.1",
|
"@octokit/webhooks-types": "^7.3.1",
|
||||||
@ -91,10 +92,10 @@
|
|||||||
"ora": "^7.0.1",
|
"ora": "^7.0.1",
|
||||||
"oracledb": "^6.4.0",
|
"oracledb": "^6.4.0",
|
||||||
"otplib": "^12.0.1",
|
"otplib": "^12.0.1",
|
||||||
"passport-github": "^1.1.0",
|
|
||||||
"passport-gitlab2": "^5.0.0",
|
"passport-gitlab2": "^5.0.0",
|
||||||
"passport-google-oauth20": "^2.0.0",
|
"passport-google-oauth20": "^2.0.0",
|
||||||
"passport-ldapauth": "^3.0.1",
|
"passport-ldapauth": "^3.0.1",
|
||||||
|
"passport-oauth2": "^1.8.0",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
"pg-boss": "^10.1.5",
|
"pg-boss": "^10.1.5",
|
||||||
"pg-query-stream": "^4.5.3",
|
"pg-query-stream": "^4.5.3",
|
||||||
@ -135,7 +136,6 @@
|
|||||||
"@types/lodash.isequal": "^4.5.8",
|
"@types/lodash.isequal": "^4.5.8",
|
||||||
"@types/node": "^20.17.30",
|
"@types/node": "^20.17.30",
|
||||||
"@types/nodemailer": "^6.4.14",
|
"@types/nodemailer": "^6.4.14",
|
||||||
"@types/passport-github": "^1.1.12",
|
|
||||||
"@types/passport-google-oauth20": "^2.0.14",
|
"@types/passport-google-oauth20": "^2.0.14",
|
||||||
"@types/pg": "^8.10.9",
|
"@types/pg": "^8.10.9",
|
||||||
"@types/picomatch": "^2.3.3",
|
"@types/picomatch": "^2.3.3",
|
||||||
@ -7245,47 +7245,247 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/core": {
|
"node_modules/@octokit/core": {
|
||||||
"version": "5.0.2",
|
"version": "6.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.5.tgz",
|
||||||
"integrity": "sha512-cZUy1gUvd4vttMic7C0lwPed8IYXWYp8kHIMatyhY8t8n3Cpw2ILczkV5pGMPqef7v0bLo0pOHrEHarsau2Ydg==",
|
"integrity": "sha512-vvmsN0r7rguA+FySiCsbaTTobSftpIDIpPW81trAmsv9TGxg3YCujAxRYp/Uy8xmDgYCzzgulG62H7KYUFmeIg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/auth-token": "^4.0.0",
|
"@octokit/auth-token": "^5.0.0",
|
||||||
"@octokit/graphql": "^7.0.0",
|
"@octokit/graphql": "^8.2.2",
|
||||||
"@octokit/request": "^8.0.2",
|
"@octokit/request": "^9.2.3",
|
||||||
"@octokit/request-error": "^5.0.0",
|
"@octokit/request-error": "^6.1.8",
|
||||||
"@octokit/types": "^12.0.0",
|
"@octokit/types": "^14.0.0",
|
||||||
"before-after-hook": "^2.2.0",
|
"before-after-hook": "^3.0.2",
|
||||||
|
"universal-user-agent": "^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/core/node_modules/@octokit/auth-token": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/core/node_modules/@octokit/endpoint": {
|
||||||
|
"version": "10.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz",
|
||||||
|
"integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/types": "^14.0.0",
|
||||||
|
"universal-user-agent": "^7.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/core/node_modules/@octokit/openapi-types": {
|
||||||
|
"version": "25.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.0.0.tgz",
|
||||||
|
"integrity": "sha512-FZvktFu7HfOIJf2BScLKIEYjDsw6RKc7rBJCdvCTfKsVnx2GEB/Nbzjr29DUdb7vQhlzS/j8qDzdditP0OC6aw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/core/node_modules/@octokit/request": {
|
||||||
|
"version": "9.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.3.tgz",
|
||||||
|
"integrity": "sha512-Ma+pZU8PXLOEYzsWf0cn/gY+ME57Wq8f49WTXA8FMHp2Ps9djKw//xYJ1je8Hm0pR2lU9FUGeJRWOtxq6olt4w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/endpoint": "^10.1.4",
|
||||||
|
"@octokit/request-error": "^6.1.8",
|
||||||
|
"@octokit/types": "^14.0.0",
|
||||||
|
"fast-content-type-parse": "^2.0.0",
|
||||||
|
"universal-user-agent": "^7.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/core/node_modules/@octokit/request-error": {
|
||||||
|
"version": "6.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz",
|
||||||
|
"integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/types": "^14.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/core/node_modules/@octokit/types": {
|
||||||
|
"version": "14.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.0.0.tgz",
|
||||||
|
"integrity": "sha512-VVmZP0lEhbo2O1pdq63gZFiGCKkm8PPp8AUOijlwPO6hojEVjspA0MWKP7E4hbvGxzFKNqKr6p0IYtOH/Wf/zA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/openapi-types": "^25.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/core/node_modules/fast-content-type-parse": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fastify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/fastify"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/core/node_modules/universal-user-agent": {
|
||||||
|
"version": "7.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz",
|
||||||
|
"integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/endpoint": {
|
||||||
|
"version": "9.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz",
|
||||||
|
"integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/types": "^13.1.0",
|
||||||
"universal-user-agent": "^6.0.0"
|
"universal-user-agent": "^6.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 18"
|
"node": ">= 18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/endpoint": {
|
"node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": {
|
||||||
"version": "9.0.4",
|
"version": "24.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||||
"integrity": "sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==",
|
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/endpoint/node_modules/@octokit/types": {
|
||||||
|
"version": "13.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||||
|
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/types": "^12.0.0",
|
"@octokit/openapi-types": "^24.2.0"
|
||||||
"universal-user-agent": "^6.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 18"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/graphql": {
|
"node_modules/@octokit/graphql": {
|
||||||
"version": "7.0.2",
|
"version": "8.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.2.tgz",
|
||||||
"integrity": "sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==",
|
"integrity": "sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/request": "^8.0.1",
|
"@octokit/request": "^9.2.3",
|
||||||
"@octokit/types": "^12.0.0",
|
"@octokit/types": "^14.0.0",
|
||||||
"universal-user-agent": "^6.0.0"
|
"universal-user-agent": "^7.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 18"
|
"node": ">= 18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@octokit/graphql/node_modules/@octokit/endpoint": {
|
||||||
|
"version": "10.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz",
|
||||||
|
"integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/types": "^14.0.0",
|
||||||
|
"universal-user-agent": "^7.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": {
|
||||||
|
"version": "25.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.0.0.tgz",
|
||||||
|
"integrity": "sha512-FZvktFu7HfOIJf2BScLKIEYjDsw6RKc7rBJCdvCTfKsVnx2GEB/Nbzjr29DUdb7vQhlzS/j8qDzdditP0OC6aw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/graphql/node_modules/@octokit/request": {
|
||||||
|
"version": "9.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.3.tgz",
|
||||||
|
"integrity": "sha512-Ma+pZU8PXLOEYzsWf0cn/gY+ME57Wq8f49WTXA8FMHp2Ps9djKw//xYJ1je8Hm0pR2lU9FUGeJRWOtxq6olt4w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/endpoint": "^10.1.4",
|
||||||
|
"@octokit/request-error": "^6.1.8",
|
||||||
|
"@octokit/types": "^14.0.0",
|
||||||
|
"fast-content-type-parse": "^2.0.0",
|
||||||
|
"universal-user-agent": "^7.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/graphql/node_modules/@octokit/request-error": {
|
||||||
|
"version": "6.1.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz",
|
||||||
|
"integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/types": "^14.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/graphql/node_modules/@octokit/types": {
|
||||||
|
"version": "14.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.0.0.tgz",
|
||||||
|
"integrity": "sha512-VVmZP0lEhbo2O1pdq63gZFiGCKkm8PPp8AUOijlwPO6hojEVjspA0MWKP7E4hbvGxzFKNqKr6p0IYtOH/Wf/zA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/openapi-types": "^25.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/graphql/node_modules/fast-content-type-parse": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fastify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/fastify"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/graphql/node_modules/universal-user-agent": {
|
||||||
|
"version": "7.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz",
|
||||||
|
"integrity": "sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==",
|
||||||
|
"license": "ISC",
|
||||||
|
"peer": true
|
||||||
|
},
|
||||||
"node_modules/@octokit/oauth-authorization-url": {
|
"node_modules/@octokit/oauth-authorization-url": {
|
||||||
"version": "7.1.1",
|
"version": "7.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-7.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/oauth-authorization-url/-/oauth-authorization-url-7.1.1.tgz",
|
||||||
@ -7380,6 +7580,18 @@
|
|||||||
"node": ">= 18"
|
"node": ">= 18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@octokit/plugin-paginate-graphql": {
|
||||||
|
"version": "5.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-graphql/-/plugin-paginate-graphql-5.2.4.tgz",
|
||||||
|
"integrity": "sha512-pLZES1jWaOynXKHOqdnwZ5ULeVR6tVVCMm+AUbp0htdcyXDU95WbkYdU4R2ej1wKj5Tu94Mee2Ne0PjPO9cCyA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@octokit/core": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@octokit/plugin-paginate-rest": {
|
"node_modules/@octokit/plugin-paginate-rest": {
|
||||||
"version": "9.1.5",
|
"version": "9.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.1.5.tgz",
|
||||||
@ -7461,28 +7673,14 @@
|
|||||||
"@octokit/openapi-types": "^18.0.0"
|
"@octokit/openapi-types": "^18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/plugin-throttling": {
|
|
||||||
"version": "8.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-8.1.3.tgz",
|
|
||||||
"integrity": "sha512-pfyqaqpc0EXh5Cn4HX9lWYsZ4gGbjnSmUILeu4u2gnuM50K/wIk9s1Pxt3lVeVwekmITgN/nJdoh43Ka+vye8A==",
|
|
||||||
"dependencies": {
|
|
||||||
"@octokit/types": "^12.2.0",
|
|
||||||
"bottleneck": "^2.15.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@octokit/core": "^5.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@octokit/request": {
|
"node_modules/@octokit/request": {
|
||||||
"version": "8.4.0",
|
"version": "8.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz",
|
||||||
"integrity": "sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==",
|
"integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/endpoint": "^9.0.1",
|
"@octokit/endpoint": "^9.0.6",
|
||||||
"@octokit/request-error": "^5.1.0",
|
"@octokit/request-error": "^5.1.1",
|
||||||
"@octokit/types": "^13.1.0",
|
"@octokit/types": "^13.1.0",
|
||||||
"universal-user-agent": "^6.0.0"
|
"universal-user-agent": "^6.0.0"
|
||||||
},
|
},
|
||||||
@ -7491,9 +7689,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@octokit/request-error": {
|
"node_modules/@octokit/request-error": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz",
|
||||||
"integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==",
|
"integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@octokit/types": "^13.1.0",
|
"@octokit/types": "^13.1.0",
|
||||||
"deprecation": "^2.0.0",
|
"deprecation": "^2.0.0",
|
||||||
@ -7543,6 +7742,59 @@
|
|||||||
"node": ">= 18"
|
"node": ">= 18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@octokit/rest/node_modules/@octokit/core": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-dKYCMuPO1bmrpuogcjQ8z7ICCH3FP6WmxpwC03yjzGfZhj9fTJg6+bS1+UAplekbN2C+M61UNllGOOoAfGCrdQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/auth-token": "^4.0.0",
|
||||||
|
"@octokit/graphql": "^7.1.0",
|
||||||
|
"@octokit/request": "^8.4.1",
|
||||||
|
"@octokit/request-error": "^5.1.1",
|
||||||
|
"@octokit/types": "^13.0.0",
|
||||||
|
"before-after-hook": "^2.2.0",
|
||||||
|
"universal-user-agent": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/rest/node_modules/@octokit/graphql": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/request": "^8.4.1",
|
||||||
|
"@octokit/types": "^13.0.0",
|
||||||
|
"universal-user-agent": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/rest/node_modules/@octokit/openapi-types": {
|
||||||
|
"version": "24.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||||
|
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/rest/node_modules/@octokit/types": {
|
||||||
|
"version": "13.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||||
|
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/openapi-types": "^24.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@octokit/rest/node_modules/before-after-hook": {
|
||||||
|
"version": "2.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
|
||||||
|
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
"node_modules/@octokit/types": {
|
"node_modules/@octokit/types": {
|
||||||
"version": "12.4.0",
|
"version": "12.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.4.0.tgz",
|
||||||
@ -9871,17 +10123,6 @@
|
|||||||
"@types/express": "*"
|
"@types/express": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/passport-github": {
|
|
||||||
"version": "1.1.12",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/passport-github/-/passport-github-1.1.12.tgz",
|
|
||||||
"integrity": "sha512-VJpMEIH+cOoXB694QgcxuvWy2wPd1Oq3gqrg2Y9DMVBYs9TmH9L14qnqPDZsNMZKBDH+SvqRsGZj9SgHYeDgcA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"@types/express": "*",
|
|
||||||
"@types/passport": "*",
|
|
||||||
"@types/passport-oauth2": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@types/passport-google-oauth20": {
|
"node_modules/@types/passport-google-oauth20": {
|
||||||
"version": "2.0.14",
|
"version": "2.0.14",
|
||||||
"resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.14.tgz",
|
"resolved": "https://registry.npmjs.org/@types/passport-google-oauth20/-/passport-google-oauth20-2.0.14.tgz",
|
||||||
@ -11654,9 +11895,11 @@
|
|||||||
"integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ=="
|
"integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ=="
|
||||||
},
|
},
|
||||||
"node_modules/before-after-hook": {
|
"node_modules/before-after-hook": {
|
||||||
"version": "2.2.3",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz",
|
||||||
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
|
"integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/big-integer": {
|
"node_modules/big-integer": {
|
||||||
"version": "1.6.52",
|
"version": "1.6.52",
|
||||||
@ -18142,9 +18385,10 @@
|
|||||||
"integrity": "sha512-p1TRH/edngVEHVbwqWnxUViEmq5znDvyB+Sik5cmuLpGOIfDf/39zLiq3swPF8Vakqn+gvNiOQAZu8djYlQILA=="
|
"integrity": "sha512-p1TRH/edngVEHVbwqWnxUViEmq5znDvyB+Sik5cmuLpGOIfDf/39zLiq3swPF8Vakqn+gvNiOQAZu8djYlQILA=="
|
||||||
},
|
},
|
||||||
"node_modules/oauth": {
|
"node_modules/oauth": {
|
||||||
"version": "0.9.15",
|
"version": "0.10.2",
|
||||||
"resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz",
|
"resolved": "https://registry.npmjs.org/oauth/-/oauth-0.10.2.tgz",
|
||||||
"integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA=="
|
"integrity": "sha512-JtFnB+8nxDEXgNyniwz573xxbKSOu3R8D40xQKqcjwJ2CDkYqUDI53o6IuzDJBx60Z8VKCm271+t8iFjakrl8Q==",
|
||||||
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/object-assign": {
|
"node_modules/object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
@ -18827,17 +19071,6 @@
|
|||||||
"url": "https://github.com/sponsors/jaredhanson"
|
"url": "https://github.com/sponsors/jaredhanson"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/passport-github": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/passport-github/-/passport-github-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-XARXJycE6fFh/dxF+Uut8OjlwbFEXgbPVj/+V+K7cvriRK7VcAOm+NgBmbiLM9Qv3SSxEAV+V6fIk89nYHXa8A==",
|
|
||||||
"dependencies": {
|
|
||||||
"passport-oauth2": "1.x.x"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 0.4.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/passport-gitlab2": {
|
"node_modules/passport-gitlab2": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/passport-gitlab2/-/passport-gitlab2-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/passport-gitlab2/-/passport-gitlab2-5.0.0.tgz",
|
||||||
@ -18873,12 +19106,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/passport-oauth2": {
|
"node_modules/passport-oauth2": {
|
||||||
"version": "1.7.0",
|
"version": "1.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.8.0.tgz",
|
||||||
"integrity": "sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==",
|
"integrity": "sha512-cjsQbOrXIDE4P8nNb3FQRCCmJJ/utnFKEz2NX209f7KOHPoX18gF7gBzBbLLsj2/je4KrgiwLLGjf0lm9rtTBA==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"base64url": "3.x.x",
|
"base64url": "3.x.x",
|
||||||
"oauth": "0.9.x",
|
"oauth": "0.10.x",
|
||||||
"passport-strategy": "1.x.x",
|
"passport-strategy": "1.x.x",
|
||||||
"uid2": "0.0.x",
|
"uid2": "0.0.x",
|
||||||
"utils-merge": "1.x.x"
|
"utils-merge": "1.x.x"
|
||||||
@ -19667,6 +19901,62 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/probot/node_modules/@octokit/core": {
|
||||||
|
"version": "5.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.1.tgz",
|
||||||
|
"integrity": "sha512-dKYCMuPO1bmrpuogcjQ8z7ICCH3FP6WmxpwC03yjzGfZhj9fTJg6+bS1+UAplekbN2C+M61UNllGOOoAfGCrdQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/auth-token": "^4.0.0",
|
||||||
|
"@octokit/graphql": "^7.1.0",
|
||||||
|
"@octokit/request": "^8.4.1",
|
||||||
|
"@octokit/request-error": "^5.1.1",
|
||||||
|
"@octokit/types": "^13.0.0",
|
||||||
|
"before-after-hook": "^2.2.0",
|
||||||
|
"universal-user-agent": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/probot/node_modules/@octokit/core/node_modules/@octokit/types": {
|
||||||
|
"version": "13.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||||
|
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/openapi-types": "^24.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/probot/node_modules/@octokit/graphql": {
|
||||||
|
"version": "7.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz",
|
||||||
|
"integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/request": "^8.4.1",
|
||||||
|
"@octokit/types": "^13.0.0",
|
||||||
|
"universal-user-agent": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/probot/node_modules/@octokit/graphql/node_modules/@octokit/types": {
|
||||||
|
"version": "13.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
|
||||||
|
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/openapi-types": "^24.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/probot/node_modules/@octokit/openapi-types": {
|
||||||
|
"version": "24.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
|
||||||
|
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/probot/node_modules/@octokit/plugin-retry": {
|
"node_modules/probot/node_modules/@octokit/plugin-retry": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.0.1.tgz",
|
||||||
@ -19683,6 +19973,28 @@
|
|||||||
"@octokit/core": ">=5"
|
"@octokit/core": ">=5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/probot/node_modules/@octokit/plugin-throttling": {
|
||||||
|
"version": "8.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-8.2.0.tgz",
|
||||||
|
"integrity": "sha512-nOpWtLayKFpgqmgD0y3GqXafMFuKcA4tRPZIfu7BArd2lEZeb1988nhWhwx4aZWmjDmUfdgVf7W+Tt4AmvRmMQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@octokit/types": "^12.2.0",
|
||||||
|
"bottleneck": "^2.15.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@octokit/core": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/probot/node_modules/before-after-hook": {
|
||||||
|
"version": "2.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
|
||||||
|
"integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
"node_modules/probot/node_modules/commander": {
|
"node_modules/probot/node_modules/commander": {
|
||||||
"version": "12.1.0",
|
"version": "12.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
||||||
|
@ -91,7 +91,6 @@
|
|||||||
"@types/lodash.isequal": "^4.5.8",
|
"@types/lodash.isequal": "^4.5.8",
|
||||||
"@types/node": "^20.17.30",
|
"@types/node": "^20.17.30",
|
||||||
"@types/nodemailer": "^6.4.14",
|
"@types/nodemailer": "^6.4.14",
|
||||||
"@types/passport-github": "^1.1.12",
|
|
||||||
"@types/passport-google-oauth20": "^2.0.14",
|
"@types/passport-google-oauth20": "^2.0.14",
|
||||||
"@types/pg": "^8.10.9",
|
"@types/pg": "^8.10.9",
|
||||||
"@types/picomatch": "^2.3.3",
|
"@types/picomatch": "^2.3.3",
|
||||||
@ -150,6 +149,7 @@
|
|||||||
"@infisical/quic": "^1.0.8",
|
"@infisical/quic": "^1.0.8",
|
||||||
"@node-saml/passport-saml": "^5.0.1",
|
"@node-saml/passport-saml": "^5.0.1",
|
||||||
"@octokit/auth-app": "^7.1.1",
|
"@octokit/auth-app": "^7.1.1",
|
||||||
|
"@octokit/plugin-paginate-graphql": "^5.2.4",
|
||||||
"@octokit/plugin-retry": "^5.0.5",
|
"@octokit/plugin-retry": "^5.0.5",
|
||||||
"@octokit/rest": "^20.0.2",
|
"@octokit/rest": "^20.0.2",
|
||||||
"@octokit/webhooks-types": "^7.3.1",
|
"@octokit/webhooks-types": "^7.3.1",
|
||||||
@ -208,10 +208,10 @@
|
|||||||
"ora": "^7.0.1",
|
"ora": "^7.0.1",
|
||||||
"oracledb": "^6.4.0",
|
"oracledb": "^6.4.0",
|
||||||
"otplib": "^12.0.1",
|
"otplib": "^12.0.1",
|
||||||
"passport-github": "^1.1.0",
|
|
||||||
"passport-gitlab2": "^5.0.0",
|
"passport-gitlab2": "^5.0.0",
|
||||||
"passport-google-oauth20": "^2.0.0",
|
"passport-google-oauth20": "^2.0.0",
|
||||||
"passport-ldapauth": "^3.0.1",
|
"passport-ldapauth": "^3.0.1",
|
||||||
|
"passport-oauth2": "^1.8.0",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
"pg-boss": "^10.1.5",
|
"pg-boss": "^10.1.5",
|
||||||
"pg-query-stream": "^4.5.3",
|
"pg-query-stream": "^4.5.3",
|
||||||
|
7
backend/src/@types/fastify.d.ts
vendored
7
backend/src/@types/fastify.d.ts
vendored
@ -5,6 +5,7 @@ import { Redis } from "ioredis";
|
|||||||
import { TUsers } from "@app/db/schemas";
|
import { TUsers } from "@app/db/schemas";
|
||||||
import { TAccessApprovalPolicyServiceFactory } from "@app/ee/services/access-approval-policy/access-approval-policy-service";
|
import { TAccessApprovalPolicyServiceFactory } from "@app/ee/services/access-approval-policy/access-approval-policy-service";
|
||||||
import { TAccessApprovalRequestServiceFactory } from "@app/ee/services/access-approval-request/access-approval-request-service";
|
import { TAccessApprovalRequestServiceFactory } from "@app/ee/services/access-approval-request/access-approval-request-service";
|
||||||
|
import { TAssumePrivilegeServiceFactory } from "@app/ee/services/assume-privilege/assume-privilege-service";
|
||||||
import { TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
import { TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
||||||
import { TCreateAuditLogDTO } from "@app/ee/services/audit-log/audit-log-types";
|
import { TCreateAuditLogDTO } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { TAuditLogStreamServiceFactory } from "@app/ee/services/audit-log-stream/audit-log-stream-service";
|
import { TAuditLogStreamServiceFactory } from "@app/ee/services/audit-log-stream/audit-log-stream-service";
|
||||||
@ -14,6 +15,7 @@ import { TDynamicSecretServiceFactory } from "@app/ee/services/dynamic-secret/dy
|
|||||||
import { TDynamicSecretLeaseServiceFactory } from "@app/ee/services/dynamic-secret-lease/dynamic-secret-lease-service";
|
import { TDynamicSecretLeaseServiceFactory } from "@app/ee/services/dynamic-secret-lease/dynamic-secret-lease-service";
|
||||||
import { TExternalKmsServiceFactory } from "@app/ee/services/external-kms/external-kms-service";
|
import { TExternalKmsServiceFactory } from "@app/ee/services/external-kms/external-kms-service";
|
||||||
import { TGatewayServiceFactory } from "@app/ee/services/gateway/gateway-service";
|
import { TGatewayServiceFactory } from "@app/ee/services/gateway/gateway-service";
|
||||||
|
import { TGithubOrgSyncServiceFactory } from "@app/ee/services/github-org-sync/github-org-sync-service";
|
||||||
import { TGroupServiceFactory } from "@app/ee/services/group/group-service";
|
import { TGroupServiceFactory } from "@app/ee/services/group/group-service";
|
||||||
import { TIdentityProjectAdditionalPrivilegeServiceFactory } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service";
|
import { TIdentityProjectAdditionalPrivilegeServiceFactory } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-service";
|
||||||
import { TIdentityProjectAdditionalPrivilegeV2ServiceFactory } from "@app/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service";
|
import { TIdentityProjectAdditionalPrivilegeV2ServiceFactory } from "@app/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-service";
|
||||||
@ -109,12 +111,14 @@ declare module "@fastify/request-context" {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
identityPermissionMetadata?: Record<string, unknown>; // filled by permission service
|
identityPermissionMetadata?: Record<string, unknown>; // filled by permission service
|
||||||
|
assumedPrivilegeDetails?: { requesterId: string; actorId: string; actorType: ActorType; projectId: string };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module "fastify" {
|
declare module "fastify" {
|
||||||
interface Session {
|
interface Session {
|
||||||
callbackPort: string;
|
callbackPort: string;
|
||||||
|
isAdminLogin: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FastifyRequest {
|
interface FastifyRequest {
|
||||||
@ -138,6 +142,7 @@ declare module "fastify" {
|
|||||||
passportUser: {
|
passportUser: {
|
||||||
isUserCompleted: boolean;
|
isUserCompleted: boolean;
|
||||||
providerAuthToken: string;
|
providerAuthToken: string;
|
||||||
|
externalProviderAccessToken?: string;
|
||||||
};
|
};
|
||||||
kmipUser: {
|
kmipUser: {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
@ -241,6 +246,8 @@ declare module "fastify" {
|
|||||||
kmipOperation: TKmipOperationServiceFactory;
|
kmipOperation: TKmipOperationServiceFactory;
|
||||||
gateway: TGatewayServiceFactory;
|
gateway: TGatewayServiceFactory;
|
||||||
secretRotationV2: TSecretRotationV2ServiceFactory;
|
secretRotationV2: TSecretRotationV2ServiceFactory;
|
||||||
|
assumePrivileges: TAssumePrivilegeServiceFactory;
|
||||||
|
githubOrgSync: TGithubOrgSyncServiceFactory;
|
||||||
};
|
};
|
||||||
// this is exclusive use for middlewares in which we need to inject data
|
// this is exclusive use for middlewares in which we need to inject data
|
||||||
// everywhere else access using service layer
|
// everywhere else access using service layer
|
||||||
|
18
backend/src/@types/knex.d.ts
vendored
18
backend/src/@types/knex.d.ts
vendored
@ -83,6 +83,9 @@ import {
|
|||||||
TGitAppOrg,
|
TGitAppOrg,
|
||||||
TGitAppOrgInsert,
|
TGitAppOrgInsert,
|
||||||
TGitAppOrgUpdate,
|
TGitAppOrgUpdate,
|
||||||
|
TGithubOrgSyncConfigs,
|
||||||
|
TGithubOrgSyncConfigsInsert,
|
||||||
|
TGithubOrgSyncConfigsUpdate,
|
||||||
TGroupProjectMembershipRoles,
|
TGroupProjectMembershipRoles,
|
||||||
TGroupProjectMembershipRolesInsert,
|
TGroupProjectMembershipRolesInsert,
|
||||||
TGroupProjectMembershipRolesUpdate,
|
TGroupProjectMembershipRolesUpdate,
|
||||||
@ -423,6 +426,11 @@ import {
|
|||||||
TWorkflowIntegrationsInsert,
|
TWorkflowIntegrationsInsert,
|
||||||
TWorkflowIntegrationsUpdate
|
TWorkflowIntegrationsUpdate
|
||||||
} from "@app/db/schemas";
|
} from "@app/db/schemas";
|
||||||
|
import {
|
||||||
|
TSecretReminderRecipients,
|
||||||
|
TSecretReminderRecipientsInsert,
|
||||||
|
TSecretReminderRecipientsUpdate
|
||||||
|
} from "@app/db/schemas/secret-reminder-recipients";
|
||||||
|
|
||||||
declare module "knex" {
|
declare module "knex" {
|
||||||
namespace Knex {
|
namespace Knex {
|
||||||
@ -994,5 +1002,15 @@ declare module "knex/types/tables" {
|
|||||||
TSecretRotationV2SecretMappingsInsert,
|
TSecretRotationV2SecretMappingsInsert,
|
||||||
TSecretRotationV2SecretMappingsUpdate
|
TSecretRotationV2SecretMappingsUpdate
|
||||||
>;
|
>;
|
||||||
|
[TableName.SecretReminderRecipients]: KnexOriginal.CompositeTableType<
|
||||||
|
TSecretReminderRecipients,
|
||||||
|
TSecretReminderRecipientsInsert,
|
||||||
|
TSecretReminderRecipientsUpdate
|
||||||
|
>;
|
||||||
|
[TableName.GithubOrgSyncConfig]: KnexOriginal.CompositeTableType<
|
||||||
|
TGithubOrgSyncConfigs,
|
||||||
|
TGithubOrgSyncConfigsInsert,
|
||||||
|
TGithubOrgSyncConfigsUpdate
|
||||||
|
>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasSecretReminderRecipientsTable = await knex.schema.hasTable(TableName.SecretReminderRecipients);
|
||||||
|
|
||||||
|
if (!hasSecretReminderRecipientsTable) {
|
||||||
|
await knex.schema.createTable(TableName.SecretReminderRecipients, (table) => {
|
||||||
|
table.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
table.timestamps(true, true, true);
|
||||||
|
table.uuid("secretId").notNullable();
|
||||||
|
table.uuid("userId").notNullable();
|
||||||
|
table.string("projectId").notNullable();
|
||||||
|
|
||||||
|
// Based on userId rather than project membership ID so we can easily extend group support in the future if need be.
|
||||||
|
// This does however mean we need to manually clean up once a user is removed from a project.
|
||||||
|
table.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||||
|
table.foreign("secretId").references("id").inTable(TableName.SecretV2).onDelete("CASCADE");
|
||||||
|
table.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||||
|
|
||||||
|
table.index("secretId");
|
||||||
|
table.unique(["secretId", "userId"]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasSecretReminderRecipientsTable = await knex.schema.hasTable(TableName.SecretReminderRecipients);
|
||||||
|
|
||||||
|
if (hasSecretReminderRecipientsTable) {
|
||||||
|
await knex.schema.dropTableIfExists(TableName.SecretReminderRecipients);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { ProjectType, TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasDefaultUserCaCol = await knex.schema.hasColumn(TableName.ProjectSshConfig, "defaultUserSshCaId");
|
||||||
|
const hasDefaultHostCaCol = await knex.schema.hasColumn(TableName.ProjectSshConfig, "defaultHostSshCaId");
|
||||||
|
|
||||||
|
if (hasDefaultUserCaCol && hasDefaultHostCaCol) {
|
||||||
|
await knex.schema.alterTable(TableName.ProjectSshConfig, (t) => {
|
||||||
|
t.dropForeign(["defaultUserSshCaId"]);
|
||||||
|
t.dropForeign(["defaultHostSshCaId"]);
|
||||||
|
});
|
||||||
|
await knex.schema.alterTable(TableName.ProjectSshConfig, (t) => {
|
||||||
|
// allow nullable (does not wipe existing values)
|
||||||
|
t.uuid("defaultUserSshCaId").nullable().alter();
|
||||||
|
t.uuid("defaultHostSshCaId").nullable().alter();
|
||||||
|
// re-add with SET NULL behavior (previously CASCADE)
|
||||||
|
t.foreign("defaultUserSshCaId").references("id").inTable(TableName.SshCertificateAuthority).onDelete("SET NULL");
|
||||||
|
t.foreign("defaultHostSshCaId").references("id").inTable(TableName.SshCertificateAuthority).onDelete("SET NULL");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// (dangtony98): backfill by adding null defaults CAs for all existing Infisical SSH projects
|
||||||
|
// that do not have an associated ProjectSshConfig record introduced in Infisical SSH V2.
|
||||||
|
|
||||||
|
const allProjects = await knex(TableName.Project).where("type", ProjectType.SSH).select("id");
|
||||||
|
|
||||||
|
const projectsWithConfig = await knex(TableName.ProjectSshConfig).select("projectId");
|
||||||
|
const projectIdsWithConfig = new Set(projectsWithConfig.map((config) => config.projectId));
|
||||||
|
|
||||||
|
const projectsNeedingConfig = allProjects.filter((project) => !projectIdsWithConfig.has(project.id));
|
||||||
|
|
||||||
|
if (projectsNeedingConfig.length > 0) {
|
||||||
|
const configsToInsert = projectsNeedingConfig.map((project) => ({
|
||||||
|
projectId: project.id,
|
||||||
|
defaultUserSshCaId: null,
|
||||||
|
defaultHostSshCaId: null,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedAt: new Date()
|
||||||
|
}));
|
||||||
|
|
||||||
|
await knex.batchInsert(TableName.ProjectSshConfig, configsToInsert);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(): Promise<void> {}
|
23
backend/src/db/migrations/20250426044605_ssh-host-alias.ts
Normal file
23
backend/src/db/migrations/20250426044605_ssh-host-alias.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasAliasColumn = await knex.schema.hasColumn(TableName.SshHost, "alias");
|
||||||
|
if (!hasAliasColumn) {
|
||||||
|
await knex.schema.alterTable(TableName.SshHost, (t) => {
|
||||||
|
t.string("alias").nullable();
|
||||||
|
t.unique(["projectId", "alias"]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasAliasColumn = await knex.schema.hasColumn(TableName.SshHost, "alias");
|
||||||
|
if (hasAliasColumn) {
|
||||||
|
await knex.schema.alterTable(TableName.SshHost, (t) => {
|
||||||
|
t.dropUnique(["projectId", "alias"]);
|
||||||
|
t.dropColumn("alias");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasTable = await knex.schema.hasTable(TableName.GithubOrgSyncConfig);
|
||||||
|
if (!hasTable) {
|
||||||
|
await knex.schema.createTable(TableName.GithubOrgSyncConfig, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.string("githubOrgName").notNullable();
|
||||||
|
t.boolean("isActive").defaultTo(false);
|
||||||
|
t.binary("encryptedGithubOrgAccessToken");
|
||||||
|
t.uuid("orgId").notNullable().unique();
|
||||||
|
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await createOnUpdateTrigger(knex, TableName.GithubOrgSyncConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.dropTableIfExists(TableName.GithubOrgSyncConfig);
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.GithubOrgSyncConfig);
|
||||||
|
}
|
@ -20,7 +20,7 @@ export const CertificatesSchema = z.object({
|
|||||||
notAfter: z.date(),
|
notAfter: z.date(),
|
||||||
revokedAt: z.date().nullable().optional(),
|
revokedAt: z.date().nullable().optional(),
|
||||||
revocationReason: z.number().nullable().optional(),
|
revocationReason: z.number().nullable().optional(),
|
||||||
altNames: z.string().default("").nullable().optional(),
|
altNames: z.string().nullable().optional(),
|
||||||
caCertId: z.string().uuid(),
|
caCertId: z.string().uuid(),
|
||||||
certificateTemplateId: z.string().uuid().nullable().optional(),
|
certificateTemplateId: z.string().uuid().nullable().optional(),
|
||||||
keyUsages: z.string().array().nullable().optional(),
|
keyUsages: z.string().array().nullable().optional(),
|
||||||
|
24
backend/src/db/schemas/github-org-sync-configs.ts
Normal file
24
backend/src/db/schemas/github-org-sync-configs.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Code generated by automation script, DO NOT EDIT.
|
||||||
|
// Automated by pulling database and generating zod schema
|
||||||
|
// To update. Just run npm run generate:schema
|
||||||
|
// Written by akhilmhdh.
|
||||||
|
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { zodBuffer } from "@app/lib/zod";
|
||||||
|
|
||||||
|
import { TImmutableDBKeys } from "./models";
|
||||||
|
|
||||||
|
export const GithubOrgSyncConfigsSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
githubOrgName: z.string(),
|
||||||
|
isActive: z.boolean().default(false).nullable().optional(),
|
||||||
|
encryptedGithubOrgAccessToken: zodBuffer.nullable().optional(),
|
||||||
|
orgId: z.string().uuid(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TGithubOrgSyncConfigs = z.infer<typeof GithubOrgSyncConfigsSchema>;
|
||||||
|
export type TGithubOrgSyncConfigsInsert = Omit<z.input<typeof GithubOrgSyncConfigsSchema>, TImmutableDBKeys>;
|
||||||
|
export type TGithubOrgSyncConfigsUpdate = Partial<Omit<z.input<typeof GithubOrgSyncConfigsSchema>, TImmutableDBKeys>>;
|
@ -25,6 +25,7 @@ export * from "./external-kms";
|
|||||||
export * from "./gateways";
|
export * from "./gateways";
|
||||||
export * from "./git-app-install-sessions";
|
export * from "./git-app-install-sessions";
|
||||||
export * from "./git-app-org";
|
export * from "./git-app-org";
|
||||||
|
export * from "./github-org-sync-configs";
|
||||||
export * from "./group-project-membership-roles";
|
export * from "./group-project-membership-roles";
|
||||||
export * from "./group-project-memberships";
|
export * from "./group-project-memberships";
|
||||||
export * from "./groups";
|
export * from "./groups";
|
||||||
|
@ -13,7 +13,7 @@ export const KmipOrgServerCertificatesSchema = z.object({
|
|||||||
id: z.string().uuid(),
|
id: z.string().uuid(),
|
||||||
orgId: z.string().uuid(),
|
orgId: z.string().uuid(),
|
||||||
commonName: z.string(),
|
commonName: z.string(),
|
||||||
altNames: z.string(),
|
altNames: z.string().nullable().optional(),
|
||||||
serialNumber: z.string(),
|
serialNumber: z.string(),
|
||||||
keyAlgorithm: z.string(),
|
keyAlgorithm: z.string(),
|
||||||
issuedAt: z.date(),
|
issuedAt: z.date(),
|
||||||
|
@ -146,7 +146,9 @@ export enum TableName {
|
|||||||
KmipOrgServerCertificates = "kmip_org_server_certificates",
|
KmipOrgServerCertificates = "kmip_org_server_certificates",
|
||||||
KmipClientCertificates = "kmip_client_certificates",
|
KmipClientCertificates = "kmip_client_certificates",
|
||||||
SecretRotationV2 = "secret_rotations_v2",
|
SecretRotationV2 = "secret_rotations_v2",
|
||||||
SecretRotationV2SecretMapping = "secret_rotation_v2_secret_mappings"
|
SecretRotationV2SecretMapping = "secret_rotation_v2_secret_mappings",
|
||||||
|
SecretReminderRecipients = "secret_reminder_recipients",
|
||||||
|
GithubOrgSyncConfig = "github_org_sync_configs"
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TImmutableDBKeys = "id" | "createdAt" | "updatedAt";
|
export type TImmutableDBKeys = "id" | "createdAt" | "updatedAt";
|
||||||
|
@ -30,9 +30,9 @@ export const OidcConfigsSchema = z.object({
|
|||||||
updatedAt: z.date(),
|
updatedAt: z.date(),
|
||||||
orgId: z.string().uuid(),
|
orgId: z.string().uuid(),
|
||||||
lastUsed: z.date().nullable().optional(),
|
lastUsed: z.date().nullable().optional(),
|
||||||
|
manageGroupMemberships: z.boolean().default(false),
|
||||||
encryptedOidcClientId: zodBuffer,
|
encryptedOidcClientId: zodBuffer,
|
||||||
encryptedOidcClientSecret: zodBuffer,
|
encryptedOidcClientSecret: zodBuffer,
|
||||||
manageGroupMemberships: z.boolean().default(false),
|
|
||||||
jwtSignatureAlgorithm: z.string().default("RS256")
|
jwtSignatureAlgorithm: z.string().default("RS256")
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ export const OrganizationsSchema = z.object({
|
|||||||
defaultMembershipRole: z.string().default("member"),
|
defaultMembershipRole: z.string().default("member"),
|
||||||
enforceMfa: z.boolean().default(false),
|
enforceMfa: z.boolean().default(false),
|
||||||
selectedMfaMethod: z.string().nullable().optional(),
|
selectedMfaMethod: z.string().nullable().optional(),
|
||||||
|
secretShareSendToAnyone: z.boolean().default(true).nullable().optional(),
|
||||||
allowSecretSharingOutsideOrganization: z.boolean().default(true).nullable().optional(),
|
allowSecretSharingOutsideOrganization: z.boolean().default(true).nullable().optional(),
|
||||||
shouldUseNewPrivilegeSystem: z.boolean().default(true),
|
shouldUseNewPrivilegeSystem: z.boolean().default(true),
|
||||||
privilegeUpgradeInitiatedByUsername: z.string().nullable().optional(),
|
privilegeUpgradeInitiatedByUsername: z.string().nullable().optional(),
|
||||||
|
23
backend/src/db/schemas/secret-reminder-recipients.ts
Normal file
23
backend/src/db/schemas/secret-reminder-recipients.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Code generated by automation script, DO NOT EDIT.
|
||||||
|
// Automated by pulling database and generating zod schema
|
||||||
|
// To update. Just run npm run generate:schema
|
||||||
|
// Written by akhilmhdh.
|
||||||
|
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { TImmutableDBKeys } from "./models";
|
||||||
|
|
||||||
|
export const SecretReminderRecipientsSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date(),
|
||||||
|
secretId: z.string().uuid(),
|
||||||
|
userId: z.string().uuid(),
|
||||||
|
projectId: z.string()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TSecretReminderRecipients = z.infer<typeof SecretReminderRecipientsSchema>;
|
||||||
|
export type TSecretReminderRecipientsInsert = Omit<z.input<typeof SecretReminderRecipientsSchema>, TImmutableDBKeys>;
|
||||||
|
export type TSecretReminderRecipientsUpdate = Partial<
|
||||||
|
Omit<z.input<typeof SecretReminderRecipientsSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
@ -16,7 +16,8 @@ export const SshHostsSchema = z.object({
|
|||||||
userCertTtl: z.string(),
|
userCertTtl: z.string(),
|
||||||
hostCertTtl: z.string(),
|
hostCertTtl: z.string(),
|
||||||
userSshCaId: z.string().uuid(),
|
userSshCaId: z.string().uuid(),
|
||||||
hostSshCaId: z.string().uuid()
|
hostSshCaId: z.string().uuid(),
|
||||||
|
alias: z.string().nullable().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TSshHosts = z.infer<typeof SshHostsSchema>;
|
export type TSshHosts = z.infer<typeof SshHostsSchema>;
|
||||||
|
124
backend/src/ee/routes/v1/assume-privilege-router.ts
Normal file
124
backend/src/ee/routes/v1/assume-privilege-router.ts
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import { requestContext } from "@fastify/request-context";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
|
import { getConfig } from "@app/lib/config/env";
|
||||||
|
import { BadRequestError } from "@app/lib/errors";
|
||||||
|
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
|
import { ActorType, AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
|
export const registerAssumePrivilegeRouter = async (server: FastifyZodProvider) => {
|
||||||
|
server.route({
|
||||||
|
method: "POST",
|
||||||
|
url: "/:projectId/assume-privileges",
|
||||||
|
config: {
|
||||||
|
rateLimit: writeLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
params: z.object({
|
||||||
|
projectId: z.string()
|
||||||
|
}),
|
||||||
|
body: z.object({
|
||||||
|
actorType: z.enum([ActorType.USER, ActorType.IDENTITY]),
|
||||||
|
actorId: z.string()
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
message: z.string()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
handler: async (req, res) => {
|
||||||
|
if (req.auth.authMode === AuthMode.JWT) {
|
||||||
|
const payload = await server.services.assumePrivileges.assumeProjectPrivileges({
|
||||||
|
targetActorType: req.body.actorType,
|
||||||
|
targetActorId: req.body.actorId,
|
||||||
|
projectId: req.params.projectId,
|
||||||
|
actorPermissionDetails: req.permission,
|
||||||
|
tokenVersionId: req.auth.tokenVersionId
|
||||||
|
});
|
||||||
|
|
||||||
|
const appCfg = getConfig();
|
||||||
|
void res.setCookie("infisical-project-assume-privileges", payload.assumePrivilegesToken, {
|
||||||
|
httpOnly: true,
|
||||||
|
path: "/",
|
||||||
|
sameSite: "strict",
|
||||||
|
secure: appCfg.HTTPS_ENABLED,
|
||||||
|
maxAge: 3600 // 1 hour in seconds
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.services.auditLog.createAuditLog({
|
||||||
|
...req.auditLogInfo,
|
||||||
|
orgId: req.permission.orgId,
|
||||||
|
event: {
|
||||||
|
type: EventType.PROJECT_ASSUME_PRIVILEGE_SESSION_START,
|
||||||
|
metadata: {
|
||||||
|
projectId: req.params.projectId,
|
||||||
|
requesterEmail: req.auth.user.username,
|
||||||
|
requesterId: req.auth.user.id,
|
||||||
|
targetActorType: req.body.actorType,
|
||||||
|
targetActorId: req.body.actorId,
|
||||||
|
duration: "1hr"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return { message: "Successfully assumed role" };
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BadRequestError({ message: "Invalid auth mode" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: "DELETE",
|
||||||
|
url: "/:projectId/assume-privileges",
|
||||||
|
config: {
|
||||||
|
rateLimit: writeLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
params: z.object({
|
||||||
|
projectId: z.string()
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
message: z.string()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
handler: async (req, res) => {
|
||||||
|
const assumedPrivilegeDetails = requestContext.get("assumedPrivilegeDetails");
|
||||||
|
if (req.auth.authMode === AuthMode.JWT && assumedPrivilegeDetails) {
|
||||||
|
const appCfg = getConfig();
|
||||||
|
void res.setCookie("infisical-project-assume-privileges", "", {
|
||||||
|
httpOnly: true,
|
||||||
|
path: "/",
|
||||||
|
sameSite: "strict",
|
||||||
|
secure: appCfg.HTTPS_ENABLED,
|
||||||
|
expires: new Date(0)
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.services.auditLog.createAuditLog({
|
||||||
|
...req.auditLogInfo,
|
||||||
|
orgId: req.permission.orgId,
|
||||||
|
event: {
|
||||||
|
type: EventType.PROJECT_ASSUME_PRIVILEGE_SESSION_END,
|
||||||
|
metadata: {
|
||||||
|
projectId: req.params.projectId,
|
||||||
|
requesterEmail: req.auth.user.username,
|
||||||
|
requesterId: req.auth.user.id,
|
||||||
|
targetActorId: assumedPrivilegeDetails.actorId,
|
||||||
|
targetActorType: assumedPrivilegeDetails.actorType
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return { message: "Successfully exited assumed role" };
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BadRequestError({ message: "Invalid auth mode" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
@ -1,7 +1,7 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { DynamicSecretLeasesSchema } from "@app/db/schemas";
|
import { DynamicSecretLeasesSchema } from "@app/db/schemas";
|
||||||
import { DYNAMIC_SECRET_LEASES } from "@app/lib/api-docs";
|
import { ApiDocsTags, DYNAMIC_SECRET_LEASES } from "@app/lib/api-docs";
|
||||||
import { daysToMillisecond } from "@app/lib/dates";
|
import { daysToMillisecond } from "@app/lib/dates";
|
||||||
import { removeTrailingSlash } from "@app/lib/fn";
|
import { removeTrailingSlash } from "@app/lib/fn";
|
||||||
import { ms } from "@app/lib/ms";
|
import { ms } from "@app/lib/ms";
|
||||||
@ -18,6 +18,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.DynamicSecrets],
|
||||||
body: z.object({
|
body: z.object({
|
||||||
dynamicSecretName: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.dynamicSecretName).toLowerCase(),
|
dynamicSecretName: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.dynamicSecretName).toLowerCase(),
|
||||||
projectSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.projectSlug),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.CREATE.projectSlug),
|
||||||
@ -65,6 +67,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.DynamicSecrets],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.DELETE.leaseId)
|
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.DELETE.leaseId)
|
||||||
}),
|
}),
|
||||||
@ -107,6 +111,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.DynamicSecrets],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.RENEW.leaseId)
|
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.RENEW.leaseId)
|
||||||
}),
|
}),
|
||||||
@ -160,6 +166,8 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.DynamicSecrets],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.GET_BY_LEASEID.leaseId)
|
leaseId: z.string().min(1).describe(DYNAMIC_SECRET_LEASES.GET_BY_LEASEID.leaseId)
|
||||||
}),
|
}),
|
||||||
|
@ -2,7 +2,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { DynamicSecretLeasesSchema } from "@app/db/schemas";
|
import { DynamicSecretLeasesSchema } from "@app/db/schemas";
|
||||||
import { DynamicSecretProviderSchema } from "@app/ee/services/dynamic-secret/providers/models";
|
import { DynamicSecretProviderSchema } from "@app/ee/services/dynamic-secret/providers/models";
|
||||||
import { DYNAMIC_SECRETS } from "@app/lib/api-docs";
|
import { ApiDocsTags, DYNAMIC_SECRETS } from "@app/lib/api-docs";
|
||||||
import { daysToMillisecond } from "@app/lib/dates";
|
import { daysToMillisecond } from "@app/lib/dates";
|
||||||
import { removeTrailingSlash } from "@app/lib/fn";
|
import { removeTrailingSlash } from "@app/lib/fn";
|
||||||
import { ms } from "@app/lib/ms";
|
import { ms } from "@app/lib/ms";
|
||||||
@ -21,6 +21,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.DynamicSecrets],
|
||||||
body: z.object({
|
body: z.object({
|
||||||
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.CREATE.projectSlug),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.CREATE.projectSlug),
|
||||||
provider: DynamicSecretProviderSchema.describe(DYNAMIC_SECRETS.CREATE.provider),
|
provider: DynamicSecretProviderSchema.describe(DYNAMIC_SECRETS.CREATE.provider),
|
||||||
@ -111,6 +113,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.DynamicSecrets],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.UPDATE.name)
|
name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.UPDATE.name)
|
||||||
}),
|
}),
|
||||||
@ -179,6 +183,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.DynamicSecrets],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.DELETE.name)
|
name: z.string().toLowerCase().describe(DYNAMIC_SECRETS.DELETE.name)
|
||||||
}),
|
}),
|
||||||
@ -215,6 +221,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.DynamicSecrets],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
name: z.string().min(1).describe(DYNAMIC_SECRETS.GET_BY_NAME.name)
|
name: z.string().min(1).describe(DYNAMIC_SECRETS.GET_BY_NAME.name)
|
||||||
}),
|
}),
|
||||||
@ -253,6 +261,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.DynamicSecrets],
|
||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST.projectSlug),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST.projectSlug),
|
||||||
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRETS.LIST.path),
|
path: z.string().trim().default("/").transform(removeTrailingSlash).describe(DYNAMIC_SECRETS.LIST.path),
|
||||||
@ -284,18 +294,20 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.DynamicSecrets],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
name: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.name)
|
name: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEASES_BY_NAME.name)
|
||||||
}),
|
}),
|
||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.projectSlug),
|
projectSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEASES_BY_NAME.projectSlug),
|
||||||
path: z
|
path: z
|
||||||
.string()
|
.string()
|
||||||
.trim()
|
.trim()
|
||||||
.default("/")
|
.default("/")
|
||||||
.transform(removeTrailingSlash)
|
.transform(removeTrailingSlash)
|
||||||
.describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.path),
|
.describe(DYNAMIC_SECRETS.LIST_LEASES_BY_NAME.path),
|
||||||
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEAES_BY_NAME.environmentSlug)
|
environmentSlug: z.string().min(1).describe(DYNAMIC_SECRETS.LIST_LEASES_BY_NAME.environmentSlug)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
|
129
backend/src/ee/routes/v1/github-org-sync-router.ts
Normal file
129
backend/src/ee/routes/v1/github-org-sync-router.ts
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { GithubOrgSyncConfigsSchema } from "@app/db/schemas";
|
||||||
|
import { CharacterType, zodValidateCharacters } from "@app/lib/validator/validate-string";
|
||||||
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
|
const SanitizedGithubOrgSyncSchema = GithubOrgSyncConfigsSchema.pick({
|
||||||
|
isActive: true,
|
||||||
|
id: true,
|
||||||
|
createdAt: true,
|
||||||
|
updatedAt: true,
|
||||||
|
orgId: true,
|
||||||
|
githubOrgName: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const githubOrgNameValidator = zodValidateCharacters([CharacterType.AlphaNumeric, CharacterType.Hyphen]);
|
||||||
|
export const registerGithubOrgSyncRouter = async (server: FastifyZodProvider) => {
|
||||||
|
server.route({
|
||||||
|
url: "/",
|
||||||
|
method: "POST",
|
||||||
|
config: {
|
||||||
|
rateLimit: writeLimit
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
schema: {
|
||||||
|
body: z.object({
|
||||||
|
githubOrgName: githubOrgNameValidator(z.string().trim(), "GitHub Org Name"),
|
||||||
|
githubOrgAccessToken: z.string().trim().max(1000).optional(),
|
||||||
|
isActive: z.boolean().default(false)
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
githubOrgSyncConfig: SanitizedGithubOrgSyncSchema
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handler: async (req) => {
|
||||||
|
const githubOrgSyncConfig = await server.services.githubOrgSync.createGithubOrgSync({
|
||||||
|
orgPermission: req.permission,
|
||||||
|
githubOrgName: req.body.githubOrgName,
|
||||||
|
githubOrgAccessToken: req.body.githubOrgAccessToken,
|
||||||
|
isActive: req.body.isActive
|
||||||
|
});
|
||||||
|
|
||||||
|
return { githubOrgSyncConfig };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
url: "/",
|
||||||
|
method: "PATCH",
|
||||||
|
config: {
|
||||||
|
rateLimit: writeLimit
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
schema: {
|
||||||
|
body: z
|
||||||
|
.object({
|
||||||
|
githubOrgName: githubOrgNameValidator(z.string().trim(), "GitHub Org Name"),
|
||||||
|
githubOrgAccessToken: z.string().trim().max(1000),
|
||||||
|
isActive: z.boolean()
|
||||||
|
})
|
||||||
|
.partial(),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
githubOrgSyncConfig: SanitizedGithubOrgSyncSchema
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handler: async (req) => {
|
||||||
|
const githubOrgSyncConfig = await server.services.githubOrgSync.updateGithubOrgSync({
|
||||||
|
orgPermission: req.permission,
|
||||||
|
githubOrgName: req.body.githubOrgName,
|
||||||
|
githubOrgAccessToken: req.body.githubOrgAccessToken,
|
||||||
|
isActive: req.body.isActive
|
||||||
|
});
|
||||||
|
|
||||||
|
return { githubOrgSyncConfig };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
url: "/",
|
||||||
|
method: "DELETE",
|
||||||
|
config: {
|
||||||
|
rateLimit: writeLimit
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
schema: {
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
githubOrgSyncConfig: SanitizedGithubOrgSyncSchema
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handler: async (req) => {
|
||||||
|
const githubOrgSyncConfig = await server.services.githubOrgSync.deleteGithubOrgSync({
|
||||||
|
orgPermission: req.permission
|
||||||
|
});
|
||||||
|
|
||||||
|
return { githubOrgSyncConfig };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
url: "/",
|
||||||
|
method: "GET",
|
||||||
|
config: {
|
||||||
|
rateLimit: readLimit
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
schema: {
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
githubOrgSyncConfig: SanitizedGithubOrgSyncSchema
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handler: async (req) => {
|
||||||
|
const githubOrgSyncConfig = await server.services.githubOrgSync.getGithubOrgSync({
|
||||||
|
orgPermission: req.permission
|
||||||
|
});
|
||||||
|
|
||||||
|
return { githubOrgSyncConfig };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
@ -2,7 +2,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { GroupsSchema, OrgMembershipRole, UsersSchema } from "@app/db/schemas";
|
import { GroupsSchema, OrgMembershipRole, UsersSchema } from "@app/db/schemas";
|
||||||
import { EFilterReturnedUsers } from "@app/ee/services/group/group-types";
|
import { EFilterReturnedUsers } from "@app/ee/services/group/group-types";
|
||||||
import { GROUPS } from "@app/lib/api-docs";
|
import { ApiDocsTags, GROUPS } from "@app/lib/api-docs";
|
||||||
import { slugSchema } from "@app/server/lib/schemas";
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@ -13,6 +13,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.Groups],
|
||||||
body: z.object({
|
body: z.object({
|
||||||
name: z.string().trim().min(1).max(50).describe(GROUPS.CREATE.name),
|
name: z.string().trim().min(1).max(50).describe(GROUPS.CREATE.name),
|
||||||
slug: slugSchema({ min: 5, max: 36 }).optional().describe(GROUPS.CREATE.slug),
|
slug: slugSchema({ min: 5, max: 36 }).optional().describe(GROUPS.CREATE.slug),
|
||||||
@ -40,6 +42,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
method: "GET",
|
method: "GET",
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.Groups],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
id: z.string().trim().describe(GROUPS.GET_BY_ID.id)
|
id: z.string().trim().describe(GROUPS.GET_BY_ID.id)
|
||||||
}),
|
}),
|
||||||
@ -65,6 +69,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
method: "GET",
|
method: "GET",
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.Groups],
|
||||||
response: {
|
response: {
|
||||||
200: GroupsSchema.array()
|
200: GroupsSchema.array()
|
||||||
}
|
}
|
||||||
@ -87,6 +93,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.Groups],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
id: z.string().trim().describe(GROUPS.UPDATE.id)
|
id: z.string().trim().describe(GROUPS.UPDATE.id)
|
||||||
}),
|
}),
|
||||||
@ -120,6 +128,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.Groups],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
id: z.string().trim().describe(GROUPS.DELETE.id)
|
id: z.string().trim().describe(GROUPS.DELETE.id)
|
||||||
}),
|
}),
|
||||||
@ -145,6 +155,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
url: "/:id/users",
|
url: "/:id/users",
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.Groups],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
id: z.string().trim().describe(GROUPS.LIST_USERS.id)
|
id: z.string().trim().describe(GROUPS.LIST_USERS.id)
|
||||||
}),
|
}),
|
||||||
@ -194,6 +206,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
url: "/:id/users/:username",
|
url: "/:id/users/:username",
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.Groups],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
id: z.string().trim().describe(GROUPS.ADD_USER.id),
|
id: z.string().trim().describe(GROUPS.ADD_USER.id),
|
||||||
username: z.string().trim().describe(GROUPS.ADD_USER.username)
|
username: z.string().trim().describe(GROUPS.ADD_USER.username)
|
||||||
@ -227,6 +241,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
url: "/:id/users/:username",
|
url: "/:id/users/:username",
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.Groups],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
id: z.string().trim().describe(GROUPS.DELETE_USER.id),
|
id: z.string().trim().describe(GROUPS.DELETE_USER.id),
|
||||||
username: z.string().trim().describe(GROUPS.DELETE_USER.username)
|
username: z.string().trim().describe(GROUPS.DELETE_USER.username)
|
||||||
|
@ -3,7 +3,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-types";
|
import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/services/identity-project-additional-privilege/identity-project-additional-privilege-types";
|
||||||
import { backfillPermissionV1SchemaToV2Schema } from "@app/ee/services/permission/project-permission";
|
import { backfillPermissionV1SchemaToV2Schema } from "@app/ee/services/permission/project-permission";
|
||||||
import { IDENTITY_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
|
import { ApiDocsTags, IDENTITY_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
|
||||||
import { UnauthorizedError } from "@app/lib/errors";
|
import { UnauthorizedError } from "@app/lib/errors";
|
||||||
import { ms } from "@app/lib/ms";
|
import { ms } from "@app/lib/ms";
|
||||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
@ -25,6 +25,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
|
||||||
description: "Create a permanent or a non expiry specific privilege for identity.",
|
description: "Create a permanent or a non expiry specific privilege for identity.",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -85,6 +87,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
|
||||||
description: "Create a temporary or a expiring specific privilege for identity.",
|
description: "Create a temporary or a expiring specific privilege for identity.",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -157,6 +161,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
|
||||||
description: "Update a specific privilege of an identity.",
|
description: "Update a specific privilege of an identity.",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -240,6 +246,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
|
||||||
description: "Delete a specific privilege of an identity.",
|
description: "Delete a specific privilege of an identity.",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -279,6 +287,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
|
||||||
description: "Retrieve details of a specific privilege by privilege slug.",
|
description: "Retrieve details of a specific privilege by privilege slug.",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -319,6 +329,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.IdentitySpecificPrivilegesV1],
|
||||||
description: "List of a specific privilege of an identity in a project.",
|
description: "List of a specific privilege of an identity in a project.",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
|
@ -2,12 +2,14 @@ import { registerProjectTemplateRouter } from "@app/ee/routes/v1/project-templat
|
|||||||
|
|
||||||
import { registerAccessApprovalPolicyRouter } from "./access-approval-policy-router";
|
import { registerAccessApprovalPolicyRouter } from "./access-approval-policy-router";
|
||||||
import { registerAccessApprovalRequestRouter } from "./access-approval-request-router";
|
import { registerAccessApprovalRequestRouter } from "./access-approval-request-router";
|
||||||
|
import { registerAssumePrivilegeRouter } from "./assume-privilege-router";
|
||||||
import { registerAuditLogStreamRouter } from "./audit-log-stream-router";
|
import { registerAuditLogStreamRouter } from "./audit-log-stream-router";
|
||||||
import { registerCaCrlRouter } from "./certificate-authority-crl-router";
|
import { registerCaCrlRouter } from "./certificate-authority-crl-router";
|
||||||
import { registerDynamicSecretLeaseRouter } from "./dynamic-secret-lease-router";
|
import { registerDynamicSecretLeaseRouter } from "./dynamic-secret-lease-router";
|
||||||
import { registerDynamicSecretRouter } from "./dynamic-secret-router";
|
import { registerDynamicSecretRouter } from "./dynamic-secret-router";
|
||||||
import { registerExternalKmsRouter } from "./external-kms-router";
|
import { registerExternalKmsRouter } from "./external-kms-router";
|
||||||
import { registerGatewayRouter } from "./gateway-router";
|
import { registerGatewayRouter } from "./gateway-router";
|
||||||
|
import { registerGithubOrgSyncRouter } from "./github-org-sync-router";
|
||||||
import { registerGroupRouter } from "./group-router";
|
import { registerGroupRouter } from "./group-router";
|
||||||
import { registerIdentityProjectAdditionalPrivilegeRouter } from "./identity-project-additional-privilege-router";
|
import { registerIdentityProjectAdditionalPrivilegeRouter } from "./identity-project-additional-privilege-router";
|
||||||
import { registerKmipRouter } from "./kmip-router";
|
import { registerKmipRouter } from "./kmip-router";
|
||||||
@ -45,6 +47,7 @@ export const registerV1EERoutes = async (server: FastifyZodProvider) => {
|
|||||||
await projectRouter.register(registerProjectRoleRouter);
|
await projectRouter.register(registerProjectRoleRouter);
|
||||||
await projectRouter.register(registerProjectRouter);
|
await projectRouter.register(registerProjectRouter);
|
||||||
await projectRouter.register(registerTrustedIpRouter);
|
await projectRouter.register(registerTrustedIpRouter);
|
||||||
|
await projectRouter.register(registerAssumePrivilegeRouter);
|
||||||
},
|
},
|
||||||
{ prefix: "/workspace" }
|
{ prefix: "/workspace" }
|
||||||
);
|
);
|
||||||
@ -70,6 +73,7 @@ export const registerV1EERoutes = async (server: FastifyZodProvider) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
await server.register(registerGatewayRouter, { prefix: "/gateways" });
|
await server.register(registerGatewayRouter, { prefix: "/gateways" });
|
||||||
|
await server.register(registerGithubOrgSyncRouter, { prefix: "/github-org-sync-config" });
|
||||||
|
|
||||||
await server.register(
|
await server.register(
|
||||||
async (pkiRouter) => {
|
async (pkiRouter) => {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { packRules } from "@casl/ability/extra";
|
import { packRules } from "@casl/ability/extra";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { ProjectMembershipRole, ProjectMembershipsSchema, ProjectRolesSchema } from "@app/db/schemas";
|
import { ProjectMembershipRole, ProjectRolesSchema } from "@app/db/schemas";
|
||||||
import {
|
import {
|
||||||
backfillPermissionV1SchemaToV2Schema,
|
backfillPermissionV1SchemaToV2Schema,
|
||||||
ProjectPermissionV1Schema
|
ProjectPermissionV1Schema
|
||||||
@ -245,13 +245,22 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
data: z.object({
|
data: z.object({
|
||||||
membership: ProjectMembershipsSchema.extend({
|
membership: z.object({
|
||||||
|
id: z.string(),
|
||||||
roles: z
|
roles: z
|
||||||
.object({
|
.object({
|
||||||
role: z.string()
|
role: z.string()
|
||||||
})
|
})
|
||||||
.array()
|
.array()
|
||||||
}),
|
}),
|
||||||
|
assumedPrivilegeDetails: z
|
||||||
|
.object({
|
||||||
|
actorId: z.string(),
|
||||||
|
actorType: z.string(),
|
||||||
|
actorName: z.string(),
|
||||||
|
actorEmail: z.string().optional()
|
||||||
|
})
|
||||||
|
.optional(),
|
||||||
permissions: z.any().array()
|
permissions: z.any().array()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -259,14 +268,20 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT]),
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
handler: async (req) => {
|
handler: async (req) => {
|
||||||
const { permissions, membership } = await server.services.projectRole.getUserPermission(
|
const { permissions, membership, assumedPrivilegeDetails } = await server.services.projectRole.getUserPermission(
|
||||||
req.permission.id,
|
req.permission.id,
|
||||||
req.params.projectId,
|
req.params.projectId,
|
||||||
req.permission.authMethod,
|
req.permission.authMethod,
|
||||||
req.permission.orgId
|
req.permission.orgId
|
||||||
);
|
);
|
||||||
|
|
||||||
return { data: { permissions, membership } };
|
return {
|
||||||
|
data: {
|
||||||
|
permissions,
|
||||||
|
membership,
|
||||||
|
assumedPrivilegeDetails
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { AuditLogsSchema, SecretSnapshotsSchema } from "@app/db/schemas";
|
import { AuditLogsSchema, SecretSnapshotsSchema } from "@app/db/schemas";
|
||||||
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { AUDIT_LOGS, PROJECTS } from "@app/lib/api-docs";
|
import { ApiDocsTags, AUDIT_LOGS, PROJECTS } from "@app/lib/api-docs";
|
||||||
import { getLastMidnightDateISO, removeTrailingSlash } from "@app/lib/fn";
|
import { getLastMidnightDateISO, removeTrailingSlash } from "@app/lib/fn";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
@ -17,6 +17,8 @@ export const registerProjectRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.Projects],
|
||||||
description: "Return project secret snapshots ids",
|
description: "Return project secret snapshots ids",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,7 @@ import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
|||||||
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
|
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
|
||||||
import { ProjectTemplateDefaultEnvironments } from "@app/ee/services/project-template/project-template-constants";
|
import { ProjectTemplateDefaultEnvironments } from "@app/ee/services/project-template/project-template-constants";
|
||||||
import { isInfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-fns";
|
import { isInfisicalProjectTemplate } from "@app/ee/services/project-template/project-template-fns";
|
||||||
import { ProjectTemplates } from "@app/lib/api-docs";
|
import { ApiDocsTags, ProjectTemplates } from "@app/lib/api-docs";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { slugSchema } from "@app/server/lib/schemas";
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
@ -101,6 +101,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectTemplates],
|
||||||
description: "List project templates for the current organization.",
|
description: "List project templates for the current organization.",
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@ -137,6 +139,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectTemplates],
|
||||||
description: "Get a project template by ID.",
|
description: "Get a project template by ID.",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
templateId: z.string().uuid()
|
templateId: z.string().uuid()
|
||||||
@ -176,6 +180,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectTemplates],
|
||||||
description: "Create a project template.",
|
description: "Create a project template.",
|
||||||
body: z.object({
|
body: z.object({
|
||||||
name: slugSchema({ field: "name" })
|
name: slugSchema({ field: "name" })
|
||||||
@ -219,6 +225,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectTemplates],
|
||||||
description: "Update a project template.",
|
description: "Update a project template.",
|
||||||
params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.UPDATE.templateId) }),
|
params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.UPDATE.templateId) }),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
@ -269,6 +277,8 @@ export const registerProjectTemplateRouter = async (server: FastifyZodProvider)
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectTemplates],
|
||||||
description: "Delete a project template.",
|
description: "Delete a project template.",
|
||||||
params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.DELETE.templateId) }),
|
params: z.object({ templateId: z.string().uuid().describe(ProjectTemplates.DELETE.templateId) }),
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { SecretSnapshotsSchema } from "@app/db/schemas";
|
import { SecretSnapshotsSchema } from "@app/db/schemas";
|
||||||
import { PROJECTS } from "@app/lib/api-docs";
|
import { ApiDocsTags, PROJECTS } from "@app/lib/api-docs";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { SanitizedTagSchema, secretRawSchema } from "@app/server/routes/sanitizedSchemas";
|
import { SanitizedTagSchema, secretRawSchema } from "@app/server/routes/sanitizedSchemas";
|
||||||
@ -65,6 +65,8 @@ export const registerSnapshotRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.Projects],
|
||||||
description: "Roll back project secrets to those captured in a secret snapshot version.",
|
description: "Roll back project secrets to those captured in a secret snapshot version.",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@ import { sanitizedSshCa } from "@app/ee/services/ssh/ssh-certificate-authority-s
|
|||||||
import { SshCaKeySource, SshCaStatus } from "@app/ee/services/ssh/ssh-certificate-authority-types";
|
import { SshCaKeySource, SshCaStatus } from "@app/ee/services/ssh/ssh-certificate-authority-types";
|
||||||
import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certificate-types";
|
import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certificate-types";
|
||||||
import { sanitizedSshCertificateTemplate } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-schema";
|
import { sanitizedSshCertificateTemplate } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-schema";
|
||||||
import { SSH_CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
|
import { ApiDocsTags, SSH_CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@ -20,6 +20,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SshCertificateAuthorities],
|
||||||
description: "Create SSH CA",
|
description: "Create SSH CA",
|
||||||
body: z
|
body: z
|
||||||
.object({
|
.object({
|
||||||
@ -92,6 +94,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SshCertificateAuthorities],
|
||||||
description: "Get SSH CA",
|
description: "Get SSH CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET.sshCaId)
|
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET.sshCaId)
|
||||||
@ -138,6 +142,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SshCertificateAuthorities],
|
||||||
description: "Get public key of SSH CA",
|
description: "Get public key of SSH CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET_PUBLIC_KEY.sshCaId)
|
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET_PUBLIC_KEY.sshCaId)
|
||||||
@ -163,6 +169,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SshCertificateAuthorities],
|
||||||
description: "Update SSH CA",
|
description: "Update SSH CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.UPDATE.sshCaId)
|
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.UPDATE.sshCaId)
|
||||||
@ -216,6 +224,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SshCertificateAuthorities],
|
||||||
description: "Delete SSH CA",
|
description: "Delete SSH CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.DELETE.sshCaId)
|
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.DELETE.sshCaId)
|
||||||
@ -261,6 +271,8 @@ export const registerSshCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SshCertificateAuthorities],
|
||||||
description: "Get list of certificate templates for the SSH CA",
|
description: "Get list of certificate templates for the SSH CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET_CERTIFICATE_TEMPLATES.sshCaId)
|
sshCaId: z.string().trim().describe(SSH_CERTIFICATE_AUTHORITIES.GET_CERTIFICATE_TEMPLATES.sshCaId)
|
||||||
|
@ -3,7 +3,7 @@ import { z } from "zod";
|
|||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { SshCertType } from "@app/ee/services/ssh/ssh-certificate-authority-types";
|
import { SshCertType } from "@app/ee/services/ssh/ssh-certificate-authority-types";
|
||||||
import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certificate-types";
|
import { SshCertKeyAlgorithm } from "@app/ee/services/ssh-certificate/ssh-certificate-types";
|
||||||
import { SSH_CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
|
import { ApiDocsTags, SSH_CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
|
||||||
import { ms } from "@app/lib/ms";
|
import { ms } from "@app/lib/ms";
|
||||||
import { writeLimit } from "@app/server/config/rateLimiter";
|
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||||
@ -20,6 +20,8 @@ export const registerSshCertRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SshCertificates],
|
||||||
description: "Sign SSH public key",
|
description: "Sign SSH public key",
|
||||||
body: z.object({
|
body: z.object({
|
||||||
certificateTemplateId: z
|
certificateTemplateId: z
|
||||||
@ -100,6 +102,8 @@ export const registerSshCertRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SshCertificates],
|
||||||
description: "Issue SSH credentials (certificate + key)",
|
description: "Issue SSH credentials (certificate + key)",
|
||||||
body: z.object({
|
body: z.object({
|
||||||
certificateTemplateId: z
|
certificateTemplateId: z
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
isValidHostPattern,
|
isValidHostPattern,
|
||||||
isValidUserPattern
|
isValidUserPattern
|
||||||
} from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-validators";
|
} from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-validators";
|
||||||
import { SSH_CERTIFICATE_TEMPLATES } from "@app/lib/api-docs";
|
import { ApiDocsTags, SSH_CERTIFICATE_TEMPLATES } from "@app/lib/api-docs";
|
||||||
import { ms } from "@app/lib/ms";
|
import { ms } from "@app/lib/ms";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
@ -22,6 +22,8 @@ export const registerSshCertificateTemplateRouter = async (server: FastifyZodPro
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SshCertificateTemplates],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
certificateTemplateId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.GET.certificateTemplateId)
|
certificateTemplateId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.GET.certificateTemplateId)
|
||||||
}),
|
}),
|
||||||
@ -61,6 +63,8 @@ export const registerSshCertificateTemplateRouter = async (server: FastifyZodPro
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SshCertificateTemplates],
|
||||||
body: z
|
body: z
|
||||||
.object({
|
.object({
|
||||||
sshCaId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.CREATE.sshCaId),
|
sshCaId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.CREATE.sshCaId),
|
||||||
@ -141,6 +145,8 @@ export const registerSshCertificateTemplateRouter = async (server: FastifyZodPro
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SshCertificateTemplates],
|
||||||
body: z.object({
|
body: z.object({
|
||||||
status: z.nativeEnum(SshCertTemplateStatus).optional(),
|
status: z.nativeEnum(SshCertTemplateStatus).optional(),
|
||||||
name: z
|
name: z
|
||||||
@ -224,6 +230,8 @@ export const registerSshCertificateTemplateRouter = async (server: FastifyZodPro
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SshCertificateTemplates],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
certificateTemplateId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.DELETE.certificateTemplateId)
|
certificateTemplateId: z.string().describe(SSH_CERTIFICATE_TEMPLATES.DELETE.certificateTemplateId)
|
||||||
}),
|
}),
|
||||||
|
@ -7,6 +7,7 @@ import { isValidHostname } from "@app/ee/services/ssh-host/ssh-host-validators";
|
|||||||
import { SSH_HOSTS } from "@app/lib/api-docs";
|
import { SSH_HOSTS } from "@app/lib/api-docs";
|
||||||
import { ms } from "@app/lib/ms";
|
import { ms } from "@app/lib/ms";
|
||||||
import { publicSshCaLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { publicSshCaLimit, readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@ -96,10 +97,12 @@ export const registerSshHostRouter = async (server: FastifyZodProvider) => {
|
|||||||
hostname: z
|
hostname: z
|
||||||
.string()
|
.string()
|
||||||
.min(1)
|
.min(1)
|
||||||
|
.trim()
|
||||||
.refine((v) => isValidHostname(v), {
|
.refine((v) => isValidHostname(v), {
|
||||||
message: "Hostname must be a valid hostname"
|
message: "Hostname must be a valid hostname"
|
||||||
})
|
})
|
||||||
.describe(SSH_HOSTS.CREATE.hostname),
|
.describe(SSH_HOSTS.CREATE.hostname),
|
||||||
|
alias: slugSchema({ min: 0, max: 64, field: "alias" }).describe(SSH_HOSTS.CREATE.alias).default(""),
|
||||||
userCertTtl: z
|
userCertTtl: z
|
||||||
.string()
|
.string()
|
||||||
.refine((val) => ms(val) > 0, "TTL must be a positive number")
|
.refine((val) => ms(val) > 0, "TTL must be a positive number")
|
||||||
@ -138,6 +141,7 @@ export const registerSshHostRouter = async (server: FastifyZodProvider) => {
|
|||||||
metadata: {
|
metadata: {
|
||||||
sshHostId: host.id,
|
sshHostId: host.id,
|
||||||
hostname: host.hostname,
|
hostname: host.hostname,
|
||||||
|
alias: host.alias ?? null,
|
||||||
userCertTtl: host.userCertTtl,
|
userCertTtl: host.userCertTtl,
|
||||||
hostCertTtl: host.hostCertTtl,
|
hostCertTtl: host.hostCertTtl,
|
||||||
loginMappings: host.loginMappings,
|
loginMappings: host.loginMappings,
|
||||||
@ -166,12 +170,14 @@ export const registerSshHostRouter = async (server: FastifyZodProvider) => {
|
|||||||
body: z.object({
|
body: z.object({
|
||||||
hostname: z
|
hostname: z
|
||||||
.string()
|
.string()
|
||||||
|
.trim()
|
||||||
.min(1)
|
.min(1)
|
||||||
.refine((v) => isValidHostname(v), {
|
.refine((v) => isValidHostname(v), {
|
||||||
message: "Hostname must be a valid hostname"
|
message: "Hostname must be a valid hostname"
|
||||||
})
|
})
|
||||||
.optional()
|
.optional()
|
||||||
.describe(SSH_HOSTS.UPDATE.hostname),
|
.describe(SSH_HOSTS.UPDATE.hostname),
|
||||||
|
alias: slugSchema({ min: 0, max: 64, field: "alias" }).describe(SSH_HOSTS.UPDATE.alias).optional(),
|
||||||
userCertTtl: z
|
userCertTtl: z
|
||||||
.string()
|
.string()
|
||||||
.refine((val) => ms(val) > 0, "TTL must be a positive number")
|
.refine((val) => ms(val) > 0, "TTL must be a positive number")
|
||||||
@ -208,6 +214,7 @@ export const registerSshHostRouter = async (server: FastifyZodProvider) => {
|
|||||||
metadata: {
|
metadata: {
|
||||||
sshHostId: host.id,
|
sshHostId: host.id,
|
||||||
hostname: host.hostname,
|
hostname: host.hostname,
|
||||||
|
alias: host.alias,
|
||||||
userCertTtl: host.userCertTtl,
|
userCertTtl: host.userCertTtl,
|
||||||
hostCertTtl: host.hostCertTtl,
|
hostCertTtl: host.hostCertTtl,
|
||||||
loginMappings: host.loginMappings,
|
loginMappings: host.loginMappings,
|
||||||
|
@ -4,7 +4,7 @@ import { z } from "zod";
|
|||||||
import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-types";
|
import { IdentityProjectAdditionalPrivilegeTemporaryMode } from "@app/ee/services/identity-project-additional-privilege-v2/identity-project-additional-privilege-v2-types";
|
||||||
import { checkForInvalidPermissionCombination } from "@app/ee/services/permission/permission-fns";
|
import { checkForInvalidPermissionCombination } from "@app/ee/services/permission/permission-fns";
|
||||||
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
|
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
|
||||||
import { IDENTITY_ADDITIONAL_PRIVILEGE_V2 } from "@app/lib/api-docs";
|
import { ApiDocsTags, IDENTITY_ADDITIONAL_PRIVILEGE_V2 } from "@app/lib/api-docs";
|
||||||
import { ms } from "@app/lib/ms";
|
import { ms } from "@app/lib/ms";
|
||||||
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
@ -21,6 +21,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
|
||||||
description: "Add an additional privilege for identity.",
|
description: "Add an additional privilege for identity.",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -84,6 +86,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
|
||||||
description: "Update a specific identity privilege.",
|
description: "Update a specific identity privilege.",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -148,6 +152,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
|
||||||
description: "Delete the specified identity privilege.",
|
description: "Delete the specified identity privilege.",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -183,6 +189,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
|
||||||
description: "Retrieve details of a specific privilege by id.",
|
description: "Retrieve details of a specific privilege by id.",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -218,6 +226,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
|
||||||
description: "Retrieve details of a specific privilege by slug.",
|
description: "Retrieve details of a specific privilege by slug.",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -258,6 +268,8 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.IdentitySpecificPrivilegesV2],
|
||||||
description: "List privileges for the specified identity by project.",
|
description: "List privileges for the specified identity by project.",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,7 @@ import { z } from "zod";
|
|||||||
import { ProjectMembershipRole, ProjectRolesSchema } from "@app/db/schemas";
|
import { ProjectMembershipRole, ProjectRolesSchema } from "@app/db/schemas";
|
||||||
import { checkForInvalidPermissionCombination } from "@app/ee/services/permission/permission-fns";
|
import { checkForInvalidPermissionCombination } from "@app/ee/services/permission/permission-fns";
|
||||||
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
|
import { ProjectPermissionV2Schema } from "@app/ee/services/permission/project-permission";
|
||||||
import { PROJECT_ROLE } from "@app/lib/api-docs";
|
import { ApiDocsTags, PROJECT_ROLE } from "@app/lib/api-docs";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { slugSchema } from "@app/server/lib/schemas";
|
import { slugSchema } from "@app/server/lib/schemas";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
@ -20,6 +20,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectRoles],
|
||||||
description: "Create a project role",
|
description: "Create a project role",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -75,6 +77,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectRoles],
|
||||||
description: "Update a project role",
|
description: "Update a project role",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -130,6 +134,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectRoles],
|
||||||
description: "Delete a project role",
|
description: "Delete a project role",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -166,6 +172,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectRoles],
|
||||||
description: "List project role",
|
description: "List project role",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -204,6 +212,8 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.ProjectRoles],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
projectId: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.projectId),
|
projectId: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.projectId),
|
||||||
roleSlug: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.roleSlug)
|
roleSlug: z.string().trim().describe(PROJECT_ROLE.GET_ROLE_BY_SLUG.roleSlug)
|
||||||
|
@ -2,6 +2,7 @@ import { SecretRotation } from "@app/ee/services/secret-rotation-v2/secret-rotat
|
|||||||
|
|
||||||
import { registerAuth0ClientSecretRotationRouter } from "./auth0-client-secret-rotation-router";
|
import { registerAuth0ClientSecretRotationRouter } from "./auth0-client-secret-rotation-router";
|
||||||
import { registerAwsIamUserSecretRotationRouter } from "./aws-iam-user-secret-rotation-router";
|
import { registerAwsIamUserSecretRotationRouter } from "./aws-iam-user-secret-rotation-router";
|
||||||
|
import { registerLdapPasswordRotationRouter } from "./ldap-password-rotation-router";
|
||||||
import { registerMsSqlCredentialsRotationRouter } from "./mssql-credentials-rotation-router";
|
import { registerMsSqlCredentialsRotationRouter } from "./mssql-credentials-rotation-router";
|
||||||
import { registerPostgresCredentialsRotationRouter } from "./postgres-credentials-rotation-router";
|
import { registerPostgresCredentialsRotationRouter } from "./postgres-credentials-rotation-router";
|
||||||
|
|
||||||
@ -14,5 +15,6 @@ export const SECRET_ROTATION_REGISTER_ROUTER_MAP: Record<
|
|||||||
[SecretRotation.PostgresCredentials]: registerPostgresCredentialsRotationRouter,
|
[SecretRotation.PostgresCredentials]: registerPostgresCredentialsRotationRouter,
|
||||||
[SecretRotation.MsSqlCredentials]: registerMsSqlCredentialsRotationRouter,
|
[SecretRotation.MsSqlCredentials]: registerMsSqlCredentialsRotationRouter,
|
||||||
[SecretRotation.Auth0ClientSecret]: registerAuth0ClientSecretRotationRouter,
|
[SecretRotation.Auth0ClientSecret]: registerAuth0ClientSecretRotationRouter,
|
||||||
|
[SecretRotation.LdapPassword]: registerLdapPasswordRotationRouter,
|
||||||
[SecretRotation.AwsIamUserSecret]: registerAwsIamUserSecretRotationRouter
|
[SecretRotation.AwsIamUserSecret]: registerAwsIamUserSecretRotationRouter
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
import {
|
||||||
|
CreateLdapPasswordRotationSchema,
|
||||||
|
LdapPasswordRotationGeneratedCredentialsSchema,
|
||||||
|
LdapPasswordRotationSchema,
|
||||||
|
UpdateLdapPasswordRotationSchema
|
||||||
|
} from "@app/ee/services/secret-rotation-v2/ldap-password";
|
||||||
|
import { SecretRotation } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-enums";
|
||||||
|
|
||||||
|
import { registerSecretRotationEndpoints } from "./secret-rotation-v2-endpoints";
|
||||||
|
|
||||||
|
export const registerLdapPasswordRotationRouter = async (server: FastifyZodProvider) =>
|
||||||
|
registerSecretRotationEndpoints({
|
||||||
|
type: SecretRotation.LdapPassword,
|
||||||
|
server,
|
||||||
|
responseSchema: LdapPasswordRotationSchema,
|
||||||
|
createSchema: CreateLdapPasswordRotationSchema,
|
||||||
|
updateSchema: UpdateLdapPasswordRotationSchema,
|
||||||
|
generatedCredentialsSchema: LdapPasswordRotationGeneratedCredentialsSchema
|
||||||
|
});
|
@ -9,7 +9,7 @@ import {
|
|||||||
TSecretRotationV2GeneratedCredentials,
|
TSecretRotationV2GeneratedCredentials,
|
||||||
TSecretRotationV2Input
|
TSecretRotationV2Input
|
||||||
} from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-types";
|
} from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-types";
|
||||||
import { SecretRotations } from "@app/lib/api-docs";
|
import { ApiDocsTags, SecretRotations } from "@app/lib/api-docs";
|
||||||
import { startsWithVowel } from "@app/lib/fn";
|
import { startsWithVowel } from "@app/lib/fn";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
@ -66,6 +66,8 @@ export const registerSecretRotationEndpoints = <
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SecretRotations],
|
||||||
description: `List the ${rotationType} Rotations for the specified project.`,
|
description: `List the ${rotationType} Rotations for the specified project.`,
|
||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
projectId: z.string().trim().min(1, "Project ID required").describe(SecretRotations.LIST(type).projectId)
|
projectId: z.string().trim().min(1, "Project ID required").describe(SecretRotations.LIST(type).projectId)
|
||||||
@ -109,6 +111,8 @@ export const registerSecretRotationEndpoints = <
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SecretRotations],
|
||||||
description: `Get the specified ${rotationType} Rotation by ID.`,
|
description: `Get the specified ${rotationType} Rotation by ID.`,
|
||||||
params: z.object({
|
params: z.object({
|
||||||
rotationId: z.string().uuid().describe(SecretRotations.GET_BY_ID(type).rotationId)
|
rotationId: z.string().uuid().describe(SecretRotations.GET_BY_ID(type).rotationId)
|
||||||
@ -151,6 +155,8 @@ export const registerSecretRotationEndpoints = <
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SecretRotations],
|
||||||
description: `Get the specified ${rotationType} Rotation by name, secret path, environment and project ID.`,
|
description: `Get the specified ${rotationType} Rotation by name, secret path, environment and project ID.`,
|
||||||
params: z.object({
|
params: z.object({
|
||||||
rotationName: z
|
rotationName: z
|
||||||
@ -215,6 +221,8 @@ export const registerSecretRotationEndpoints = <
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SecretRotations],
|
||||||
description: `Create ${
|
description: `Create ${
|
||||||
startsWithVowel(rotationType) ? "an" : "a"
|
startsWithVowel(rotationType) ? "an" : "a"
|
||||||
} ${rotationType} Rotation for the specified project.`,
|
} ${rotationType} Rotation for the specified project.`,
|
||||||
@ -254,6 +262,8 @@ export const registerSecretRotationEndpoints = <
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SecretRotations],
|
||||||
description: `Update the specified ${rotationType} Rotation.`,
|
description: `Update the specified ${rotationType} Rotation.`,
|
||||||
params: z.object({
|
params: z.object({
|
||||||
rotationId: z.string().uuid().describe(SecretRotations.UPDATE(type).rotationId)
|
rotationId: z.string().uuid().describe(SecretRotations.UPDATE(type).rotationId)
|
||||||
@ -296,6 +306,8 @@ export const registerSecretRotationEndpoints = <
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SecretRotations],
|
||||||
description: `Delete the specified ${rotationType} Rotation.`,
|
description: `Delete the specified ${rotationType} Rotation.`,
|
||||||
params: z.object({
|
params: z.object({
|
||||||
rotationId: z.string().uuid().describe(SecretRotations.DELETE(type).rotationId)
|
rotationId: z.string().uuid().describe(SecretRotations.DELETE(type).rotationId)
|
||||||
@ -349,6 +361,8 @@ export const registerSecretRotationEndpoints = <
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SecretRotations],
|
||||||
description: `Get the generated credentials for the specified ${rotationType} Rotation.`,
|
description: `Get the generated credentials for the specified ${rotationType} Rotation.`,
|
||||||
params: z.object({
|
params: z.object({
|
||||||
rotationId: z.string().uuid().describe(SecretRotations.GET_GENERATED_CREDENTIALS_BY_ID(type).rotationId)
|
rotationId: z.string().uuid().describe(SecretRotations.GET_GENERATED_CREDENTIALS_BY_ID(type).rotationId)
|
||||||
@ -402,6 +416,8 @@ export const registerSecretRotationEndpoints = <
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SecretRotations],
|
||||||
description: `Rotate the generated credentials for the specified ${rotationType} Rotation.`,
|
description: `Rotate the generated credentials for the specified ${rotationType} Rotation.`,
|
||||||
params: z.object({
|
params: z.object({
|
||||||
rotationId: z.string().uuid().describe(SecretRotations.ROTATE(type).rotationId)
|
rotationId: z.string().uuid().describe(SecretRotations.ROTATE(type).rotationId)
|
||||||
|
@ -3,10 +3,11 @@ import { z } from "zod";
|
|||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { Auth0ClientSecretRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/auth0-client-secret";
|
import { Auth0ClientSecretRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/auth0-client-secret";
|
||||||
import { AwsIamUserSecretRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/aws-iam-user-secret";
|
import { AwsIamUserSecretRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/aws-iam-user-secret";
|
||||||
|
import { LdapPasswordRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/ldap-password";
|
||||||
import { MsSqlCredentialsRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/mssql-credentials";
|
import { MsSqlCredentialsRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/mssql-credentials";
|
||||||
import { PostgresCredentialsRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/postgres-credentials";
|
import { PostgresCredentialsRotationListItemSchema } from "@app/ee/services/secret-rotation-v2/postgres-credentials";
|
||||||
import { SecretRotationV2Schema } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-union-schema";
|
import { SecretRotationV2Schema } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-union-schema";
|
||||||
import { SecretRotations } from "@app/lib/api-docs";
|
import { ApiDocsTags, SecretRotations } from "@app/lib/api-docs";
|
||||||
import { readLimit } from "@app/server/config/rateLimiter";
|
import { readLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@ -15,6 +16,7 @@ const SecretRotationV2OptionsSchema = z.discriminatedUnion("type", [
|
|||||||
PostgresCredentialsRotationListItemSchema,
|
PostgresCredentialsRotationListItemSchema,
|
||||||
MsSqlCredentialsRotationListItemSchema,
|
MsSqlCredentialsRotationListItemSchema,
|
||||||
Auth0ClientSecretRotationListItemSchema,
|
Auth0ClientSecretRotationListItemSchema,
|
||||||
|
LdapPasswordRotationListItemSchema,
|
||||||
AwsIamUserSecretRotationListItemSchema
|
AwsIamUserSecretRotationListItemSchema
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -26,6 +28,8 @@ export const registerSecretRotationV2Router = async (server: FastifyZodProvider)
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SecretRotations],
|
||||||
description: "List the available Secret Rotation Options.",
|
description: "List the available Secret Rotation Options.",
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@ -47,6 +51,8 @@ export const registerSecretRotationV2Router = async (server: FastifyZodProvider)
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.SecretRotations],
|
||||||
description: "List all the Secret Rotations for the specified project.",
|
description: "List all the Secret Rotations for the specified project.",
|
||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
projectId: z.string().trim().min(1, "Project ID required").describe(SecretRotations.LIST().projectId)
|
projectId: z.string().trim().min(1, "Project ID required").describe(SecretRotations.LIST().projectId)
|
||||||
|
@ -0,0 +1,101 @@
|
|||||||
|
import { ForbiddenError } from "@casl/ability";
|
||||||
|
import jwt from "jsonwebtoken";
|
||||||
|
|
||||||
|
import { ActionProjectType } from "@app/db/schemas";
|
||||||
|
import { getConfig } from "@app/lib/config/env";
|
||||||
|
import { ForbiddenRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
|
import { ActorType } from "@app/services/auth/auth-type";
|
||||||
|
import { TProjectDALFactory } from "@app/services/project/project-dal";
|
||||||
|
|
||||||
|
import { TPermissionServiceFactory } from "../permission/permission-service";
|
||||||
|
import {
|
||||||
|
ProjectPermissionIdentityActions,
|
||||||
|
ProjectPermissionMemberActions,
|
||||||
|
ProjectPermissionSub
|
||||||
|
} from "../permission/project-permission";
|
||||||
|
import { TAssumeProjectPrivilegeDTO } from "./assume-privilege-types";
|
||||||
|
|
||||||
|
type TAssumePrivilegeServiceFactoryDep = {
|
||||||
|
projectDAL: Pick<TProjectDALFactory, "findById">;
|
||||||
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TAssumePrivilegeServiceFactory = ReturnType<typeof assumePrivilegeServiceFactory>;
|
||||||
|
|
||||||
|
export const assumePrivilegeServiceFactory = ({ projectDAL, permissionService }: TAssumePrivilegeServiceFactoryDep) => {
|
||||||
|
const assumeProjectPrivileges = async ({
|
||||||
|
targetActorType,
|
||||||
|
targetActorId,
|
||||||
|
projectId,
|
||||||
|
actorPermissionDetails,
|
||||||
|
tokenVersionId
|
||||||
|
}: TAssumeProjectPrivilegeDTO) => {
|
||||||
|
const project = await projectDAL.findById(projectId);
|
||||||
|
if (!project) throw new NotFoundError({ message: `Project with ID '${projectId}' not found` });
|
||||||
|
const { permission } = await permissionService.getProjectPermission({
|
||||||
|
actor: actorPermissionDetails.type,
|
||||||
|
actorId: actorPermissionDetails.id,
|
||||||
|
projectId,
|
||||||
|
actorAuthMethod: actorPermissionDetails.authMethod,
|
||||||
|
actorOrgId: actorPermissionDetails.orgId,
|
||||||
|
actionProjectType: ActionProjectType.Any
|
||||||
|
});
|
||||||
|
|
||||||
|
if (targetActorType === ActorType.USER) {
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionMemberActions.AssumePrivileges,
|
||||||
|
ProjectPermissionSub.Member
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionIdentityActions.AssumePrivileges,
|
||||||
|
ProjectPermissionSub.Identity
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check entity is part of project
|
||||||
|
await permissionService.getProjectPermission({
|
||||||
|
actor: targetActorType,
|
||||||
|
actorId: targetActorId,
|
||||||
|
projectId,
|
||||||
|
actorAuthMethod: actorPermissionDetails.authMethod,
|
||||||
|
actorOrgId: actorPermissionDetails.orgId,
|
||||||
|
actionProjectType: ActionProjectType.Any
|
||||||
|
});
|
||||||
|
|
||||||
|
const appCfg = getConfig();
|
||||||
|
const assumePrivilegesToken = jwt.sign(
|
||||||
|
{
|
||||||
|
tokenVersionId,
|
||||||
|
actorType: targetActorType,
|
||||||
|
actorId: targetActorId,
|
||||||
|
projectId,
|
||||||
|
requesterId: actorPermissionDetails.id
|
||||||
|
},
|
||||||
|
appCfg.AUTH_SECRET,
|
||||||
|
{ expiresIn: "1hr" }
|
||||||
|
);
|
||||||
|
|
||||||
|
return { actorType: targetActorType, actorId: targetActorId, projectId, assumePrivilegesToken };
|
||||||
|
};
|
||||||
|
|
||||||
|
const verifyAssumePrivilegeToken = (token: string, tokenVersionId: string) => {
|
||||||
|
const appCfg = getConfig();
|
||||||
|
const decodedToken = jwt.verify(token, appCfg.AUTH_SECRET) as {
|
||||||
|
tokenVersionId: string;
|
||||||
|
projectId: string;
|
||||||
|
requesterId: string;
|
||||||
|
actorType: ActorType;
|
||||||
|
actorId: string;
|
||||||
|
};
|
||||||
|
if (decodedToken.tokenVersionId !== tokenVersionId) {
|
||||||
|
throw new ForbiddenRequestError({ message: "Invalid token version" });
|
||||||
|
}
|
||||||
|
return decodedToken;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
assumeProjectPrivileges,
|
||||||
|
verifyAssumePrivilegeToken
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,10 @@
|
|||||||
|
import { OrgServiceActor } from "@app/lib/types";
|
||||||
|
import { ActorType } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
|
export type TAssumeProjectPrivilegeDTO = {
|
||||||
|
targetActorType: ActorType.USER | ActorType.IDENTITY;
|
||||||
|
targetActorId: string;
|
||||||
|
projectId: string;
|
||||||
|
tokenVersionId: string;
|
||||||
|
actorPermissionDetails: OrgServiceActor;
|
||||||
|
};
|
@ -234,6 +234,7 @@ export enum EventType {
|
|||||||
GET_PROJECT_KMS_BACKUP = "get-project-kms-backup",
|
GET_PROJECT_KMS_BACKUP = "get-project-kms-backup",
|
||||||
LOAD_PROJECT_KMS_BACKUP = "load-project-kms-backup",
|
LOAD_PROJECT_KMS_BACKUP = "load-project-kms-backup",
|
||||||
ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project",
|
ORG_ADMIN_ACCESS_PROJECT = "org-admin-accessed-project",
|
||||||
|
ORG_ADMIN_BYPASS_SSO = "org-admin-bypassed-sso",
|
||||||
CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template",
|
CREATE_CERTIFICATE_TEMPLATE = "create-certificate-template",
|
||||||
UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template",
|
UPDATE_CERTIFICATE_TEMPLATE = "update-certificate-template",
|
||||||
DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template",
|
DELETE_CERTIFICATE_TEMPLATE = "delete-certificate-template",
|
||||||
@ -248,6 +249,8 @@ export enum EventType {
|
|||||||
DELETE_SLACK_INTEGRATION = "delete-slack-integration",
|
DELETE_SLACK_INTEGRATION = "delete-slack-integration",
|
||||||
GET_PROJECT_SLACK_CONFIG = "get-project-slack-config",
|
GET_PROJECT_SLACK_CONFIG = "get-project-slack-config",
|
||||||
UPDATE_PROJECT_SLACK_CONFIG = "update-project-slack-config",
|
UPDATE_PROJECT_SLACK_CONFIG = "update-project-slack-config",
|
||||||
|
GET_PROJECT_SSH_CONFIG = "get-project-ssh-config",
|
||||||
|
UPDATE_PROJECT_SSH_CONFIG = "update-project-ssh-config",
|
||||||
INTEGRATION_SYNCED = "integration-synced",
|
INTEGRATION_SYNCED = "integration-synced",
|
||||||
CREATE_CMEK = "create-cmek",
|
CREATE_CMEK = "create-cmek",
|
||||||
UPDATE_CMEK = "update-cmek",
|
UPDATE_CMEK = "update-cmek",
|
||||||
@ -317,7 +320,9 @@ export enum EventType {
|
|||||||
DELETE_SECRET_ROTATION = "delete-secret-rotation",
|
DELETE_SECRET_ROTATION = "delete-secret-rotation",
|
||||||
SECRET_ROTATION_ROTATE_SECRETS = "secret-rotation-rotate-secrets",
|
SECRET_ROTATION_ROTATE_SECRETS = "secret-rotation-rotate-secrets",
|
||||||
|
|
||||||
PROJECT_ACCESS_REQUEST = "project-access-request"
|
PROJECT_ACCESS_REQUEST = "project-access-request",
|
||||||
|
PROJECT_ASSUME_PRIVILEGE_SESSION_START = "project-assume-privileges-session-start",
|
||||||
|
PROJECT_ASSUME_PRIVILEGE_SESSION_END = "project-assume-privileges-session-end"
|
||||||
}
|
}
|
||||||
|
|
||||||
export const filterableSecretEvents: EventType[] = [
|
export const filterableSecretEvents: EventType[] = [
|
||||||
@ -1491,6 +1496,7 @@ interface CreateSshHost {
|
|||||||
metadata: {
|
metadata: {
|
||||||
sshHostId: string;
|
sshHostId: string;
|
||||||
hostname: string;
|
hostname: string;
|
||||||
|
alias: string | null;
|
||||||
userCertTtl: string;
|
userCertTtl: string;
|
||||||
hostCertTtl: string;
|
hostCertTtl: string;
|
||||||
loginMappings: {
|
loginMappings: {
|
||||||
@ -1509,6 +1515,7 @@ interface UpdateSshHost {
|
|||||||
metadata: {
|
metadata: {
|
||||||
sshHostId: string;
|
sshHostId: string;
|
||||||
hostname?: string;
|
hostname?: string;
|
||||||
|
alias?: string | null;
|
||||||
userCertTtl?: string;
|
userCertTtl?: string;
|
||||||
hostCertTtl?: string;
|
hostCertTtl?: string;
|
||||||
loginMappings?: {
|
loginMappings?: {
|
||||||
@ -1907,6 +1914,11 @@ interface OrgAdminAccessProjectEvent {
|
|||||||
}; // no metadata yet
|
}; // no metadata yet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface OrgAdminBypassSSOEvent {
|
||||||
|
type: EventType.ORG_ADMIN_BYPASS_SSO;
|
||||||
|
metadata: Record<string, string>; // no metadata yet
|
||||||
|
}
|
||||||
|
|
||||||
interface CreateCertificateTemplateEstConfig {
|
interface CreateCertificateTemplateEstConfig {
|
||||||
type: EventType.CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG;
|
type: EventType.CREATE_CERTIFICATE_TEMPLATE_EST_CONFIG;
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -1986,6 +1998,25 @@ interface GetProjectSlackConfig {
|
|||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface GetProjectSshConfig {
|
||||||
|
type: EventType.GET_PROJECT_SSH_CONFIG;
|
||||||
|
metadata: {
|
||||||
|
id: string;
|
||||||
|
projectId: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UpdateProjectSshConfig {
|
||||||
|
type: EventType.UPDATE_PROJECT_SSH_CONFIG;
|
||||||
|
metadata: {
|
||||||
|
id: string;
|
||||||
|
projectId: string;
|
||||||
|
defaultUserSshCaId?: string | null;
|
||||||
|
defaultHostSshCaId?: string | null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
interface IntegrationSyncedEvent {
|
interface IntegrationSyncedEvent {
|
||||||
type: EventType.INTEGRATION_SYNCED;
|
type: EventType.INTEGRATION_SYNCED;
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -2425,6 +2456,29 @@ interface ProjectAccessRequestEvent {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ProjectAssumePrivilegesEvent {
|
||||||
|
type: EventType.PROJECT_ASSUME_PRIVILEGE_SESSION_START;
|
||||||
|
metadata: {
|
||||||
|
projectId: string;
|
||||||
|
requesterId: string;
|
||||||
|
requesterEmail: string;
|
||||||
|
targetActorType: ActorType;
|
||||||
|
targetActorId: string;
|
||||||
|
duration: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ProjectAssumePrivilegesExitEvent {
|
||||||
|
type: EventType.PROJECT_ASSUME_PRIVILEGE_SESSION_END;
|
||||||
|
metadata: {
|
||||||
|
projectId: string;
|
||||||
|
requesterId: string;
|
||||||
|
requesterEmail: string;
|
||||||
|
targetActorType: ActorType;
|
||||||
|
targetActorId: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
interface SetupKmipEvent {
|
interface SetupKmipEvent {
|
||||||
type: EventType.SETUP_KMIP;
|
type: EventType.SETUP_KMIP;
|
||||||
metadata: {
|
metadata: {
|
||||||
@ -2656,6 +2710,7 @@ export type Event =
|
|||||||
| GetProjectKmsBackupEvent
|
| GetProjectKmsBackupEvent
|
||||||
| LoadProjectKmsBackupEvent
|
| LoadProjectKmsBackupEvent
|
||||||
| OrgAdminAccessProjectEvent
|
| OrgAdminAccessProjectEvent
|
||||||
|
| OrgAdminBypassSSOEvent
|
||||||
| CreateCertificateTemplate
|
| CreateCertificateTemplate
|
||||||
| UpdateCertificateTemplate
|
| UpdateCertificateTemplate
|
||||||
| GetCertificateTemplate
|
| GetCertificateTemplate
|
||||||
@ -2670,6 +2725,8 @@ export type Event =
|
|||||||
| GetSlackIntegration
|
| GetSlackIntegration
|
||||||
| UpdateProjectSlackConfig
|
| UpdateProjectSlackConfig
|
||||||
| GetProjectSlackConfig
|
| GetProjectSlackConfig
|
||||||
|
| GetProjectSshConfig
|
||||||
|
| UpdateProjectSshConfig
|
||||||
| IntegrationSyncedEvent
|
| IntegrationSyncedEvent
|
||||||
| CreateCmekEvent
|
| CreateCmekEvent
|
||||||
| UpdateCmekEvent
|
| UpdateCmekEvent
|
||||||
@ -2727,6 +2784,8 @@ export type Event =
|
|||||||
| KmipOperationLocateEvent
|
| KmipOperationLocateEvent
|
||||||
| KmipOperationRegisterEvent
|
| KmipOperationRegisterEvent
|
||||||
| ProjectAccessRequestEvent
|
| ProjectAccessRequestEvent
|
||||||
|
| ProjectAssumePrivilegesEvent
|
||||||
|
| ProjectAssumePrivilegesExitEvent
|
||||||
| CreateSecretRequestEvent
|
| CreateSecretRequestEvent
|
||||||
| SecretApprovalRequestReview
|
| SecretApprovalRequestReview
|
||||||
| GetSecretRotationsEvent
|
| GetSecretRotationsEvent
|
||||||
|
@ -130,7 +130,17 @@ export const dynamicSecretLeaseServiceFactory = ({
|
|||||||
if (expireAt > maxExpiryDate) throw new BadRequestError({ message: "TTL cannot be larger than max TTL" });
|
if (expireAt > maxExpiryDate) throw new BadRequestError({ message: "TTL cannot be larger than max TTL" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const { entityId, data } = await selectedProvider.create(decryptedStoredInput, expireAt.getTime());
|
let result;
|
||||||
|
try {
|
||||||
|
result = await selectedProvider.create(decryptedStoredInput, expireAt.getTime());
|
||||||
|
} catch (error: unknown) {
|
||||||
|
if (error && typeof error === "object" && error !== null && "sqlMessage" in error) {
|
||||||
|
throw new BadRequestError({ message: error.sqlMessage as string });
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
const { entityId, data } = result;
|
||||||
|
|
||||||
const dynamicSecretLease = await dynamicSecretLeaseDAL.create({
|
const dynamicSecretLease = await dynamicSecretLeaseDAL.create({
|
||||||
expireAt,
|
expireAt,
|
||||||
version: 1,
|
version: 1,
|
||||||
|
@ -83,18 +83,26 @@ export const externalKmsServiceFactory = ({
|
|||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
|
|
||||||
// if missing kms key this generate a new kms key id and returns new provider input
|
try {
|
||||||
const newProviderInput = await externalKms.generateInputKmsKey();
|
// if missing kms key this generate a new kms key id and returns new provider input
|
||||||
sanitizedProviderInput = JSON.stringify(newProviderInput);
|
const newProviderInput = await externalKms.generateInputKmsKey();
|
||||||
|
sanitizedProviderInput = JSON.stringify(newProviderInput);
|
||||||
|
|
||||||
await externalKms.validateConnection();
|
await externalKms.validateConnection();
|
||||||
|
} finally {
|
||||||
|
await externalKms.cleanup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KmsProviders.Gcp:
|
case KmsProviders.Gcp:
|
||||||
{
|
{
|
||||||
const externalKms = await GcpKmsProviderFactory({ inputs: provider.inputs });
|
const externalKms = await GcpKmsProviderFactory({ inputs: provider.inputs });
|
||||||
await externalKms.validateConnection();
|
try {
|
||||||
sanitizedProviderInput = JSON.stringify(provider.inputs);
|
await externalKms.validateConnection();
|
||||||
|
sanitizedProviderInput = JSON.stringify(provider.inputs);
|
||||||
|
} finally {
|
||||||
|
await externalKms.cleanup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -186,8 +194,12 @@ export const externalKmsServiceFactory = ({
|
|||||||
);
|
);
|
||||||
const updatedProviderInput = { ...decryptedProviderInput, ...provider.inputs };
|
const updatedProviderInput = { ...decryptedProviderInput, ...provider.inputs };
|
||||||
const externalKms = await AwsKmsProviderFactory({ inputs: updatedProviderInput });
|
const externalKms = await AwsKmsProviderFactory({ inputs: updatedProviderInput });
|
||||||
await externalKms.validateConnection();
|
try {
|
||||||
sanitizedProviderInput = JSON.stringify(updatedProviderInput);
|
await externalKms.validateConnection();
|
||||||
|
sanitizedProviderInput = JSON.stringify(updatedProviderInput);
|
||||||
|
} finally {
|
||||||
|
await externalKms.cleanup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KmsProviders.Gcp:
|
case KmsProviders.Gcp:
|
||||||
@ -197,8 +209,12 @@ export const externalKmsServiceFactory = ({
|
|||||||
);
|
);
|
||||||
const updatedProviderInput = { ...decryptedProviderInput, ...provider.inputs };
|
const updatedProviderInput = { ...decryptedProviderInput, ...provider.inputs };
|
||||||
const externalKms = await GcpKmsProviderFactory({ inputs: updatedProviderInput });
|
const externalKms = await GcpKmsProviderFactory({ inputs: updatedProviderInput });
|
||||||
await externalKms.validateConnection();
|
try {
|
||||||
sanitizedProviderInput = JSON.stringify(updatedProviderInput);
|
await externalKms.validateConnection();
|
||||||
|
sanitizedProviderInput = JSON.stringify(updatedProviderInput);
|
||||||
|
} finally {
|
||||||
|
await externalKms.cleanup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -368,7 +384,11 @@ export const externalKmsServiceFactory = ({
|
|||||||
|
|
||||||
const fetchGcpKeys = async ({ credential, gcpRegion }: Pick<TExternalKmsGcpSchema, "credential" | "gcpRegion">) => {
|
const fetchGcpKeys = async ({ credential, gcpRegion }: Pick<TExternalKmsGcpSchema, "credential" | "gcpRegion">) => {
|
||||||
const externalKms = await GcpKmsProviderFactory({ inputs: { credential, gcpRegion, keyName: "" } });
|
const externalKms = await GcpKmsProviderFactory({ inputs: { credential, gcpRegion, keyName: "" } });
|
||||||
return externalKms.getKeysList();
|
try {
|
||||||
|
return await externalKms.getKeysList();
|
||||||
|
} finally {
|
||||||
|
await externalKms.cleanup();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -102,10 +102,19 @@ export const AwsKmsProviderFactory = async ({ inputs }: AwsKmsProviderArgs): Pro
|
|||||||
return { data: Buffer.from(decryptionCommand.Plaintext) };
|
return { data: Buffer.from(decryptionCommand.Plaintext) };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cleanup = async () => {
|
||||||
|
try {
|
||||||
|
awsClient.destroy();
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error("Failed to cleanup AWS KMS client", { cause: error });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
generateInputKmsKey,
|
generateInputKmsKey,
|
||||||
validateConnection,
|
validateConnection,
|
||||||
encrypt,
|
encrypt,
|
||||||
decrypt
|
decrypt,
|
||||||
|
cleanup
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -45,6 +45,14 @@ export const GcpKmsProviderFactory = async ({ inputs }: GcpKmsProviderArgs): Pro
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cleanup = async () => {
|
||||||
|
try {
|
||||||
|
await gcpKmsClient.close();
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error("Failed to cleanup GCP KMS client", { cause: error });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Used when adding the KMS to fetch the list of keys in specified region
|
// Used when adding the KMS to fetch the list of keys in specified region
|
||||||
const getKeysList = async () => {
|
const getKeysList = async () => {
|
||||||
try {
|
try {
|
||||||
@ -108,6 +116,7 @@ export const GcpKmsProviderFactory = async ({ inputs }: GcpKmsProviderArgs): Pro
|
|||||||
validateConnection,
|
validateConnection,
|
||||||
getKeysList,
|
getKeysList,
|
||||||
encrypt,
|
encrypt,
|
||||||
decrypt
|
decrypt,
|
||||||
|
cleanup
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -98,4 +98,5 @@ export type TExternalKmsProviderFns = {
|
|||||||
validateConnection: () => Promise<boolean>;
|
validateConnection: () => Promise<boolean>;
|
||||||
encrypt: (data: Buffer) => Promise<{ encryptedBlob: Buffer }>;
|
encrypt: (data: Buffer) => Promise<{ encryptedBlob: Buffer }>;
|
||||||
decrypt: (encryptedBlob: Buffer) => Promise<{ data: Buffer }>;
|
decrypt: (encryptedBlob: Buffer) => Promise<{ data: Buffer }>;
|
||||||
|
cleanup: () => Promise<void>;
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
import { TDbClient } from "@app/db";
|
||||||
|
import { TableName } from "@app/db/schemas";
|
||||||
|
import { ormify } from "@app/lib/knex";
|
||||||
|
|
||||||
|
export type TGithubOrgSyncDALFactory = ReturnType<typeof githubOrgSyncDALFactory>;
|
||||||
|
|
||||||
|
export const githubOrgSyncDALFactory = (db: TDbClient) => {
|
||||||
|
const orm = ormify(db, TableName.GithubOrgSyncConfig);
|
||||||
|
return orm;
|
||||||
|
};
|
@ -0,0 +1,354 @@
|
|||||||
|
import { ForbiddenError } from "@casl/ability";
|
||||||
|
import { Octokit } from "@octokit/core";
|
||||||
|
import { paginateGraphQL } from "@octokit/plugin-paginate-graphql";
|
||||||
|
import { Octokit as OctokitRest } from "@octokit/rest";
|
||||||
|
|
||||||
|
import { OrgMembershipRole } from "@app/db/schemas";
|
||||||
|
import { BadRequestError, NotFoundError } from "@app/lib/errors";
|
||||||
|
import { groupBy } from "@app/lib/fn";
|
||||||
|
import { logger } from "@app/lib/logger";
|
||||||
|
import { TKmsServiceFactory } from "@app/services/kms/kms-service";
|
||||||
|
import { KmsDataKey } from "@app/services/kms/kms-types";
|
||||||
|
|
||||||
|
import { TGroupDALFactory } from "../group/group-dal";
|
||||||
|
import { TUserGroupMembershipDALFactory } from "../group/user-group-membership-dal";
|
||||||
|
import { TLicenseServiceFactory } from "../license/license-service";
|
||||||
|
import { OrgPermissionActions, OrgPermissionSubjects } from "../permission/org-permission";
|
||||||
|
import { TPermissionServiceFactory } from "../permission/permission-service";
|
||||||
|
import { TGithubOrgSyncDALFactory } from "./github-org-sync-dal";
|
||||||
|
import { TCreateGithubOrgSyncDTO, TDeleteGithubOrgSyncDTO, TUpdateGithubOrgSyncDTO } from "./github-org-sync-types";
|
||||||
|
|
||||||
|
const OctokitWithPlugin = Octokit.plugin(paginateGraphQL);
|
||||||
|
|
||||||
|
type TGithubOrgSyncServiceFactoryDep = {
|
||||||
|
githubOrgSyncDAL: TGithubOrgSyncDALFactory;
|
||||||
|
permissionService: Pick<TPermissionServiceFactory, "getOrgPermission">;
|
||||||
|
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
|
||||||
|
userGroupMembershipDAL: Pick<
|
||||||
|
TUserGroupMembershipDALFactory,
|
||||||
|
"findGroupMembershipsByUserIdInOrg" | "insertMany" | "delete"
|
||||||
|
>;
|
||||||
|
groupDAL: Pick<TGroupDALFactory, "insertMany" | "transaction" | "find">;
|
||||||
|
licenseService: Pick<TLicenseServiceFactory, "getPlan">;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TGithubOrgSyncServiceFactory = ReturnType<typeof githubOrgSyncServiceFactory>;
|
||||||
|
|
||||||
|
export const githubOrgSyncServiceFactory = ({
|
||||||
|
githubOrgSyncDAL,
|
||||||
|
permissionService,
|
||||||
|
kmsService,
|
||||||
|
userGroupMembershipDAL,
|
||||||
|
groupDAL,
|
||||||
|
licenseService
|
||||||
|
}: TGithubOrgSyncServiceFactoryDep) => {
|
||||||
|
const createGithubOrgSync = async ({
|
||||||
|
githubOrgName,
|
||||||
|
orgPermission,
|
||||||
|
githubOrgAccessToken,
|
||||||
|
isActive
|
||||||
|
}: TCreateGithubOrgSyncDTO) => {
|
||||||
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
|
orgPermission.type,
|
||||||
|
orgPermission.id,
|
||||||
|
orgPermission.orgId,
|
||||||
|
orgPermission.authMethod,
|
||||||
|
orgPermission.orgId
|
||||||
|
);
|
||||||
|
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Create, OrgPermissionSubjects.GithubOrgSync);
|
||||||
|
const plan = await licenseService.getPlan(orgPermission.orgId);
|
||||||
|
if (!plan.githubOrgSync) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Failed to create github organization team sync due to plan restriction. Upgrade plan to create github organization sync."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingConfig = await githubOrgSyncDAL.findOne({ orgId: orgPermission.orgId });
|
||||||
|
if (existingConfig)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: `Organization ${orgPermission.orgId} already has GitHub Organization sync config.`
|
||||||
|
});
|
||||||
|
|
||||||
|
const octokit = new OctokitRest({
|
||||||
|
auth: githubOrgAccessToken,
|
||||||
|
request: {
|
||||||
|
signal: AbortSignal.timeout(5000)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const { data } = await octokit.rest.orgs.get({
|
||||||
|
org: githubOrgName
|
||||||
|
});
|
||||||
|
if (data.login.toLowerCase() !== githubOrgName.toLowerCase())
|
||||||
|
throw new BadRequestError({ message: "Invalid GitHub organisation" });
|
||||||
|
|
||||||
|
const { encryptor } = await kmsService.createCipherPairWithDataKey({
|
||||||
|
type: KmsDataKey.Organization,
|
||||||
|
orgId: orgPermission.orgId
|
||||||
|
});
|
||||||
|
|
||||||
|
const config = await githubOrgSyncDAL.create({
|
||||||
|
orgId: orgPermission.orgId,
|
||||||
|
githubOrgName,
|
||||||
|
isActive,
|
||||||
|
encryptedGithubOrgAccessToken: githubOrgAccessToken
|
||||||
|
? encryptor({ plainText: Buffer.from(githubOrgAccessToken) }).cipherTextBlob
|
||||||
|
: null
|
||||||
|
});
|
||||||
|
|
||||||
|
return config;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateGithubOrgSync = async ({
|
||||||
|
githubOrgName,
|
||||||
|
orgPermission,
|
||||||
|
githubOrgAccessToken,
|
||||||
|
isActive
|
||||||
|
}: TUpdateGithubOrgSyncDTO) => {
|
||||||
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
|
orgPermission.type,
|
||||||
|
orgPermission.id,
|
||||||
|
orgPermission.orgId,
|
||||||
|
orgPermission.authMethod,
|
||||||
|
orgPermission.orgId
|
||||||
|
);
|
||||||
|
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Edit, OrgPermissionSubjects.GithubOrgSync);
|
||||||
|
const plan = await licenseService.getPlan(orgPermission.orgId);
|
||||||
|
if (!plan.githubOrgSync) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Failed to update github organization team sync due to plan restriction. Upgrade plan to update github organization sync."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingConfig = await githubOrgSyncDAL.findOne({ orgId: orgPermission.orgId });
|
||||||
|
if (!existingConfig)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: `Organization ${orgPermission.orgId} GitHub organization sync config missing.`
|
||||||
|
});
|
||||||
|
|
||||||
|
const { encryptor, decryptor } = await kmsService.createCipherPairWithDataKey({
|
||||||
|
type: KmsDataKey.Organization,
|
||||||
|
orgId: orgPermission.orgId
|
||||||
|
});
|
||||||
|
const newData = {
|
||||||
|
githubOrgName: githubOrgName || existingConfig.githubOrgName,
|
||||||
|
githubOrgAccessToken:
|
||||||
|
githubOrgAccessToken ||
|
||||||
|
(existingConfig.encryptedGithubOrgAccessToken
|
||||||
|
? decryptor({ cipherTextBlob: existingConfig.encryptedGithubOrgAccessToken }).toString()
|
||||||
|
: null)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (githubOrgName || githubOrgAccessToken) {
|
||||||
|
const octokit = new OctokitRest({
|
||||||
|
auth: newData.githubOrgAccessToken,
|
||||||
|
request: {
|
||||||
|
signal: AbortSignal.timeout(5000)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const { data } = await octokit.rest.orgs.get({
|
||||||
|
org: newData.githubOrgName
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data.login.toLowerCase() !== newData.githubOrgName.toLowerCase())
|
||||||
|
throw new BadRequestError({ message: "Invalid GitHub organisation" });
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = await githubOrgSyncDAL.updateById(existingConfig.id, {
|
||||||
|
orgId: orgPermission.orgId,
|
||||||
|
githubOrgName: newData.githubOrgName,
|
||||||
|
isActive,
|
||||||
|
encryptedGithubOrgAccessToken: newData.githubOrgAccessToken
|
||||||
|
? encryptor({ plainText: Buffer.from(newData.githubOrgAccessToken) }).cipherTextBlob
|
||||||
|
: null
|
||||||
|
});
|
||||||
|
|
||||||
|
return config;
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteGithubOrgSync = async ({ orgPermission }: TDeleteGithubOrgSyncDTO) => {
|
||||||
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
|
orgPermission.type,
|
||||||
|
orgPermission.id,
|
||||||
|
orgPermission.orgId,
|
||||||
|
orgPermission.authMethod,
|
||||||
|
orgPermission.orgId
|
||||||
|
);
|
||||||
|
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Delete, OrgPermissionSubjects.GithubOrgSync);
|
||||||
|
|
||||||
|
const plan = await licenseService.getPlan(orgPermission.orgId);
|
||||||
|
if (!plan.githubOrgSync) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Failed to delete github organization team sync due to plan restriction. Upgrade plan to delete github organization sync."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingConfig = await githubOrgSyncDAL.findOne({ orgId: orgPermission.orgId });
|
||||||
|
if (!existingConfig)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: `Organization ${orgPermission.orgId} GitHub organization sync config missing.`
|
||||||
|
});
|
||||||
|
|
||||||
|
const config = await githubOrgSyncDAL.deleteById(existingConfig.id);
|
||||||
|
|
||||||
|
return config;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getGithubOrgSync = async ({ orgPermission }: TDeleteGithubOrgSyncDTO) => {
|
||||||
|
const { permission } = await permissionService.getOrgPermission(
|
||||||
|
orgPermission.type,
|
||||||
|
orgPermission.id,
|
||||||
|
orgPermission.orgId,
|
||||||
|
orgPermission.authMethod,
|
||||||
|
orgPermission.orgId
|
||||||
|
);
|
||||||
|
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(OrgPermissionActions.Read, OrgPermissionSubjects.GithubOrgSync);
|
||||||
|
|
||||||
|
const existingConfig = await githubOrgSyncDAL.findOne({ orgId: orgPermission.orgId });
|
||||||
|
if (!existingConfig)
|
||||||
|
throw new NotFoundError({
|
||||||
|
message: `Organization ${orgPermission.orgId} GitHub organization sync config missing.`
|
||||||
|
});
|
||||||
|
|
||||||
|
return existingConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
const syncUserGroups = async (orgId: string, userId: string, accessToken: string) => {
|
||||||
|
const config = await githubOrgSyncDAL.findOne({ orgId });
|
||||||
|
if (!config || !config?.isActive) return;
|
||||||
|
|
||||||
|
const infisicalUserGroups = await userGroupMembershipDAL.findGroupMembershipsByUserIdInOrg(userId, orgId);
|
||||||
|
const infisicalUserGroupSet = new Set(infisicalUserGroups.map((el) => el.groupName));
|
||||||
|
|
||||||
|
const octoRest = new OctokitRest({
|
||||||
|
auth: accessToken,
|
||||||
|
request: {
|
||||||
|
signal: AbortSignal.timeout(5000)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const { data: userOrgMembershipDetails } = await octoRest.rest.orgs
|
||||||
|
.getMembershipForAuthenticatedUser({
|
||||||
|
org: config.githubOrgName
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
logger.error(err, "User not part of GitHub synced organization");
|
||||||
|
throw new BadRequestError({ message: "User not part of GitHub synced organization" });
|
||||||
|
});
|
||||||
|
const username = userOrgMembershipDetails?.user?.login;
|
||||||
|
if (!username) throw new BadRequestError({ message: "User not part of GitHub synced organization" });
|
||||||
|
|
||||||
|
const octokit = new OctokitWithPlugin({
|
||||||
|
auth: accessToken,
|
||||||
|
request: {
|
||||||
|
signal: AbortSignal.timeout(5000)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const data = await octokit.graphql
|
||||||
|
.paginate<{
|
||||||
|
organization: { teams: { totalCount: number; edges: { node: { name: string; description: string } }[] } };
|
||||||
|
}>(
|
||||||
|
`
|
||||||
|
query orgTeams($cursor: String,$org: String!, $username: String!){
|
||||||
|
organization(login: $org) {
|
||||||
|
teams(first: 100, userLogins: [$username], after: $cursor) {
|
||||||
|
totalCount
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
name
|
||||||
|
description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
endCursor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
org: config.githubOrgName,
|
||||||
|
username
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.catch((err) => {
|
||||||
|
if ((err as Error)?.message?.includes("Although you appear to have the correct authorization credential")) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message:
|
||||||
|
"Please check your organization have approved Infisical Oauth application. For more info: https://infisical.com/docs/documentation/platform/github-org-sync#troubleshooting"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw new BadRequestError({ message: (err as Error)?.message });
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
organization: { teams }
|
||||||
|
} = data;
|
||||||
|
const githubUserTeams = teams?.edges?.map((el) => el.node.name.toLowerCase()) || [];
|
||||||
|
const githubUserTeamSet = new Set(githubUserTeams);
|
||||||
|
const githubUserTeamOnInfisical = await groupDAL.find({ orgId, $in: { name: githubUserTeams } });
|
||||||
|
const githubUserTeamOnInfisicalGroupByName = groupBy(githubUserTeamOnInfisical, (i) => i.name);
|
||||||
|
|
||||||
|
const newTeams = githubUserTeams.filter(
|
||||||
|
(el) => !infisicalUserGroupSet.has(el) && !Object.hasOwn(githubUserTeamOnInfisicalGroupByName, el)
|
||||||
|
);
|
||||||
|
const updateTeams = githubUserTeams.filter(
|
||||||
|
(el) => !infisicalUserGroupSet.has(el) && Object.hasOwn(githubUserTeamOnInfisicalGroupByName, el)
|
||||||
|
);
|
||||||
|
const removeFromTeams = infisicalUserGroups.filter((el) => !githubUserTeamSet.has(el.groupName));
|
||||||
|
|
||||||
|
if (newTeams.length || updateTeams.length || removeFromTeams.length) {
|
||||||
|
await groupDAL.transaction(async (tx) => {
|
||||||
|
if (newTeams.length) {
|
||||||
|
const newGroups = await groupDAL.insertMany(
|
||||||
|
newTeams.map((newGroupName) => ({
|
||||||
|
name: newGroupName,
|
||||||
|
role: OrgMembershipRole.Member,
|
||||||
|
slug: newGroupName,
|
||||||
|
orgId
|
||||||
|
})),
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
await userGroupMembershipDAL.insertMany(
|
||||||
|
newGroups.map((el) => ({
|
||||||
|
groupId: el.id,
|
||||||
|
userId
|
||||||
|
})),
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateTeams.length) {
|
||||||
|
await userGroupMembershipDAL.insertMany(
|
||||||
|
updateTeams.map((el) => ({
|
||||||
|
groupId: githubUserTeamOnInfisicalGroupByName[el][0].id,
|
||||||
|
userId
|
||||||
|
})),
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeFromTeams.length) {
|
||||||
|
await userGroupMembershipDAL.delete(
|
||||||
|
{ userId, $in: { groupId: removeFromTeams.map((el) => el.groupId) } },
|
||||||
|
tx
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
createGithubOrgSync,
|
||||||
|
updateGithubOrgSync,
|
||||||
|
deleteGithubOrgSync,
|
||||||
|
getGithubOrgSync,
|
||||||
|
syncUserGroups
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,23 @@
|
|||||||
|
import { OrgServiceActor } from "@app/lib/types";
|
||||||
|
|
||||||
|
export interface TCreateGithubOrgSyncDTO {
|
||||||
|
orgPermission: OrgServiceActor;
|
||||||
|
githubOrgName: string;
|
||||||
|
githubOrgAccessToken?: string;
|
||||||
|
isActive?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TUpdateGithubOrgSyncDTO {
|
||||||
|
orgPermission: OrgServiceActor;
|
||||||
|
githubOrgName?: string;
|
||||||
|
githubOrgAccessToken?: string;
|
||||||
|
isActive?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TDeleteGithubOrgSyncDTO {
|
||||||
|
orgPermission: OrgServiceActor;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TGetGithubOrgSyncDTO {
|
||||||
|
orgPermission: OrgServiceActor;
|
||||||
|
}
|
@ -22,6 +22,7 @@ export const getDefaultOnPremFeatures = (): TFeatureSet => ({
|
|||||||
pitRecovery: false,
|
pitRecovery: false,
|
||||||
ipAllowlisting: false,
|
ipAllowlisting: false,
|
||||||
rbac: false,
|
rbac: false,
|
||||||
|
githubOrgSync: false,
|
||||||
customRateLimits: false,
|
customRateLimits: false,
|
||||||
customAlerts: false,
|
customAlerts: false,
|
||||||
secretAccessInsights: false,
|
secretAccessInsights: false,
|
||||||
|
@ -45,6 +45,7 @@ export type TFeatureSet = {
|
|||||||
auditLogsRetentionDays: 0;
|
auditLogsRetentionDays: 0;
|
||||||
auditLogStreams: false;
|
auditLogStreams: false;
|
||||||
auditLogStreamLimit: 3;
|
auditLogStreamLimit: 3;
|
||||||
|
githubOrgSync: false;
|
||||||
samlSSO: false;
|
samlSSO: false;
|
||||||
hsm: false;
|
hsm: false;
|
||||||
oidcSSO: false;
|
oidcSSO: false;
|
||||||
|
@ -685,10 +685,16 @@ export const oidcConfigServiceFactory = ({
|
|||||||
id_token_signed_response_alg: oidcCfg.jwtSignatureAlgorithm
|
id_token_signed_response_alg: oidcCfg.jwtSignatureAlgorithm
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Check if the OIDC provider supports PKCE
|
||||||
|
const codeChallengeMethods = client.issuer.metadata.code_challenge_methods_supported;
|
||||||
|
const supportsPKCE = Array.isArray(codeChallengeMethods) && codeChallengeMethods.includes("S256");
|
||||||
|
|
||||||
const strategy = new OpenIdStrategy(
|
const strategy = new OpenIdStrategy(
|
||||||
{
|
{
|
||||||
client,
|
client,
|
||||||
passReqToCallback: true
|
passReqToCallback: true,
|
||||||
|
usePKCE: supportsPKCE,
|
||||||
|
params: supportsPKCE ? { code_challenge_method: "S256" } : undefined
|
||||||
},
|
},
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
(_req: any, tokenSet: TokenSet, cb: any) => {
|
(_req: any, tokenSet: TokenSet, cb: any) => {
|
||||||
|
@ -8,7 +8,8 @@ export enum OIDCConfigurationType {
|
|||||||
export enum OIDCJWTSignatureAlgorithm {
|
export enum OIDCJWTSignatureAlgorithm {
|
||||||
RS256 = "RS256",
|
RS256 = "RS256",
|
||||||
HS256 = "HS256",
|
HS256 = "HS256",
|
||||||
RS512 = "RS512"
|
RS512 = "RS512",
|
||||||
|
EDDSA = "EdDSA"
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TOidcLoginDTO = {
|
export type TOidcLoginDTO = {
|
||||||
|
@ -74,6 +74,7 @@ export enum OrgPermissionSubjects {
|
|||||||
IncidentAccount = "incident-contact",
|
IncidentAccount = "incident-contact",
|
||||||
Sso = "sso",
|
Sso = "sso",
|
||||||
Scim = "scim",
|
Scim = "scim",
|
||||||
|
GithubOrgSync = "github-org-sync",
|
||||||
Ldap = "ldap",
|
Ldap = "ldap",
|
||||||
Groups = "groups",
|
Groups = "groups",
|
||||||
Billing = "billing",
|
Billing = "billing",
|
||||||
@ -101,6 +102,7 @@ export type OrgPermissionSet =
|
|||||||
| [OrgPermissionActions, OrgPermissionSubjects.IncidentAccount]
|
| [OrgPermissionActions, OrgPermissionSubjects.IncidentAccount]
|
||||||
| [OrgPermissionActions, OrgPermissionSubjects.Sso]
|
| [OrgPermissionActions, OrgPermissionSubjects.Sso]
|
||||||
| [OrgPermissionActions, OrgPermissionSubjects.Scim]
|
| [OrgPermissionActions, OrgPermissionSubjects.Scim]
|
||||||
|
| [OrgPermissionActions, OrgPermissionSubjects.GithubOrgSync]
|
||||||
| [OrgPermissionActions, OrgPermissionSubjects.Ldap]
|
| [OrgPermissionActions, OrgPermissionSubjects.Ldap]
|
||||||
| [OrgPermissionGroupActions, OrgPermissionSubjects.Groups]
|
| [OrgPermissionGroupActions, OrgPermissionSubjects.Groups]
|
||||||
| [OrgPermissionActions, OrgPermissionSubjects.SecretScanning]
|
| [OrgPermissionActions, OrgPermissionSubjects.SecretScanning]
|
||||||
@ -165,6 +167,10 @@ export const OrgPermissionSchema = z.discriminatedUnion("subject", [
|
|||||||
subject: z.literal(OrgPermissionSubjects.Scim).describe("The entity this permission pertains to."),
|
subject: z.literal(OrgPermissionSubjects.Scim).describe("The entity this permission pertains to."),
|
||||||
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
|
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
|
||||||
}),
|
}),
|
||||||
|
z.object({
|
||||||
|
subject: z.literal(OrgPermissionSubjects.GithubOrgSync).describe("The entity this permission pertains to."),
|
||||||
|
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
|
||||||
|
}),
|
||||||
z.object({
|
z.object({
|
||||||
subject: z.literal(OrgPermissionSubjects.Ldap).describe("The entity this permission pertains to."),
|
subject: z.literal(OrgPermissionSubjects.Ldap).describe("The entity this permission pertains to."),
|
||||||
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
|
action: CASL_ACTION_SCHEMA_NATIVE_ENUM(OrgPermissionActions).describe("Describe what action an entity can take.")
|
||||||
@ -273,6 +279,11 @@ const buildAdminPermission = () => {
|
|||||||
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Scim);
|
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Scim);
|
||||||
can(OrgPermissionActions.Delete, OrgPermissionSubjects.Scim);
|
can(OrgPermissionActions.Delete, OrgPermissionSubjects.Scim);
|
||||||
|
|
||||||
|
can(OrgPermissionActions.Read, OrgPermissionSubjects.GithubOrgSync);
|
||||||
|
can(OrgPermissionActions.Create, OrgPermissionSubjects.GithubOrgSync);
|
||||||
|
can(OrgPermissionActions.Edit, OrgPermissionSubjects.GithubOrgSync);
|
||||||
|
can(OrgPermissionActions.Delete, OrgPermissionSubjects.GithubOrgSync);
|
||||||
|
|
||||||
can(OrgPermissionActions.Read, OrgPermissionSubjects.Ldap);
|
can(OrgPermissionActions.Read, OrgPermissionSubjects.Ldap);
|
||||||
can(OrgPermissionActions.Create, OrgPermissionSubjects.Ldap);
|
can(OrgPermissionActions.Create, OrgPermissionSubjects.Ldap);
|
||||||
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Ldap);
|
can(OrgPermissionActions.Edit, OrgPermissionSubjects.Ldap);
|
||||||
|
@ -551,13 +551,26 @@ export const permissionServiceFactory = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getProjectPermission = async <T extends ActorType>({
|
const getProjectPermission = async <T extends ActorType>({
|
||||||
actor,
|
actor: inputActor,
|
||||||
actorId,
|
actorId: inputActorId,
|
||||||
projectId,
|
projectId,
|
||||||
actorAuthMethod,
|
actorAuthMethod,
|
||||||
actorOrgId,
|
actorOrgId,
|
||||||
actionProjectType
|
actionProjectType
|
||||||
}: TGetProjectPermissionArg): Promise<TProjectPermissionRT<T>> => {
|
}: TGetProjectPermissionArg): Promise<TProjectPermissionRT<T>> => {
|
||||||
|
let actor = inputActor;
|
||||||
|
let actorId = inputActorId;
|
||||||
|
const assumedPrivilegeDetailsCtx = requestContext.get("assumedPrivilegeDetails");
|
||||||
|
if (
|
||||||
|
assumedPrivilegeDetailsCtx &&
|
||||||
|
actor === ActorType.USER &&
|
||||||
|
actorId === assumedPrivilegeDetailsCtx.requesterId &&
|
||||||
|
projectId === assumedPrivilegeDetailsCtx.projectId
|
||||||
|
) {
|
||||||
|
actor = assumedPrivilegeDetailsCtx.actorType;
|
||||||
|
actorId = assumedPrivilegeDetailsCtx.actorId;
|
||||||
|
}
|
||||||
|
|
||||||
switch (actor) {
|
switch (actor) {
|
||||||
case ActorType.USER:
|
case ActorType.USER:
|
||||||
return getUserProjectPermission({
|
return getUserProjectPermission({
|
||||||
|
@ -50,7 +50,8 @@ export enum ProjectPermissionIdentityActions {
|
|||||||
Create = "create",
|
Create = "create",
|
||||||
Edit = "edit",
|
Edit = "edit",
|
||||||
Delete = "delete",
|
Delete = "delete",
|
||||||
GrantPrivileges = "grant-privileges"
|
GrantPrivileges = "grant-privileges",
|
||||||
|
AssumePrivileges = "assume-privileges"
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ProjectPermissionMemberActions {
|
export enum ProjectPermissionMemberActions {
|
||||||
@ -58,7 +59,8 @@ export enum ProjectPermissionMemberActions {
|
|||||||
Create = "create",
|
Create = "create",
|
||||||
Edit = "edit",
|
Edit = "edit",
|
||||||
Delete = "delete",
|
Delete = "delete",
|
||||||
GrantPrivileges = "grant-privileges"
|
GrantPrivileges = "grant-privileges",
|
||||||
|
AssumePrivileges = "assume-privileges"
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ProjectPermissionGroupActions {
|
export enum ProjectPermissionGroupActions {
|
||||||
@ -714,7 +716,8 @@ const buildAdminPermissionRules = () => {
|
|||||||
ProjectPermissionMemberActions.Edit,
|
ProjectPermissionMemberActions.Edit,
|
||||||
ProjectPermissionMemberActions.Delete,
|
ProjectPermissionMemberActions.Delete,
|
||||||
ProjectPermissionMemberActions.Read,
|
ProjectPermissionMemberActions.Read,
|
||||||
ProjectPermissionMemberActions.GrantPrivileges
|
ProjectPermissionMemberActions.GrantPrivileges,
|
||||||
|
ProjectPermissionMemberActions.AssumePrivileges
|
||||||
],
|
],
|
||||||
ProjectPermissionSub.Member
|
ProjectPermissionSub.Member
|
||||||
);
|
);
|
||||||
@ -736,7 +739,8 @@ const buildAdminPermissionRules = () => {
|
|||||||
ProjectPermissionIdentityActions.Edit,
|
ProjectPermissionIdentityActions.Edit,
|
||||||
ProjectPermissionIdentityActions.Delete,
|
ProjectPermissionIdentityActions.Delete,
|
||||||
ProjectPermissionIdentityActions.Read,
|
ProjectPermissionIdentityActions.Read,
|
||||||
ProjectPermissionIdentityActions.GrantPrivileges
|
ProjectPermissionIdentityActions.GrantPrivileges,
|
||||||
|
ProjectPermissionIdentityActions.AssumePrivileges
|
||||||
],
|
],
|
||||||
ProjectPermissionSub.Identity
|
ProjectPermissionSub.Identity
|
||||||
);
|
);
|
||||||
@ -965,7 +969,6 @@ const buildMemberPermissionRules = () => {
|
|||||||
can([ProjectPermissionActions.Read], ProjectPermissionSub.PkiAlerts);
|
can([ProjectPermissionActions.Read], ProjectPermissionSub.PkiAlerts);
|
||||||
can([ProjectPermissionActions.Read], ProjectPermissionSub.PkiCollections);
|
can([ProjectPermissionActions.Read], ProjectPermissionSub.PkiCollections);
|
||||||
|
|
||||||
can([ProjectPermissionActions.Read], ProjectPermissionSub.SshCertificateAuthorities);
|
|
||||||
can([ProjectPermissionActions.Read], ProjectPermissionSub.SshCertificates);
|
can([ProjectPermissionActions.Read], ProjectPermissionSub.SshCertificates);
|
||||||
can([ProjectPermissionActions.Create], ProjectPermissionSub.SshCertificates);
|
can([ProjectPermissionActions.Create], ProjectPermissionSub.SshCertificates);
|
||||||
can([ProjectPermissionActions.Read], ProjectPermissionSub.SshCertificateTemplates);
|
can([ProjectPermissionActions.Read], ProjectPermissionSub.SshCertificateTemplates);
|
||||||
@ -1031,7 +1034,6 @@ const buildViewerPermissionRules = () => {
|
|||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.CertificateAuthorities);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.CertificateAuthorities);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.Certificates);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.Certificates);
|
||||||
can(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek);
|
can(ProjectPermissionCmekActions.Read, ProjectPermissionSub.Cmek);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificateAuthorities);
|
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificates);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificates);
|
||||||
can(ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificateTemplates);
|
can(ProjectPermissionActions.Read, ProjectPermissionSub.SshCertificateTemplates);
|
||||||
can(ProjectPermissionSecretSyncActions.Read, ProjectPermissionSub.SecretSyncs);
|
can(ProjectPermissionSecretSyncActions.Read, ProjectPermissionSub.SecretSyncs);
|
||||||
|
@ -33,6 +33,7 @@ export type TApprovalCreateSecretV2Bridge = {
|
|||||||
secretComment?: string;
|
secretComment?: string;
|
||||||
reminderNote?: string | null;
|
reminderNote?: string | null;
|
||||||
reminderRepeatDays?: number | null;
|
reminderRepeatDays?: number | null;
|
||||||
|
secretReminderRecipients?: string[] | null;
|
||||||
skipMultilineEncoding?: boolean;
|
skipMultilineEncoding?: boolean;
|
||||||
metadata?: Record<string, string>;
|
metadata?: Record<string, string>;
|
||||||
secretMetadata?: ResourceMetadataDTO;
|
secretMetadata?: ResourceMetadataDTO;
|
||||||
|
@ -267,7 +267,6 @@ export const secretReplicationServiceFactory = ({
|
|||||||
const sourceLocalSecrets = await secretV2BridgeDAL.find({ folderId: folder.id, type: SecretType.Shared });
|
const sourceLocalSecrets = await secretV2BridgeDAL.find({ folderId: folder.id, type: SecretType.Shared });
|
||||||
const sourceSecretImports = await secretImportDAL.find({ folderId: folder.id });
|
const sourceSecretImports = await secretImportDAL.find({ folderId: folder.id });
|
||||||
const sourceImportedSecrets = await fnSecretsV2FromImports({
|
const sourceImportedSecrets = await fnSecretsV2FromImports({
|
||||||
projectId,
|
|
||||||
secretImports: sourceSecretImports,
|
secretImports: sourceSecretImports,
|
||||||
secretDAL: secretV2BridgeDAL,
|
secretDAL: secretV2BridgeDAL,
|
||||||
folderDAL,
|
folderDAL,
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
export * from "./ldap-password-rotation-constants";
|
||||||
|
export * from "./ldap-password-rotation-schemas";
|
||||||
|
export * from "./ldap-password-rotation-types";
|
@ -0,0 +1,15 @@
|
|||||||
|
import { SecretRotation } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-enums";
|
||||||
|
import { TSecretRotationV2ListItem } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-types";
|
||||||
|
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||||
|
|
||||||
|
export const LDAP_PASSWORD_ROTATION_LIST_OPTION: TSecretRotationV2ListItem = {
|
||||||
|
name: "LDAP Password",
|
||||||
|
type: SecretRotation.LdapPassword,
|
||||||
|
connection: AppConnection.LDAP,
|
||||||
|
template: {
|
||||||
|
secretsMapping: {
|
||||||
|
dn: "LDAP_DN",
|
||||||
|
password: "LDAP_PASSWORD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,181 @@
|
|||||||
|
import ldap from "ldapjs";
|
||||||
|
|
||||||
|
import {
|
||||||
|
TRotationFactory,
|
||||||
|
TRotationFactoryGetSecretsPayload,
|
||||||
|
TRotationFactoryIssueCredentials,
|
||||||
|
TRotationFactoryRevokeCredentials,
|
||||||
|
TRotationFactoryRotateCredentials
|
||||||
|
} from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-types";
|
||||||
|
import { logger } from "@app/lib/logger";
|
||||||
|
import { encryptAppConnectionCredentials } from "@app/services/app-connection/app-connection-fns";
|
||||||
|
import { getLdapConnectionClient, LdapProvider, TLdapConnection } from "@app/services/app-connection/ldap";
|
||||||
|
|
||||||
|
import { generatePassword } from "../shared/utils";
|
||||||
|
import {
|
||||||
|
TLdapPasswordRotationGeneratedCredentials,
|
||||||
|
TLdapPasswordRotationWithConnection
|
||||||
|
} from "./ldap-password-rotation-types";
|
||||||
|
|
||||||
|
const getEncodedPassword = (password: string) => Buffer.from(`"${password}"`, "utf16le");
|
||||||
|
|
||||||
|
export const ldapPasswordRotationFactory: TRotationFactory<
|
||||||
|
TLdapPasswordRotationWithConnection,
|
||||||
|
TLdapPasswordRotationGeneratedCredentials
|
||||||
|
> = (secretRotation, appConnectionDAL, kmsService) => {
|
||||||
|
const {
|
||||||
|
connection,
|
||||||
|
parameters: { dn, passwordRequirements },
|
||||||
|
secretsMapping
|
||||||
|
} = secretRotation;
|
||||||
|
|
||||||
|
const $verifyCredentials = async (credentials: Pick<TLdapConnection["credentials"], "dn" | "password">) => {
|
||||||
|
try {
|
||||||
|
const client = await getLdapConnectionClient({ ...connection.credentials, ...credentials });
|
||||||
|
|
||||||
|
client.unbind();
|
||||||
|
client.destroy();
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error(`Failed to verify credentials - ${(error as Error).message}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const $rotatePassword = async () => {
|
||||||
|
const { credentials, orgId } = connection;
|
||||||
|
|
||||||
|
if (!credentials.url.startsWith("ldaps")) throw new Error("Password Rotation requires an LDAPS connection");
|
||||||
|
|
||||||
|
const client = await getLdapConnectionClient(credentials);
|
||||||
|
const isPersonalRotation = credentials.dn === dn;
|
||||||
|
|
||||||
|
const password = generatePassword(passwordRequirements);
|
||||||
|
|
||||||
|
let changes: ldap.Change[] | ldap.Change;
|
||||||
|
|
||||||
|
switch (credentials.provider) {
|
||||||
|
case LdapProvider.ActiveDirectory:
|
||||||
|
{
|
||||||
|
const encodedPassword = getEncodedPassword(password);
|
||||||
|
|
||||||
|
// service account vs personal password rotation require different changes
|
||||||
|
if (isPersonalRotation) {
|
||||||
|
const currentEncodedPassword = getEncodedPassword(credentials.password);
|
||||||
|
|
||||||
|
changes = [
|
||||||
|
new ldap.Change({
|
||||||
|
operation: "delete",
|
||||||
|
modification: {
|
||||||
|
type: "unicodePwd",
|
||||||
|
values: [currentEncodedPassword]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
new ldap.Change({
|
||||||
|
operation: "add",
|
||||||
|
modification: {
|
||||||
|
type: "unicodePwd",
|
||||||
|
values: [encodedPassword]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
changes = new ldap.Change({
|
||||||
|
operation: "replace",
|
||||||
|
modification: {
|
||||||
|
type: "unicodePwd",
|
||||||
|
values: [encodedPassword]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error(`Unhandled provider: ${credentials.provider as LdapProvider}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
client.modify(dn, changes, (err) => {
|
||||||
|
if (err) {
|
||||||
|
logger.error(err, "LDAP Password Rotation Failed");
|
||||||
|
reject(new Error(`Provider Modify Error: ${err.message}`));
|
||||||
|
} else {
|
||||||
|
resolve(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
client.unbind();
|
||||||
|
client.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
await $verifyCredentials({ dn, password });
|
||||||
|
|
||||||
|
if (isPersonalRotation) {
|
||||||
|
const updatedCredentials: TLdapConnection["credentials"] = {
|
||||||
|
...credentials,
|
||||||
|
password
|
||||||
|
};
|
||||||
|
|
||||||
|
const encryptedCredentials = await encryptAppConnectionCredentials({
|
||||||
|
credentials: updatedCredentials,
|
||||||
|
orgId,
|
||||||
|
kmsService
|
||||||
|
});
|
||||||
|
|
||||||
|
await appConnectionDAL.updateById(connection.id, { encryptedCredentials });
|
||||||
|
}
|
||||||
|
|
||||||
|
return { dn, password };
|
||||||
|
};
|
||||||
|
|
||||||
|
const issueCredentials: TRotationFactoryIssueCredentials<TLdapPasswordRotationGeneratedCredentials> = async (
|
||||||
|
callback
|
||||||
|
) => {
|
||||||
|
const credentials = await $rotatePassword();
|
||||||
|
|
||||||
|
return callback(credentials);
|
||||||
|
};
|
||||||
|
|
||||||
|
const revokeCredentials: TRotationFactoryRevokeCredentials<TLdapPasswordRotationGeneratedCredentials> = async (
|
||||||
|
_,
|
||||||
|
callback
|
||||||
|
) => {
|
||||||
|
// we just rotate to a new password, essentially revoking old credentials
|
||||||
|
await $rotatePassword();
|
||||||
|
|
||||||
|
return callback();
|
||||||
|
};
|
||||||
|
|
||||||
|
const rotateCredentials: TRotationFactoryRotateCredentials<TLdapPasswordRotationGeneratedCredentials> = async (
|
||||||
|
_,
|
||||||
|
callback
|
||||||
|
) => {
|
||||||
|
const credentials = await $rotatePassword();
|
||||||
|
|
||||||
|
return callback(credentials);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSecretsPayload: TRotationFactoryGetSecretsPayload<TLdapPasswordRotationGeneratedCredentials> = (
|
||||||
|
generatedCredentials
|
||||||
|
) => {
|
||||||
|
const secrets = [
|
||||||
|
{
|
||||||
|
key: secretsMapping.dn,
|
||||||
|
value: generatedCredentials.dn
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: secretsMapping.password,
|
||||||
|
value: generatedCredentials.password
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return secrets;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
issueCredentials,
|
||||||
|
revokeCredentials,
|
||||||
|
rotateCredentials,
|
||||||
|
getSecretsPayload
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,68 @@
|
|||||||
|
import RE2 from "re2";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { SecretRotation } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-enums";
|
||||||
|
import {
|
||||||
|
BaseCreateSecretRotationSchema,
|
||||||
|
BaseSecretRotationSchema,
|
||||||
|
BaseUpdateSecretRotationSchema
|
||||||
|
} from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-schemas";
|
||||||
|
import { PasswordRequirementsSchema } from "@app/ee/services/secret-rotation-v2/shared/general";
|
||||||
|
import { SecretRotations } from "@app/lib/api-docs";
|
||||||
|
import { DistinguishedNameRegex } from "@app/lib/regex";
|
||||||
|
import { SecretNameSchema } from "@app/server/lib/schemas";
|
||||||
|
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||||
|
|
||||||
|
export const LdapPasswordRotationGeneratedCredentialsSchema = z
|
||||||
|
.object({
|
||||||
|
dn: z.string(),
|
||||||
|
password: z.string()
|
||||||
|
})
|
||||||
|
.array()
|
||||||
|
.min(1)
|
||||||
|
.max(2);
|
||||||
|
|
||||||
|
const LdapPasswordRotationParametersSchema = z.object({
|
||||||
|
dn: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.regex(new RE2(DistinguishedNameRegex), "Invalid DN format, ie; CN=user,OU=users,DC=example,DC=com")
|
||||||
|
.min(1, "Distinguished Name (DN) Required")
|
||||||
|
.describe(SecretRotations.PARAMETERS.LDAP_PASSWORD.dn),
|
||||||
|
passwordRequirements: PasswordRequirementsSchema.optional()
|
||||||
|
});
|
||||||
|
|
||||||
|
const LdapPasswordRotationSecretsMappingSchema = z.object({
|
||||||
|
dn: SecretNameSchema.describe(SecretRotations.SECRETS_MAPPING.LDAP_PASSWORD.dn),
|
||||||
|
password: SecretNameSchema.describe(SecretRotations.SECRETS_MAPPING.LDAP_PASSWORD.password)
|
||||||
|
});
|
||||||
|
|
||||||
|
export const LdapPasswordRotationTemplateSchema = z.object({
|
||||||
|
secretsMapping: z.object({
|
||||||
|
dn: z.string(),
|
||||||
|
password: z.string()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
export const LdapPasswordRotationSchema = BaseSecretRotationSchema(SecretRotation.LdapPassword).extend({
|
||||||
|
type: z.literal(SecretRotation.LdapPassword),
|
||||||
|
parameters: LdapPasswordRotationParametersSchema,
|
||||||
|
secretsMapping: LdapPasswordRotationSecretsMappingSchema
|
||||||
|
});
|
||||||
|
|
||||||
|
export const CreateLdapPasswordRotationSchema = BaseCreateSecretRotationSchema(SecretRotation.LdapPassword).extend({
|
||||||
|
parameters: LdapPasswordRotationParametersSchema,
|
||||||
|
secretsMapping: LdapPasswordRotationSecretsMappingSchema
|
||||||
|
});
|
||||||
|
|
||||||
|
export const UpdateLdapPasswordRotationSchema = BaseUpdateSecretRotationSchema(SecretRotation.LdapPassword).extend({
|
||||||
|
parameters: LdapPasswordRotationParametersSchema.optional(),
|
||||||
|
secretsMapping: LdapPasswordRotationSecretsMappingSchema.optional()
|
||||||
|
});
|
||||||
|
|
||||||
|
export const LdapPasswordRotationListItemSchema = z.object({
|
||||||
|
name: z.literal("LDAP Password"),
|
||||||
|
connection: z.literal(AppConnection.LDAP),
|
||||||
|
type: z.literal(SecretRotation.LdapPassword),
|
||||||
|
template: LdapPasswordRotationTemplateSchema
|
||||||
|
});
|
@ -0,0 +1,22 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { TLdapConnection } from "@app/services/app-connection/ldap";
|
||||||
|
|
||||||
|
import {
|
||||||
|
CreateLdapPasswordRotationSchema,
|
||||||
|
LdapPasswordRotationGeneratedCredentialsSchema,
|
||||||
|
LdapPasswordRotationListItemSchema,
|
||||||
|
LdapPasswordRotationSchema
|
||||||
|
} from "./ldap-password-rotation-schemas";
|
||||||
|
|
||||||
|
export type TLdapPasswordRotation = z.infer<typeof LdapPasswordRotationSchema>;
|
||||||
|
|
||||||
|
export type TLdapPasswordRotationInput = z.infer<typeof CreateLdapPasswordRotationSchema>;
|
||||||
|
|
||||||
|
export type TLdapPasswordRotationListItem = z.infer<typeof LdapPasswordRotationListItemSchema>;
|
||||||
|
|
||||||
|
export type TLdapPasswordRotationWithConnection = TLdapPasswordRotation & {
|
||||||
|
connection: TLdapConnection;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TLdapPasswordRotationGeneratedCredentials = z.infer<typeof LdapPasswordRotationGeneratedCredentialsSchema>;
|
@ -2,6 +2,7 @@ export enum SecretRotation {
|
|||||||
PostgresCredentials = "postgres-credentials",
|
PostgresCredentials = "postgres-credentials",
|
||||||
MsSqlCredentials = "mssql-credentials",
|
MsSqlCredentials = "mssql-credentials",
|
||||||
Auth0ClientSecret = "auth0-client-secret",
|
Auth0ClientSecret = "auth0-client-secret",
|
||||||
|
LdapPassword = "ldap-password",
|
||||||
AwsIamUserSecret = "aws-iam-user-secret"
|
AwsIamUserSecret = "aws-iam-user-secret"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import { KmsDataKey } from "@app/services/kms/kms-types";
|
|||||||
|
|
||||||
import { AUTH0_CLIENT_SECRET_ROTATION_LIST_OPTION } from "./auth0-client-secret";
|
import { AUTH0_CLIENT_SECRET_ROTATION_LIST_OPTION } from "./auth0-client-secret";
|
||||||
import { AWS_IAM_USER_SECRET_ROTATION_LIST_OPTION } from "./aws-iam-user-secret";
|
import { AWS_IAM_USER_SECRET_ROTATION_LIST_OPTION } from "./aws-iam-user-secret";
|
||||||
|
import { LDAP_PASSWORD_ROTATION_LIST_OPTION } from "./ldap-password";
|
||||||
import { MSSQL_CREDENTIALS_ROTATION_LIST_OPTION } from "./mssql-credentials";
|
import { MSSQL_CREDENTIALS_ROTATION_LIST_OPTION } from "./mssql-credentials";
|
||||||
import { POSTGRES_CREDENTIALS_ROTATION_LIST_OPTION } from "./postgres-credentials";
|
import { POSTGRES_CREDENTIALS_ROTATION_LIST_OPTION } from "./postgres-credentials";
|
||||||
import { SecretRotation, SecretRotationStatus } from "./secret-rotation-v2-enums";
|
import { SecretRotation, SecretRotationStatus } from "./secret-rotation-v2-enums";
|
||||||
@ -20,6 +21,7 @@ const SECRET_ROTATION_LIST_OPTIONS: Record<SecretRotation, TSecretRotationV2List
|
|||||||
[SecretRotation.PostgresCredentials]: POSTGRES_CREDENTIALS_ROTATION_LIST_OPTION,
|
[SecretRotation.PostgresCredentials]: POSTGRES_CREDENTIALS_ROTATION_LIST_OPTION,
|
||||||
[SecretRotation.MsSqlCredentials]: MSSQL_CREDENTIALS_ROTATION_LIST_OPTION,
|
[SecretRotation.MsSqlCredentials]: MSSQL_CREDENTIALS_ROTATION_LIST_OPTION,
|
||||||
[SecretRotation.Auth0ClientSecret]: AUTH0_CLIENT_SECRET_ROTATION_LIST_OPTION,
|
[SecretRotation.Auth0ClientSecret]: AUTH0_CLIENT_SECRET_ROTATION_LIST_OPTION,
|
||||||
|
[SecretRotation.LdapPassword]: LDAP_PASSWORD_ROTATION_LIST_OPTION,
|
||||||
[SecretRotation.AwsIamUserSecret]: AWS_IAM_USER_SECRET_ROTATION_LIST_OPTION
|
[SecretRotation.AwsIamUserSecret]: AWS_IAM_USER_SECRET_ROTATION_LIST_OPTION
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ export const SECRET_ROTATION_NAME_MAP: Record<SecretRotation, string> = {
|
|||||||
[SecretRotation.PostgresCredentials]: "PostgreSQL Credentials",
|
[SecretRotation.PostgresCredentials]: "PostgreSQL Credentials",
|
||||||
[SecretRotation.MsSqlCredentials]: "Microsoft SQL Server Credentials",
|
[SecretRotation.MsSqlCredentials]: "Microsoft SQL Server Credentials",
|
||||||
[SecretRotation.Auth0ClientSecret]: "Auth0 Client Secret",
|
[SecretRotation.Auth0ClientSecret]: "Auth0 Client Secret",
|
||||||
|
[SecretRotation.LdapPassword]: "LDAP Password",
|
||||||
[SecretRotation.AwsIamUserSecret]: "AWS IAM User Secret"
|
[SecretRotation.AwsIamUserSecret]: "AWS IAM User Secret"
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -12,5 +13,6 @@ export const SECRET_ROTATION_CONNECTION_MAP: Record<SecretRotation, AppConnectio
|
|||||||
[SecretRotation.PostgresCredentials]: AppConnection.Postgres,
|
[SecretRotation.PostgresCredentials]: AppConnection.Postgres,
|
||||||
[SecretRotation.MsSqlCredentials]: AppConnection.MsSql,
|
[SecretRotation.MsSqlCredentials]: AppConnection.MsSql,
|
||||||
[SecretRotation.Auth0ClientSecret]: AppConnection.Auth0,
|
[SecretRotation.Auth0ClientSecret]: AppConnection.Auth0,
|
||||||
|
[SecretRotation.LdapPassword]: AppConnection.LDAP,
|
||||||
[SecretRotation.AwsIamUserSecret]: AppConnection.AWS
|
[SecretRotation.AwsIamUserSecret]: AppConnection.AWS
|
||||||
};
|
};
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
ProjectPermissionSub
|
ProjectPermissionSub
|
||||||
} from "@app/ee/services/permission/project-permission";
|
} from "@app/ee/services/permission/project-permission";
|
||||||
import { auth0ClientSecretRotationFactory } from "@app/ee/services/secret-rotation-v2/auth0-client-secret/auth0-client-secret-rotation-fns";
|
import { auth0ClientSecretRotationFactory } from "@app/ee/services/secret-rotation-v2/auth0-client-secret/auth0-client-secret-rotation-fns";
|
||||||
|
import { ldapPasswordRotationFactory } from "@app/ee/services/secret-rotation-v2/ldap-password/ldap-password-rotation-fns";
|
||||||
import { SecretRotation, SecretRotationStatus } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-enums";
|
import { SecretRotation, SecretRotationStatus } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-enums";
|
||||||
import {
|
import {
|
||||||
calculateNextRotationAt,
|
calculateNextRotationAt,
|
||||||
@ -116,6 +117,7 @@ const SECRET_ROTATION_FACTORY_MAP: Record<SecretRotation, TRotationFactoryImplem
|
|||||||
[SecretRotation.PostgresCredentials]: sqlCredentialsRotationFactory as TRotationFactoryImplementation,
|
[SecretRotation.PostgresCredentials]: sqlCredentialsRotationFactory as TRotationFactoryImplementation,
|
||||||
[SecretRotation.MsSqlCredentials]: sqlCredentialsRotationFactory as TRotationFactoryImplementation,
|
[SecretRotation.MsSqlCredentials]: sqlCredentialsRotationFactory as TRotationFactoryImplementation,
|
||||||
[SecretRotation.Auth0ClientSecret]: auth0ClientSecretRotationFactory as TRotationFactoryImplementation,
|
[SecretRotation.Auth0ClientSecret]: auth0ClientSecretRotationFactory as TRotationFactoryImplementation,
|
||||||
|
[SecretRotation.LdapPassword]: ldapPasswordRotationFactory as TRotationFactoryImplementation,
|
||||||
[SecretRotation.AwsIamUserSecret]: awsIamUserSecretRotationFactory as TRotationFactoryImplementation
|
[SecretRotation.AwsIamUserSecret]: awsIamUserSecretRotationFactory as TRotationFactoryImplementation
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -451,6 +453,18 @@ export const secretRotationV2ServiceFactory = ({
|
|||||||
kmsService
|
kmsService
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// even though we have a db constraint we want to check before any rotation of credentials is attempted
|
||||||
|
// to prevent creation failure after external credentials have been modified
|
||||||
|
const conflictingRotation = await secretRotationV2DAL.findOne({
|
||||||
|
name: payload.name,
|
||||||
|
folderId: folder.id
|
||||||
|
});
|
||||||
|
|
||||||
|
if (conflictingRotation)
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: `A Secret Rotation with the name "${payload.name}" already exists at the secret path "${secretPath}"`
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const currentTime = new Date();
|
const currentTime = new Date();
|
||||||
|
|
||||||
|
@ -19,6 +19,13 @@ import {
|
|||||||
TAwsIamUserSecretRotationListItem,
|
TAwsIamUserSecretRotationListItem,
|
||||||
TAwsIamUserSecretRotationWithConnection
|
TAwsIamUserSecretRotationWithConnection
|
||||||
} from "./aws-iam-user-secret";
|
} from "./aws-iam-user-secret";
|
||||||
|
import {
|
||||||
|
TLdapPasswordRotation,
|
||||||
|
TLdapPasswordRotationGeneratedCredentials,
|
||||||
|
TLdapPasswordRotationInput,
|
||||||
|
TLdapPasswordRotationListItem,
|
||||||
|
TLdapPasswordRotationWithConnection
|
||||||
|
} from "./ldap-password";
|
||||||
import {
|
import {
|
||||||
TMsSqlCredentialsRotation,
|
TMsSqlCredentialsRotation,
|
||||||
TMsSqlCredentialsRotationInput,
|
TMsSqlCredentialsRotationInput,
|
||||||
@ -38,29 +45,34 @@ export type TSecretRotationV2 =
|
|||||||
| TPostgresCredentialsRotation
|
| TPostgresCredentialsRotation
|
||||||
| TMsSqlCredentialsRotation
|
| TMsSqlCredentialsRotation
|
||||||
| TAuth0ClientSecretRotation
|
| TAuth0ClientSecretRotation
|
||||||
|
| TLdapPasswordRotation
|
||||||
| TAwsIamUserSecretRotation;
|
| TAwsIamUserSecretRotation;
|
||||||
|
|
||||||
export type TSecretRotationV2WithConnection =
|
export type TSecretRotationV2WithConnection =
|
||||||
| TPostgresCredentialsRotationWithConnection
|
| TPostgresCredentialsRotationWithConnection
|
||||||
| TMsSqlCredentialsRotationWithConnection
|
| TMsSqlCredentialsRotationWithConnection
|
||||||
| TAuth0ClientSecretRotationWithConnection
|
| TAuth0ClientSecretRotationWithConnection
|
||||||
|
| TLdapPasswordRotationWithConnection
|
||||||
| TAwsIamUserSecretRotationWithConnection;
|
| TAwsIamUserSecretRotationWithConnection;
|
||||||
|
|
||||||
export type TSecretRotationV2GeneratedCredentials =
|
export type TSecretRotationV2GeneratedCredentials =
|
||||||
| TSqlCredentialsRotationGeneratedCredentials
|
| TSqlCredentialsRotationGeneratedCredentials
|
||||||
| TAuth0ClientSecretRotationGeneratedCredentials
|
| TAuth0ClientSecretRotationGeneratedCredentials
|
||||||
|
| TLdapPasswordRotationGeneratedCredentials
|
||||||
| TAwsIamUserSecretRotationGeneratedCredentials;
|
| TAwsIamUserSecretRotationGeneratedCredentials;
|
||||||
|
|
||||||
export type TSecretRotationV2Input =
|
export type TSecretRotationV2Input =
|
||||||
| TPostgresCredentialsRotationInput
|
| TPostgresCredentialsRotationInput
|
||||||
| TMsSqlCredentialsRotationInput
|
| TMsSqlCredentialsRotationInput
|
||||||
| TAuth0ClientSecretRotationInput
|
| TAuth0ClientSecretRotationInput
|
||||||
|
| TLdapPasswordRotationInput
|
||||||
| TAwsIamUserSecretRotationInput;
|
| TAwsIamUserSecretRotationInput;
|
||||||
|
|
||||||
export type TSecretRotationV2ListItem =
|
export type TSecretRotationV2ListItem =
|
||||||
| TPostgresCredentialsRotationListItem
|
| TPostgresCredentialsRotationListItem
|
||||||
| TMsSqlCredentialsRotationListItem
|
| TMsSqlCredentialsRotationListItem
|
||||||
| TAuth0ClientSecretRotationListItem
|
| TAuth0ClientSecretRotationListItem
|
||||||
|
| TLdapPasswordRotationListItem
|
||||||
| TAwsIamUserSecretRotationListItem;
|
| TAwsIamUserSecretRotationListItem;
|
||||||
|
|
||||||
export type TSecretRotationV2Raw = NonNullable<Awaited<ReturnType<TSecretRotationV2DALFactory["findById"]>>>;
|
export type TSecretRotationV2Raw = NonNullable<Awaited<ReturnType<TSecretRotationV2DALFactory["findById"]>>>;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { Auth0ClientSecretRotationSchema } from "@app/ee/services/secret-rotation-v2/auth0-client-secret";
|
import { Auth0ClientSecretRotationSchema } from "@app/ee/services/secret-rotation-v2/auth0-client-secret";
|
||||||
|
import { LdapPasswordRotationSchema } from "@app/ee/services/secret-rotation-v2/ldap-password";
|
||||||
import { MsSqlCredentialsRotationSchema } from "@app/ee/services/secret-rotation-v2/mssql-credentials";
|
import { MsSqlCredentialsRotationSchema } from "@app/ee/services/secret-rotation-v2/mssql-credentials";
|
||||||
import { PostgresCredentialsRotationSchema } from "@app/ee/services/secret-rotation-v2/postgres-credentials";
|
import { PostgresCredentialsRotationSchema } from "@app/ee/services/secret-rotation-v2/postgres-credentials";
|
||||||
|
|
||||||
@ -10,5 +11,6 @@ export const SecretRotationV2Schema = z.discriminatedUnion("type", [
|
|||||||
PostgresCredentialsRotationSchema,
|
PostgresCredentialsRotationSchema,
|
||||||
MsSqlCredentialsRotationSchema,
|
MsSqlCredentialsRotationSchema,
|
||||||
Auth0ClientSecretRotationSchema,
|
Auth0ClientSecretRotationSchema,
|
||||||
|
LdapPasswordRotationSchema,
|
||||||
AwsIamUserSecretRotationSchema
|
AwsIamUserSecretRotationSchema
|
||||||
]);
|
]);
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
export * from "./password-requirements-schema";
|
@ -0,0 +1,44 @@
|
|||||||
|
import RE2 from "re2";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { SecretRotations } from "@app/lib/api-docs";
|
||||||
|
|
||||||
|
export const PasswordRequirementsSchema = z
|
||||||
|
.object({
|
||||||
|
length: z
|
||||||
|
.number()
|
||||||
|
.min(1, "Password length must be a positive number")
|
||||||
|
.max(250, "Password length must be less than 250")
|
||||||
|
.describe(SecretRotations.PARAMETERS.GENERAL.PASSWORD_REQUIREMENTS.length),
|
||||||
|
required: z.object({
|
||||||
|
digits: z
|
||||||
|
.number()
|
||||||
|
.min(0, "Digit count must be non-negative")
|
||||||
|
.describe(SecretRotations.PARAMETERS.GENERAL.PASSWORD_REQUIREMENTS.required.digits),
|
||||||
|
lowercase: z
|
||||||
|
.number()
|
||||||
|
.min(0, "Lowercase count must be non-negative")
|
||||||
|
.describe(SecretRotations.PARAMETERS.GENERAL.PASSWORD_REQUIREMENTS.required.lowercase),
|
||||||
|
uppercase: z
|
||||||
|
.number()
|
||||||
|
.min(0, "Uppercase count must be non-negative")
|
||||||
|
.describe(SecretRotations.PARAMETERS.GENERAL.PASSWORD_REQUIREMENTS.required.uppercase),
|
||||||
|
symbols: z
|
||||||
|
.number()
|
||||||
|
.min(0, "Symbol count must be non-negative")
|
||||||
|
.describe(SecretRotations.PARAMETERS.GENERAL.PASSWORD_REQUIREMENTS.required.symbols)
|
||||||
|
}),
|
||||||
|
allowedSymbols: z
|
||||||
|
.string()
|
||||||
|
.regex(new RE2("[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?~]"), "Invalid symbols")
|
||||||
|
.optional()
|
||||||
|
.describe(SecretRotations.PARAMETERS.GENERAL.PASSWORD_REQUIREMENTS.allowedSymbols)
|
||||||
|
})
|
||||||
|
.refine((data) => {
|
||||||
|
return Object.values(data.required).some((count) => count > 0);
|
||||||
|
}, "At least one character type must be required")
|
||||||
|
.refine((data) => {
|
||||||
|
const total = Object.values(data.required).reduce((sum, count) => sum + count, 0);
|
||||||
|
return total <= data.length;
|
||||||
|
}, "Sum of required characters cannot exceed the total length")
|
||||||
|
.describe(SecretRotations.PARAMETERS.GENERAL.PASSWORD_REQUIREMENTS.base);
|
@ -1,6 +1,17 @@
|
|||||||
import { randomInt } from "crypto";
|
import { randomInt } from "crypto";
|
||||||
|
|
||||||
const DEFAULT_PASSWORD_REQUIREMENTS = {
|
type TPasswordRequirements = {
|
||||||
|
length: number;
|
||||||
|
required: {
|
||||||
|
lowercase: number;
|
||||||
|
uppercase: number;
|
||||||
|
digits: number;
|
||||||
|
symbols: number;
|
||||||
|
};
|
||||||
|
allowedSymbols?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEFAULT_PASSWORD_REQUIREMENTS: TPasswordRequirements = {
|
||||||
length: 48,
|
length: 48,
|
||||||
required: {
|
required: {
|
||||||
lowercase: 1,
|
lowercase: 1,
|
||||||
@ -11,9 +22,9 @@ const DEFAULT_PASSWORD_REQUIREMENTS = {
|
|||||||
allowedSymbols: "-_.~!*"
|
allowedSymbols: "-_.~!*"
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generatePassword = () => {
|
export const generatePassword = (passwordRequirements?: TPasswordRequirements) => {
|
||||||
try {
|
try {
|
||||||
const { length, required, allowedSymbols } = DEFAULT_PASSWORD_REQUIREMENTS;
|
const { length, required, allowedSymbols } = passwordRequirements ?? DEFAULT_PASSWORD_REQUIREMENTS;
|
||||||
|
|
||||||
const chars = {
|
const chars = {
|
||||||
lowercase: "abcdefghijklmnopqrstuvwxyz",
|
lowercase: "abcdefghijklmnopqrstuvwxyz",
|
||||||
|
@ -33,6 +33,7 @@ export const sshHostDALFactory = (db: TDbClient) => {
|
|||||||
db.ref("id").withSchema(TableName.SshHost).as("sshHostId"),
|
db.ref("id").withSchema(TableName.SshHost).as("sshHostId"),
|
||||||
db.ref("projectId").withSchema(TableName.SshHost),
|
db.ref("projectId").withSchema(TableName.SshHost),
|
||||||
db.ref("hostname").withSchema(TableName.SshHost),
|
db.ref("hostname").withSchema(TableName.SshHost),
|
||||||
|
db.ref("alias").withSchema(TableName.SshHost),
|
||||||
db.ref("userCertTtl").withSchema(TableName.SshHost),
|
db.ref("userCertTtl").withSchema(TableName.SshHost),
|
||||||
db.ref("hostCertTtl").withSchema(TableName.SshHost),
|
db.ref("hostCertTtl").withSchema(TableName.SshHost),
|
||||||
db.ref("loginUser").withSchema(TableName.SshHostLoginUser),
|
db.ref("loginUser").withSchema(TableName.SshHostLoginUser),
|
||||||
@ -45,7 +46,8 @@ export const sshHostDALFactory = (db: TDbClient) => {
|
|||||||
|
|
||||||
const grouped = groupBy(rows, (r) => r.sshHostId);
|
const grouped = groupBy(rows, (r) => r.sshHostId);
|
||||||
return Object.values(grouped).map((hostRows) => {
|
return Object.values(grouped).map((hostRows) => {
|
||||||
const { sshHostId, hostname, userCertTtl, hostCertTtl, userSshCaId, hostSshCaId, projectId } = hostRows[0];
|
const { sshHostId, hostname, alias, userCertTtl, hostCertTtl, userSshCaId, hostSshCaId, projectId } =
|
||||||
|
hostRows[0];
|
||||||
|
|
||||||
const loginMappingGrouped = groupBy(hostRows, (r) => r.loginUser);
|
const loginMappingGrouped = groupBy(hostRows, (r) => r.loginUser);
|
||||||
|
|
||||||
@ -59,6 +61,7 @@ export const sshHostDALFactory = (db: TDbClient) => {
|
|||||||
return {
|
return {
|
||||||
id: sshHostId,
|
id: sshHostId,
|
||||||
hostname,
|
hostname,
|
||||||
|
alias,
|
||||||
projectId,
|
projectId,
|
||||||
userCertTtl,
|
userCertTtl,
|
||||||
hostCertTtl,
|
hostCertTtl,
|
||||||
@ -87,6 +90,7 @@ export const sshHostDALFactory = (db: TDbClient) => {
|
|||||||
db.ref("id").withSchema(TableName.SshHost).as("sshHostId"),
|
db.ref("id").withSchema(TableName.SshHost).as("sshHostId"),
|
||||||
db.ref("projectId").withSchema(TableName.SshHost),
|
db.ref("projectId").withSchema(TableName.SshHost),
|
||||||
db.ref("hostname").withSchema(TableName.SshHost),
|
db.ref("hostname").withSchema(TableName.SshHost),
|
||||||
|
db.ref("alias").withSchema(TableName.SshHost),
|
||||||
db.ref("userCertTtl").withSchema(TableName.SshHost),
|
db.ref("userCertTtl").withSchema(TableName.SshHost),
|
||||||
db.ref("hostCertTtl").withSchema(TableName.SshHost),
|
db.ref("hostCertTtl").withSchema(TableName.SshHost),
|
||||||
db.ref("loginUser").withSchema(TableName.SshHostLoginUser),
|
db.ref("loginUser").withSchema(TableName.SshHostLoginUser),
|
||||||
@ -99,7 +103,7 @@ export const sshHostDALFactory = (db: TDbClient) => {
|
|||||||
|
|
||||||
const hostsGrouped = groupBy(rows, (r) => r.sshHostId);
|
const hostsGrouped = groupBy(rows, (r) => r.sshHostId);
|
||||||
return Object.values(hostsGrouped).map((hostRows) => {
|
return Object.values(hostsGrouped).map((hostRows) => {
|
||||||
const { sshHostId, hostname, userCertTtl, hostCertTtl, userSshCaId, hostSshCaId } = hostRows[0];
|
const { sshHostId, hostname, alias, userCertTtl, hostCertTtl, userSshCaId, hostSshCaId } = hostRows[0];
|
||||||
|
|
||||||
const loginMappingGrouped = groupBy(
|
const loginMappingGrouped = groupBy(
|
||||||
hostRows.filter((r) => r.loginUser),
|
hostRows.filter((r) => r.loginUser),
|
||||||
@ -116,6 +120,7 @@ export const sshHostDALFactory = (db: TDbClient) => {
|
|||||||
return {
|
return {
|
||||||
id: sshHostId,
|
id: sshHostId,
|
||||||
hostname,
|
hostname,
|
||||||
|
alias,
|
||||||
projectId,
|
projectId,
|
||||||
userCertTtl,
|
userCertTtl,
|
||||||
hostCertTtl,
|
hostCertTtl,
|
||||||
@ -144,6 +149,7 @@ export const sshHostDALFactory = (db: TDbClient) => {
|
|||||||
db.ref("id").withSchema(TableName.SshHost).as("sshHostId"),
|
db.ref("id").withSchema(TableName.SshHost).as("sshHostId"),
|
||||||
db.ref("projectId").withSchema(TableName.SshHost),
|
db.ref("projectId").withSchema(TableName.SshHost),
|
||||||
db.ref("hostname").withSchema(TableName.SshHost),
|
db.ref("hostname").withSchema(TableName.SshHost),
|
||||||
|
db.ref("alias").withSchema(TableName.SshHost),
|
||||||
db.ref("userCertTtl").withSchema(TableName.SshHost),
|
db.ref("userCertTtl").withSchema(TableName.SshHost),
|
||||||
db.ref("hostCertTtl").withSchema(TableName.SshHost),
|
db.ref("hostCertTtl").withSchema(TableName.SshHost),
|
||||||
db.ref("loginUser").withSchema(TableName.SshHostLoginUser),
|
db.ref("loginUser").withSchema(TableName.SshHostLoginUser),
|
||||||
@ -155,7 +161,7 @@ export const sshHostDALFactory = (db: TDbClient) => {
|
|||||||
|
|
||||||
if (rows.length === 0) return null;
|
if (rows.length === 0) return null;
|
||||||
|
|
||||||
const { sshHostId: id, projectId, hostname, userCertTtl, hostCertTtl, userSshCaId, hostSshCaId } = rows[0];
|
const { sshHostId: id, projectId, hostname, alias, userCertTtl, hostCertTtl, userSshCaId, hostSshCaId } = rows[0];
|
||||||
|
|
||||||
const loginMappingGrouped = groupBy(
|
const loginMappingGrouped = groupBy(
|
||||||
rows.filter((r) => r.loginUser),
|
rows.filter((r) => r.loginUser),
|
||||||
@ -173,6 +179,7 @@ export const sshHostDALFactory = (db: TDbClient) => {
|
|||||||
id,
|
id,
|
||||||
projectId,
|
projectId,
|
||||||
hostname,
|
hostname,
|
||||||
|
alias,
|
||||||
userCertTtl,
|
userCertTtl,
|
||||||
hostCertTtl,
|
hostCertTtl,
|
||||||
loginMappings,
|
loginMappings,
|
||||||
|
@ -6,6 +6,7 @@ export const sanitizedSshHost = SshHostsSchema.pick({
|
|||||||
id: true,
|
id: true,
|
||||||
projectId: true,
|
projectId: true,
|
||||||
hostname: true,
|
hostname: true,
|
||||||
|
alias: true,
|
||||||
userCertTtl: true,
|
userCertTtl: true,
|
||||||
hostCertTtl: true,
|
hostCertTtl: true,
|
||||||
userSshCaId: true,
|
userSshCaId: true,
|
||||||
|
@ -119,6 +119,7 @@ export const sshHostServiceFactory = ({
|
|||||||
const createSshHost = async ({
|
const createSshHost = async ({
|
||||||
projectId,
|
projectId,
|
||||||
hostname,
|
hostname,
|
||||||
|
alias,
|
||||||
userCertTtl,
|
userCertTtl,
|
||||||
hostCertTtl,
|
hostCertTtl,
|
||||||
loginMappings,
|
loginMappings,
|
||||||
@ -192,6 +193,7 @@ export const sshHostServiceFactory = ({
|
|||||||
{
|
{
|
||||||
projectId,
|
projectId,
|
||||||
hostname,
|
hostname,
|
||||||
|
alias: alias === "" ? null : alias,
|
||||||
userCertTtl,
|
userCertTtl,
|
||||||
hostCertTtl,
|
hostCertTtl,
|
||||||
userSshCaId,
|
userSshCaId,
|
||||||
@ -265,6 +267,7 @@ export const sshHostServiceFactory = ({
|
|||||||
const updateSshHost = async ({
|
const updateSshHost = async ({
|
||||||
sshHostId,
|
sshHostId,
|
||||||
hostname,
|
hostname,
|
||||||
|
alias,
|
||||||
userCertTtl,
|
userCertTtl,
|
||||||
hostCertTtl,
|
hostCertTtl,
|
||||||
loginMappings,
|
loginMappings,
|
||||||
@ -297,6 +300,7 @@ export const sshHostServiceFactory = ({
|
|||||||
sshHostId,
|
sshHostId,
|
||||||
{
|
{
|
||||||
hostname,
|
hostname,
|
||||||
|
alias: alias === "" ? null : alias,
|
||||||
userCertTtl,
|
userCertTtl,
|
||||||
hostCertTtl
|
hostCertTtl
|
||||||
},
|
},
|
||||||
|
@ -4,6 +4,7 @@ export type TListSshHostsDTO = Omit<TProjectPermission, "projectId">;
|
|||||||
|
|
||||||
export type TCreateSshHostDTO = {
|
export type TCreateSshHostDTO = {
|
||||||
hostname: string;
|
hostname: string;
|
||||||
|
alias?: string;
|
||||||
userCertTtl: string;
|
userCertTtl: string;
|
||||||
hostCertTtl: string;
|
hostCertTtl: string;
|
||||||
loginMappings: {
|
loginMappings: {
|
||||||
@ -19,6 +20,7 @@ export type TCreateSshHostDTO = {
|
|||||||
export type TUpdateSshHostDTO = {
|
export type TUpdateSshHostDTO = {
|
||||||
sshHostId: string;
|
sshHostId: string;
|
||||||
hostname?: string;
|
hostname?: string;
|
||||||
|
alias?: string;
|
||||||
userCertTtl?: string;
|
userCertTtl?: string;
|
||||||
hostCertTtl?: string;
|
hostCertTtl?: string;
|
||||||
loginMappings?: {
|
loginMappings?: {
|
||||||
|
@ -8,6 +8,51 @@ import { APP_CONNECTION_NAME_MAP } from "@app/services/app-connection/app-connec
|
|||||||
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
|
import { SecretSync } from "@app/services/secret-sync/secret-sync-enums";
|
||||||
import { SECRET_SYNC_CONNECTION_MAP, SECRET_SYNC_NAME_MAP } from "@app/services/secret-sync/secret-sync-maps";
|
import { SECRET_SYNC_CONNECTION_MAP, SECRET_SYNC_NAME_MAP } from "@app/services/secret-sync/secret-sync-maps";
|
||||||
|
|
||||||
|
export enum ApiDocsTags {
|
||||||
|
Identities = "Identities",
|
||||||
|
TokenAuth = "Token Auth",
|
||||||
|
UniversalAuth = "Universal Auth",
|
||||||
|
GcpAuth = "GCP Auth",
|
||||||
|
AwsAuth = "AWS Auth",
|
||||||
|
AzureAuth = "Azure Auth",
|
||||||
|
KubernetesAuth = "Kubernetes Auth",
|
||||||
|
JwtAuth = "JWT Auth",
|
||||||
|
OidcAuth = "OIDC Auth",
|
||||||
|
Groups = "Groups",
|
||||||
|
Organizations = "Organizations",
|
||||||
|
Projects = "Projects",
|
||||||
|
ProjectUsers = "Project Users",
|
||||||
|
ProjectGroups = "Project Groups",
|
||||||
|
ProjectIdentities = "Project Identities",
|
||||||
|
ProjectRoles = "Project Roles",
|
||||||
|
ProjectTemplates = "Project Templates",
|
||||||
|
Environments = "Environments",
|
||||||
|
Folders = "Folders",
|
||||||
|
SecretTags = "Secret Tags",
|
||||||
|
Secrets = "Secrets",
|
||||||
|
DynamicSecrets = "Dynamic Secrets",
|
||||||
|
SecretImports = "Secret Imports",
|
||||||
|
SecretRotations = "Secret Rotations",
|
||||||
|
IdentitySpecificPrivilegesV1 = "Identity Specific Privileges",
|
||||||
|
IdentitySpecificPrivilegesV2 = "Identity Specific Privileges V2",
|
||||||
|
AppConnections = "App Connections",
|
||||||
|
SecretSyncs = "Secret Syncs",
|
||||||
|
Integrations = "Integrations",
|
||||||
|
ServiceTokens = "Service Tokens",
|
||||||
|
AuditLogs = "Audit Logs",
|
||||||
|
PkiCertificateAuthorities = "PKI Certificate Authorities",
|
||||||
|
PkiCertificates = "PKI Certificates",
|
||||||
|
PkiCertificateTemplates = "PKI Certificate Templates",
|
||||||
|
PkiCertificateCollections = "PKI Certificate Collections",
|
||||||
|
PkiAlerting = "PKI Alerting",
|
||||||
|
SshCertificates = "SSH Certificates",
|
||||||
|
SshCertificateAuthorities = "SSH Certificate Authorities",
|
||||||
|
SshCertificateTemplates = "SSH Certificate Templates",
|
||||||
|
KmsKeys = "KMS Keys",
|
||||||
|
KmsEncryption = "KMS Encryption",
|
||||||
|
KmsSigning = "KMS Signing"
|
||||||
|
}
|
||||||
|
|
||||||
export const GROUPS = {
|
export const GROUPS = {
|
||||||
CREATE: {
|
CREATE: {
|
||||||
name: "The name of the group to create.",
|
name: "The name of the group to create.",
|
||||||
@ -762,6 +807,8 @@ export const RAW_SECRETS = {
|
|||||||
tagIds: "The ID of the tags to be attached to the updated secret.",
|
tagIds: "The ID of the tags to be attached to the updated secret.",
|
||||||
secretReminderRepeatDays: "Interval for secret rotation notifications, measured in days.",
|
secretReminderRepeatDays: "Interval for secret rotation notifications, measured in days.",
|
||||||
secretReminderNote: "Note to be attached in notification email.",
|
secretReminderNote: "Note to be attached in notification email.",
|
||||||
|
secretReminderRecipients:
|
||||||
|
"An array of user IDs that will receive the reminder email. If not specified, all project members will receive the reminder email.",
|
||||||
newSecretName: "The new name for the secret."
|
newSecretName: "The new name for the secret."
|
||||||
},
|
},
|
||||||
DELETE: {
|
DELETE: {
|
||||||
@ -888,7 +935,7 @@ export const DYNAMIC_SECRETS = {
|
|||||||
environmentSlug: "The slug of the environment to list folders from.",
|
environmentSlug: "The slug of the environment to list folders from.",
|
||||||
path: "The path to list folders from."
|
path: "The path to list folders from."
|
||||||
},
|
},
|
||||||
LIST_LEAES_BY_NAME: {
|
LIST_LEASES_BY_NAME: {
|
||||||
projectSlug: "The slug of the project to create dynamic secret in.",
|
projectSlug: "The slug of the project to create dynamic secret in.",
|
||||||
environmentSlug: "The slug of the environment to list folders from.",
|
environmentSlug: "The slug of the environment to list folders from.",
|
||||||
path: "The path to list folders from.",
|
path: "The path to list folders from.",
|
||||||
@ -1342,6 +1389,7 @@ export const SSH_HOSTS = {
|
|||||||
CREATE: {
|
CREATE: {
|
||||||
projectId: "The ID of the project to create the SSH host in.",
|
projectId: "The ID of the project to create the SSH host in.",
|
||||||
hostname: "The hostname of the SSH host.",
|
hostname: "The hostname of the SSH host.",
|
||||||
|
alias: "The alias for the SSH host.",
|
||||||
userCertTtl: "The time to live for user certificates issued under this host.",
|
userCertTtl: "The time to live for user certificates issued under this host.",
|
||||||
hostCertTtl: "The time to live for host certificates issued under this host.",
|
hostCertTtl: "The time to live for host certificates issued under this host.",
|
||||||
loginUser: "A login user on the remote machine (e.g. 'ec2-user', 'deploy', 'admin')",
|
loginUser: "A login user on the remote machine (e.g. 'ec2-user', 'deploy', 'admin')",
|
||||||
@ -1356,6 +1404,7 @@ export const SSH_HOSTS = {
|
|||||||
UPDATE: {
|
UPDATE: {
|
||||||
sshHostId: "The ID of the SSH host to update.",
|
sshHostId: "The ID of the SSH host to update.",
|
||||||
hostname: "The hostname of the SSH host to update to.",
|
hostname: "The hostname of the SSH host to update to.",
|
||||||
|
alias: "The alias for the SSH host to update to.",
|
||||||
userCertTtl: "The time to live for user certificates issued under this host to update to.",
|
userCertTtl: "The time to live for user certificates issued under this host to update to.",
|
||||||
hostCertTtl: "The time to live for host certificates issued under this host to update to.",
|
hostCertTtl: "The time to live for host certificates issued under this host to update to.",
|
||||||
loginUser: "A login user on the remote machine (e.g. 'ec2-user', 'deploy', 'admin')",
|
loginUser: "A login user on the remote machine (e.g. 'ec2-user', 'deploy', 'admin')",
|
||||||
@ -1812,6 +1861,20 @@ export const AppConnections = {
|
|||||||
WINDMILL: {
|
WINDMILL: {
|
||||||
instanceUrl: "The Windmill instance URL to connect with (defaults to https://app.windmill.dev).",
|
instanceUrl: "The Windmill instance URL to connect with (defaults to https://app.windmill.dev).",
|
||||||
accessToken: "The access token to use to connect with Windmill."
|
accessToken: "The access token to use to connect with Windmill."
|
||||||
|
},
|
||||||
|
LDAP: {
|
||||||
|
provider: "The type of LDAP provider. Determines provider-specific behaviors.",
|
||||||
|
url: "The LDAP/LDAPS URL to connect to (e.g., 'ldap://domain-or-ip:389' or 'ldaps://domain-or-ip:636').",
|
||||||
|
dn: "The Distinguished Name (DN) of the principal to bind with (e.g., 'CN=John,CN=Users,DC=example,DC=com').",
|
||||||
|
password: "The password to bind with for authentication.",
|
||||||
|
sslRejectUnauthorized:
|
||||||
|
"Whether or not to reject unauthorized SSL certificates (true/false) when using ldaps://. Set to false only in test environments.",
|
||||||
|
sslCertificate:
|
||||||
|
"The SSL certificate (PEM format) to use for secure connection when using ldaps:// with a self-signed certificate."
|
||||||
|
},
|
||||||
|
TEAMCITY: {
|
||||||
|
instanceUrl: "The TeamCity instance URL to connect with.",
|
||||||
|
accessToken: "The access token to use to connect with TeamCity."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1951,6 +2014,10 @@ export const SecretSyncs = {
|
|||||||
WINDMILL: {
|
WINDMILL: {
|
||||||
workspace: "The Windmill workspace to sync secrets to.",
|
workspace: "The Windmill workspace to sync secrets to.",
|
||||||
path: "The Windmill workspace path to sync secrets to."
|
path: "The Windmill workspace path to sync secrets to."
|
||||||
|
},
|
||||||
|
TEAMCITY: {
|
||||||
|
project: "The TeamCity project to sync secrets to.",
|
||||||
|
buildConfig: "The TeamCity build configuration to sync secrets to."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -2016,6 +2083,22 @@ export const SecretRotations = {
|
|||||||
AUTH0_CLIENT_SECRET: {
|
AUTH0_CLIENT_SECRET: {
|
||||||
clientId: "The client ID of the Auth0 Application to rotate the client secret for."
|
clientId: "The client ID of the Auth0 Application to rotate the client secret for."
|
||||||
},
|
},
|
||||||
|
LDAP_PASSWORD: {
|
||||||
|
dn: "The Distinguished Name (DN) of the principal to rotate the password for."
|
||||||
|
},
|
||||||
|
GENERAL: {
|
||||||
|
PASSWORD_REQUIREMENTS: {
|
||||||
|
base: "The password requirements to use when generating the new password.",
|
||||||
|
length: "The length of the password to generate.",
|
||||||
|
required: {
|
||||||
|
digits: "The amount of digits to require in the generated password.",
|
||||||
|
lowercase: "The amount of lowercase characters to require in the generated password.",
|
||||||
|
uppercase: "The amount of uppercase characters to require in the generated password.",
|
||||||
|
symbols: "The amount of symbols to require in the generated password."
|
||||||
|
},
|
||||||
|
allowedSymbols: 'The allowed symbols to use in the generated password (defaults to "-_.~!*").'
|
||||||
|
}
|
||||||
|
},
|
||||||
AWS_IAM_USER_SECRET: {
|
AWS_IAM_USER_SECRET: {
|
||||||
userName: "The name of the client to rotate credentials for.",
|
userName: "The name of the client to rotate credentials for.",
|
||||||
region: "The AWS region the client is present in."
|
region: "The AWS region the client is present in."
|
||||||
@ -2030,6 +2113,10 @@ export const SecretRotations = {
|
|||||||
clientId: "The name of the secret that the client ID will be mapped to.",
|
clientId: "The name of the secret that the client ID will be mapped to.",
|
||||||
clientSecret: "The name of the secret that the rotated client secret will be mapped to."
|
clientSecret: "The name of the secret that the rotated client secret will be mapped to."
|
||||||
},
|
},
|
||||||
|
LDAP_PASSWORD: {
|
||||||
|
dn: "The name of the secret that the Distinguished Name (DN) of the principal will be mapped to.",
|
||||||
|
password: "The name of the secret that the rotated password will be mapped to."
|
||||||
|
},
|
||||||
AWS_IAM_USER_SECRET: {
|
AWS_IAM_USER_SECRET: {
|
||||||
accessKeyId: "The name of the secret that the access key ID will be mapped to.",
|
accessKeyId: "The name of the secret that the access key ID will be mapped to.",
|
||||||
secretAccessKey: "The name of the secret that the rotated secret access key will be mapped to."
|
secretAccessKey: "The name of the secret that the rotated secret access key will be mapped to."
|
||||||
|
1
backend/src/lib/config/const.ts
Normal file
1
backend/src/lib/config/const.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const INFISICAL_PROVIDER_GITHUB_ACCESS_TOKEN = "x-infisical-github-auth-access-token";
|
@ -2,7 +2,7 @@ export const daysToMillisecond = (days: number) => days * 24 * 60 * 60 * 1000;
|
|||||||
|
|
||||||
export const secondsToMillis = (seconds: number) => seconds * 1000;
|
export const secondsToMillis = (seconds: number) => seconds * 1000;
|
||||||
|
|
||||||
export const applyJitter = (delayMs: number, jitterMs: number) => {
|
export const applyJitter = (delay: number, jitter: number) => {
|
||||||
const jitter = Math.floor(Math.random() * (2 * jitterMs)) - jitterMs;
|
const jitterTime = Math.floor(Math.random() * (2 * jitter)) - jitter;
|
||||||
return delayMs + jitter;
|
return delay + jitterTime;
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
import { Knex } from "knex";
|
import { Knex } from "knex";
|
||||||
import { Tables } from "knex/types/tables";
|
import { Tables } from "knex/types/tables";
|
||||||
|
|
||||||
|
import { TableName } from "@app/db/schemas";
|
||||||
|
|
||||||
import { DatabaseError } from "../errors";
|
import { DatabaseError } from "../errors";
|
||||||
import { buildDynamicKnexQuery, TKnexDynamicOperator } from "./dynamic";
|
import { buildDynamicKnexQuery, TKnexDynamicOperator } from "./dynamic";
|
||||||
|
|
||||||
@ -25,28 +27,41 @@ export type TFindFilter<R extends object = object> = Partial<R> & {
|
|||||||
$search?: Partial<{ [k in keyof R]: R[k] }>;
|
$search?: Partial<{ [k in keyof R]: R[k] }>;
|
||||||
$complex?: TKnexDynamicOperator<R>;
|
$complex?: TKnexDynamicOperator<R>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const buildFindFilter =
|
export const buildFindFilter =
|
||||||
<R extends object = object>({ $in, $notNull, $search, $complex, ...filter }: TFindFilter<R>) =>
|
<R extends object = object>(
|
||||||
|
{ $in, $notNull, $search, $complex, ...filter }: TFindFilter<R>,
|
||||||
|
tableName?: TableName,
|
||||||
|
excludeKeys?: Array<keyof R>
|
||||||
|
) =>
|
||||||
(bd: Knex.QueryBuilder<R, R>) => {
|
(bd: Knex.QueryBuilder<R, R>) => {
|
||||||
void bd.where(filter);
|
const processedFilter = tableName
|
||||||
|
? Object.fromEntries(
|
||||||
|
Object.entries(filter)
|
||||||
|
.filter(([key]) => !excludeKeys || !excludeKeys.includes(key as keyof R))
|
||||||
|
.map(([key, value]) => [`${tableName}.${key}`, value])
|
||||||
|
)
|
||||||
|
: filter;
|
||||||
|
|
||||||
|
void bd.where(processedFilter);
|
||||||
if ($in) {
|
if ($in) {
|
||||||
Object.entries($in).forEach(([key, val]) => {
|
Object.entries($in).forEach(([key, val]) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
void bd.whereIn(key as never, val as never);
|
void bd.whereIn([`${tableName ? `${tableName}.` : ""}${key}`] as never, val as never);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($notNull?.length) {
|
if ($notNull?.length) {
|
||||||
$notNull.forEach((key) => {
|
$notNull.forEach((key) => {
|
||||||
void bd.whereNotNull(key as never);
|
void bd.whereNotNull([`${tableName ? `${tableName}.` : ""}${key as string}`] as never);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($search) {
|
if ($search) {
|
||||||
Object.entries($search).forEach(([key, val]) => {
|
Object.entries($search).forEach(([key, val]) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
void bd.whereILike(key as never, val as never);
|
void bd.whereILike([`${tableName ? `${tableName}.` : ""}${key}`] as never, val as never);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
3
backend/src/lib/regex/index.ts
Normal file
3
backend/src/lib/regex/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export const DistinguishedNameRegex =
|
||||||
|
// DN format, ie; CN=user,OU=users,DC=example,DC=com
|
||||||
|
/^(?:(?:[a-zA-Z0-9]+=[^,+="<>#;\\\\]+)(?:(?:\\+[a-zA-Z0-9]+=[^,+="<>#;\\\\]+)*)(?:,(?:[a-zA-Z0-9]+=[^,+="<>#;\\\\]+)(?:(?:\\+[a-zA-Z0-9]+=[^,+="<>#;\\\\]+)*))*)?$/;
|
@ -16,3 +16,17 @@ export const fetchGithubEmails = async (accessToken: string) => {
|
|||||||
});
|
});
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type TGithubUser = {
|
||||||
|
name?: string;
|
||||||
|
login: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fetchGithubUser = async (accessToken: string) => {
|
||||||
|
const { data } = await request.get<TGithubUser>(`${INTEGRATION_GITHUB_API_URL}/user`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${accessToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
@ -15,13 +15,13 @@ export const blockLocalAndPrivateIpAddresses = async (url: string) => {
|
|||||||
|
|
||||||
const validUrl = new URL(url);
|
const validUrl = new URL(url);
|
||||||
const inputHostIps: string[] = [];
|
const inputHostIps: string[] = [];
|
||||||
if (isIPv4(validUrl.host)) {
|
if (isIPv4(validUrl.hostname)) {
|
||||||
inputHostIps.push(validUrl.host);
|
inputHostIps.push(validUrl.hostname);
|
||||||
} else {
|
} else {
|
||||||
if (validUrl.host === "localhost" || validUrl.host === "host.docker.internal") {
|
if (validUrl.hostname === "localhost" || validUrl.hostname === "host.docker.internal") {
|
||||||
throw new BadRequestError({ message: "Local IPs not allowed as URL" });
|
throw new BadRequestError({ message: "Local IPs not allowed as URL" });
|
||||||
}
|
}
|
||||||
const resolvedIps = await dns.resolve4(validUrl.host);
|
const resolvedIps = await dns.resolve4(validUrl.hostname);
|
||||||
inputHostIps.push(...resolvedIps);
|
inputHostIps.push(...resolvedIps);
|
||||||
}
|
}
|
||||||
const isInternalIp = inputHostIps.some((el) => isPrivateIp(el));
|
const isInternalIp = inputHostIps.some((el) => isPrivateIp(el));
|
||||||
|
@ -73,6 +73,7 @@ const run = async () => {
|
|||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
process.on("SIGINT", async () => {
|
process.on("SIGINT", async () => {
|
||||||
await server.close();
|
await server.close();
|
||||||
|
await queue.shutdown();
|
||||||
await db.destroy();
|
await db.destroy();
|
||||||
await removeTemporaryBaseDirectory();
|
await removeTemporaryBaseDirectory();
|
||||||
hsmModule.finalize();
|
hsmModule.finalize();
|
||||||
@ -82,19 +83,22 @@ const run = async () => {
|
|||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
process.on("SIGTERM", async () => {
|
process.on("SIGTERM", async () => {
|
||||||
await server.close();
|
await server.close();
|
||||||
|
await queue.shutdown();
|
||||||
await db.destroy();
|
await db.destroy();
|
||||||
await removeTemporaryBaseDirectory();
|
await removeTemporaryBaseDirectory();
|
||||||
hsmModule.finalize();
|
hsmModule.finalize();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on("uncaughtException", (error) => {
|
if (!envConfig.isDevelopmentMode) {
|
||||||
logger.error(error, "CRITICAL ERROR: Uncaught Exception");
|
process.on("uncaughtException", (error) => {
|
||||||
});
|
logger.error(error, "CRITICAL ERROR: Uncaught Exception");
|
||||||
|
});
|
||||||
|
|
||||||
process.on("unhandledRejection", (error) => {
|
process.on("unhandledRejection", (error) => {
|
||||||
logger.error(error, "CRITICAL ERROR: Unhandled Promise Rejection");
|
logger.error(error, "CRITICAL ERROR: Unhandled Promise Rejection");
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await server.listen({
|
await server.listen({
|
||||||
port: envConfig.PORT,
|
port: envConfig.PORT,
|
||||||
|
24
backend/src/server/plugins/auth/inject-assume-privilege.ts
Normal file
24
backend/src/server/plugins/auth/inject-assume-privilege.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { requestContext } from "@fastify/request-context";
|
||||||
|
import fp from "fastify-plugin";
|
||||||
|
|
||||||
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
|
export const injectAssumePrivilege = fp(async (server: FastifyZodProvider) => {
|
||||||
|
server.addHook("onRequest", async (req, res) => {
|
||||||
|
const assumeRoleCookie = req.cookies["infisical-project-assume-privileges"];
|
||||||
|
try {
|
||||||
|
if (req?.auth?.authMode === AuthMode.JWT && assumeRoleCookie) {
|
||||||
|
const decodedToken = server.services.assumePrivileges.verifyAssumePrivilegeToken(
|
||||||
|
assumeRoleCookie,
|
||||||
|
req.auth.tokenVersionId
|
||||||
|
);
|
||||||
|
if (decodedToken) {
|
||||||
|
requestContext.set("assumedPrivilegeDetails", decodedToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
req.log.error({ error }, "Failed to verify assume privilege token");
|
||||||
|
void res.clearCookie("infisical-project-assume-privileges");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -49,14 +49,17 @@ function resolveSchema(maybeSchema: ZodAny | { properties: ZodAny }): Pick<ZodAn
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const createJsonSchemaTransform = ({ skipList }: { skipList: readonly string[] }) => {
|
export const createJsonSchemaTransform = ({ skipList }: { skipList: readonly string[] }) => {
|
||||||
return ({ schema, url }: { schema: Schema; url: string }) => {
|
return ({ schema = {}, url }: { schema: Schema; url: string }) => {
|
||||||
if (!schema) {
|
if (!schema) {
|
||||||
return {
|
return {
|
||||||
schema,
|
schema: { hide: true },
|
||||||
url
|
url
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof schema.hide === "undefined") {
|
||||||
|
schema.hide = true;
|
||||||
|
}
|
||||||
const { response, headers, querystring, body, params, hide, ...rest } = schema;
|
const { response, headers, querystring, body, params, hide, ...rest } = schema;
|
||||||
|
|
||||||
const transformed: FreeformRecord = {};
|
const transformed: FreeformRecord = {};
|
||||||
|
@ -12,6 +12,7 @@ import { accessApprovalPolicyServiceFactory } from "@app/ee/services/access-appr
|
|||||||
import { accessApprovalRequestDALFactory } from "@app/ee/services/access-approval-request/access-approval-request-dal";
|
import { accessApprovalRequestDALFactory } from "@app/ee/services/access-approval-request/access-approval-request-dal";
|
||||||
import { accessApprovalRequestReviewerDALFactory } from "@app/ee/services/access-approval-request/access-approval-request-reviewer-dal";
|
import { accessApprovalRequestReviewerDALFactory } from "@app/ee/services/access-approval-request/access-approval-request-reviewer-dal";
|
||||||
import { accessApprovalRequestServiceFactory } from "@app/ee/services/access-approval-request/access-approval-request-service";
|
import { accessApprovalRequestServiceFactory } from "@app/ee/services/access-approval-request/access-approval-request-service";
|
||||||
|
import { assumePrivilegeServiceFactory } from "@app/ee/services/assume-privilege/assume-privilege-service";
|
||||||
import { auditLogDALFactory } from "@app/ee/services/audit-log/audit-log-dal";
|
import { auditLogDALFactory } from "@app/ee/services/audit-log/audit-log-dal";
|
||||||
import { auditLogQueueServiceFactory } from "@app/ee/services/audit-log/audit-log-queue";
|
import { auditLogQueueServiceFactory } from "@app/ee/services/audit-log/audit-log-queue";
|
||||||
import { auditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
import { auditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
||||||
@ -32,6 +33,8 @@ import { gatewayDALFactory } from "@app/ee/services/gateway/gateway-dal";
|
|||||||
import { gatewayServiceFactory } from "@app/ee/services/gateway/gateway-service";
|
import { gatewayServiceFactory } from "@app/ee/services/gateway/gateway-service";
|
||||||
import { orgGatewayConfigDALFactory } from "@app/ee/services/gateway/org-gateway-config-dal";
|
import { orgGatewayConfigDALFactory } from "@app/ee/services/gateway/org-gateway-config-dal";
|
||||||
import { projectGatewayDALFactory } from "@app/ee/services/gateway/project-gateway-dal";
|
import { projectGatewayDALFactory } from "@app/ee/services/gateway/project-gateway-dal";
|
||||||
|
import { githubOrgSyncDALFactory } from "@app/ee/services/github-org-sync/github-org-sync-dal";
|
||||||
|
import { githubOrgSyncServiceFactory } from "@app/ee/services/github-org-sync/github-org-sync-service";
|
||||||
import { groupDALFactory } from "@app/ee/services/group/group-dal";
|
import { groupDALFactory } from "@app/ee/services/group/group-dal";
|
||||||
import { groupServiceFactory } from "@app/ee/services/group/group-service";
|
import { groupServiceFactory } from "@app/ee/services/group/group-service";
|
||||||
import { userGroupMembershipDALFactory } from "@app/ee/services/group/user-group-membership-dal";
|
import { userGroupMembershipDALFactory } from "@app/ee/services/group/user-group-membership-dal";
|
||||||
@ -214,6 +217,7 @@ import { secretFolderServiceFactory } from "@app/services/secret-folder/secret-f
|
|||||||
import { secretFolderVersionDALFactory } from "@app/services/secret-folder/secret-folder-version-dal";
|
import { secretFolderVersionDALFactory } from "@app/services/secret-folder/secret-folder-version-dal";
|
||||||
import { secretImportDALFactory } from "@app/services/secret-import/secret-import-dal";
|
import { secretImportDALFactory } from "@app/services/secret-import/secret-import-dal";
|
||||||
import { secretImportServiceFactory } from "@app/services/secret-import/secret-import-service";
|
import { secretImportServiceFactory } from "@app/services/secret-import/secret-import-service";
|
||||||
|
import { secretReminderRecipientsDALFactory } from "@app/services/secret-reminder-recipients/secret-reminder-recipients-dal";
|
||||||
import { secretSharingDALFactory } from "@app/services/secret-sharing/secret-sharing-dal";
|
import { secretSharingDALFactory } from "@app/services/secret-sharing/secret-sharing-dal";
|
||||||
import { secretSharingServiceFactory } from "@app/services/secret-sharing/secret-sharing-service";
|
import { secretSharingServiceFactory } from "@app/services/secret-sharing/secret-sharing-service";
|
||||||
import { secretSyncDALFactory } from "@app/services/secret-sync/secret-sync-dal";
|
import { secretSyncDALFactory } from "@app/services/secret-sync/secret-sync-dal";
|
||||||
@ -248,6 +252,7 @@ import { workflowIntegrationDALFactory } from "@app/services/workflow-integratio
|
|||||||
import { workflowIntegrationServiceFactory } from "@app/services/workflow-integration/workflow-integration-service";
|
import { workflowIntegrationServiceFactory } from "@app/services/workflow-integration/workflow-integration-service";
|
||||||
|
|
||||||
import { injectAuditLogInfo } from "../plugins/audit-log";
|
import { injectAuditLogInfo } from "../plugins/audit-log";
|
||||||
|
import { injectAssumePrivilege } from "../plugins/auth/inject-assume-privilege";
|
||||||
import { injectIdentity } from "../plugins/auth/inject-identity";
|
import { injectIdentity } from "../plugins/auth/inject-identity";
|
||||||
import { injectPermission } from "../plugins/auth/inject-permission";
|
import { injectPermission } from "../plugins/auth/inject-permission";
|
||||||
import { injectRateLimits } from "../plugins/inject-rate-limits";
|
import { injectRateLimits } from "../plugins/inject-rate-limits";
|
||||||
@ -417,6 +422,8 @@ export const registerRoutes = async (
|
|||||||
const orgGatewayConfigDAL = orgGatewayConfigDALFactory(db);
|
const orgGatewayConfigDAL = orgGatewayConfigDALFactory(db);
|
||||||
const gatewayDAL = gatewayDALFactory(db);
|
const gatewayDAL = gatewayDALFactory(db);
|
||||||
const projectGatewayDAL = projectGatewayDALFactory(db);
|
const projectGatewayDAL = projectGatewayDALFactory(db);
|
||||||
|
const secretReminderRecipientsDAL = secretReminderRecipientsDALFactory(db);
|
||||||
|
const githubOrgSyncDAL = githubOrgSyncDALFactory(db);
|
||||||
|
|
||||||
const secretRotationV2DAL = secretRotationV2DALFactory(db, folderDAL);
|
const secretRotationV2DAL = secretRotationV2DALFactory(db, folderDAL);
|
||||||
|
|
||||||
@ -427,6 +434,11 @@ export const registerRoutes = async (
|
|||||||
serviceTokenDAL,
|
serviceTokenDAL,
|
||||||
projectDAL
|
projectDAL
|
||||||
});
|
});
|
||||||
|
const assumePrivilegeService = assumePrivilegeServiceFactory({
|
||||||
|
projectDAL,
|
||||||
|
permissionService
|
||||||
|
});
|
||||||
|
|
||||||
const licenseService = licenseServiceFactory({
|
const licenseService = licenseServiceFactory({
|
||||||
permissionService,
|
permissionService,
|
||||||
orgDAL,
|
orgDAL,
|
||||||
@ -549,6 +561,15 @@ export const registerRoutes = async (
|
|||||||
externalGroupOrgRoleMappingDAL
|
externalGroupOrgRoleMappingDAL
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const githubOrgSyncConfigService = githubOrgSyncServiceFactory({
|
||||||
|
licenseService,
|
||||||
|
githubOrgSyncDAL,
|
||||||
|
kmsService,
|
||||||
|
permissionService,
|
||||||
|
groupDAL,
|
||||||
|
userGroupMembershipDAL
|
||||||
|
});
|
||||||
|
|
||||||
const ldapService = ldapConfigServiceFactory({
|
const ldapService = ldapConfigServiceFactory({
|
||||||
ldapConfigDAL,
|
ldapConfigDAL,
|
||||||
ldapGroupMapDAL,
|
ldapGroupMapDAL,
|
||||||
@ -596,7 +617,14 @@ export const registerRoutes = async (
|
|||||||
kmsService
|
kmsService
|
||||||
});
|
});
|
||||||
|
|
||||||
const loginService = authLoginServiceFactory({ userDAL, smtpService, tokenService, orgDAL, totpService });
|
const loginService = authLoginServiceFactory({
|
||||||
|
userDAL,
|
||||||
|
smtpService,
|
||||||
|
tokenService,
|
||||||
|
orgDAL,
|
||||||
|
totpService,
|
||||||
|
auditLogService
|
||||||
|
});
|
||||||
const passwordService = authPaswordServiceFactory({
|
const passwordService = authPaswordServiceFactory({
|
||||||
tokenService,
|
tokenService,
|
||||||
smtpService,
|
smtpService,
|
||||||
@ -721,6 +749,7 @@ export const registerRoutes = async (
|
|||||||
projectKeyDAL,
|
projectKeyDAL,
|
||||||
projectRoleDAL,
|
projectRoleDAL,
|
||||||
groupProjectDAL,
|
groupProjectDAL,
|
||||||
|
secretReminderRecipientsDAL,
|
||||||
licenseService
|
licenseService
|
||||||
});
|
});
|
||||||
const projectUserAdditionalPrivilegeService = projectUserAdditionalPrivilegeServiceFactory({
|
const projectUserAdditionalPrivilegeService = projectUserAdditionalPrivilegeServiceFactory({
|
||||||
@ -954,6 +983,7 @@ export const registerRoutes = async (
|
|||||||
secretApprovalRequestDAL,
|
secretApprovalRequestDAL,
|
||||||
projectKeyDAL,
|
projectKeyDAL,
|
||||||
projectUserMembershipRoleDAL,
|
projectUserMembershipRoleDAL,
|
||||||
|
secretReminderRecipientsDAL,
|
||||||
orgService,
|
orgService,
|
||||||
resourceMetadataDAL,
|
resourceMetadataDAL,
|
||||||
secretSyncQueue
|
secretSyncQueue
|
||||||
@ -1015,7 +1045,9 @@ export const registerRoutes = async (
|
|||||||
projectRoleDAL,
|
projectRoleDAL,
|
||||||
projectUserMembershipRoleDAL,
|
projectUserMembershipRoleDAL,
|
||||||
identityProjectMembershipRoleDAL,
|
identityProjectMembershipRoleDAL,
|
||||||
projectDAL
|
projectDAL,
|
||||||
|
identityDAL,
|
||||||
|
userDAL
|
||||||
});
|
});
|
||||||
|
|
||||||
const snapshotService = secretSnapshotServiceFactory({
|
const snapshotService = secretSnapshotServiceFactory({
|
||||||
@ -1089,7 +1121,8 @@ export const registerRoutes = async (
|
|||||||
secretApprovalRequestSecretDAL,
|
secretApprovalRequestSecretDAL,
|
||||||
kmsService,
|
kmsService,
|
||||||
snapshotService,
|
snapshotService,
|
||||||
resourceMetadataDAL
|
resourceMetadataDAL,
|
||||||
|
keyStore
|
||||||
});
|
});
|
||||||
|
|
||||||
const secretApprovalRequestService = secretApprovalRequestServiceFactory({
|
const secretApprovalRequestService = secretApprovalRequestServiceFactory({
|
||||||
@ -1667,7 +1700,9 @@ export const registerRoutes = async (
|
|||||||
kmip: kmipService,
|
kmip: kmipService,
|
||||||
kmipOperation: kmipOperationService,
|
kmipOperation: kmipOperationService,
|
||||||
gateway: gatewayService,
|
gateway: gatewayService,
|
||||||
secretRotationV2: secretRotationV2Service
|
secretRotationV2: secretRotationV2Service,
|
||||||
|
assumePrivileges: assumePrivilegeService,
|
||||||
|
githubOrgSync: githubOrgSyncConfigService
|
||||||
});
|
});
|
||||||
|
|
||||||
const cronJobs: CronJob[] = [];
|
const cronJobs: CronJob[] = [];
|
||||||
@ -1688,6 +1723,7 @@ export const registerRoutes = async (
|
|||||||
});
|
});
|
||||||
|
|
||||||
await server.register(injectIdentity, { userDAL, serviceTokenDAL });
|
await server.register(injectIdentity, { userDAL, serviceTokenDAL });
|
||||||
|
await server.register(injectAssumePrivilege);
|
||||||
await server.register(injectPermission);
|
await server.register(injectPermission);
|
||||||
await server.register(injectRateLimits);
|
await server.register(injectRateLimits);
|
||||||
await server.register(injectAuditLogInfo);
|
await server.register(injectAuditLogInfo);
|
||||||
@ -1727,30 +1763,6 @@ export const registerRoutes = async (
|
|||||||
|
|
||||||
logger.info(`Raw event loop stats: ${JSON.stringify(histogram, null, 2)}`);
|
logger.info(`Raw event loop stats: ${JSON.stringify(histogram, null, 2)}`);
|
||||||
|
|
||||||
// try {
|
|
||||||
// await db.raw("SELECT NOW()");
|
|
||||||
// } catch (err) {
|
|
||||||
// logger.error("Health check: database connection failed", err);
|
|
||||||
// return reply.code(503).send({
|
|
||||||
// date: new Date(),
|
|
||||||
// message: "Service unavailable"
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (cfg.isRedisConfigured) {
|
|
||||||
// const redis = new Redis(cfg.REDIS_URL);
|
|
||||||
// try {
|
|
||||||
// await redis.ping();
|
|
||||||
// redis.disconnect();
|
|
||||||
// } catch (err) {
|
|
||||||
// logger.error("Health check: redis connection failed", err);
|
|
||||||
// return reply.code(503).send({
|
|
||||||
// date: new Date(),
|
|
||||||
// message: "Service unavailable"
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
date: new Date(),
|
date: new Date(),
|
||||||
message: "Ok",
|
message: "Ok",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { AppConnections } from "@app/lib/api-docs";
|
import { ApiDocsTags, AppConnections } from "@app/lib/api-docs";
|
||||||
import { startsWithVowel } from "@app/lib/fn";
|
import { startsWithVowel } from "@app/lib/fn";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
@ -43,6 +43,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AppConnections],
|
||||||
description: `List the ${appName} Connections for the current organization.`,
|
description: `List the ${appName} Connections for the current organization.`,
|
||||||
response: {
|
response: {
|
||||||
200: z.object({ appConnections: sanitizedResponseSchema.array() })
|
200: z.object({ appConnections: sanitizedResponseSchema.array() })
|
||||||
@ -76,6 +78,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AppConnections],
|
||||||
description: `List the ${appName} Connections the current user has permission to establish connections with.`,
|
description: `List the ${appName} Connections the current user has permission to establish connections with.`,
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@ -120,6 +124,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AppConnections],
|
||||||
description: `Get the specified ${appName} Connection by ID.`,
|
description: `Get the specified ${appName} Connection by ID.`,
|
||||||
params: z.object({
|
params: z.object({
|
||||||
connectionId: z.string().uuid().describe(AppConnections.GET_BY_ID(app).connectionId)
|
connectionId: z.string().uuid().describe(AppConnections.GET_BY_ID(app).connectionId)
|
||||||
@ -160,6 +166,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AppConnections],
|
||||||
description: `Get the specified ${appName} Connection by name.`,
|
description: `Get the specified ${appName} Connection by name.`,
|
||||||
params: z.object({
|
params: z.object({
|
||||||
connectionName: z
|
connectionName: z
|
||||||
@ -204,6 +212,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AppConnections],
|
||||||
description: `Create ${
|
description: `Create ${
|
||||||
startsWithVowel(appName) ? "an" : "a"
|
startsWithVowel(appName) ? "an" : "a"
|
||||||
} ${appName} Connection for the current organization.`,
|
} ${appName} Connection for the current organization.`,
|
||||||
@ -247,6 +257,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AppConnections],
|
||||||
description: `Update the specified ${appName} Connection.`,
|
description: `Update the specified ${appName} Connection.`,
|
||||||
params: z.object({
|
params: z.object({
|
||||||
connectionId: z.string().uuid().describe(AppConnections.UPDATE(app).connectionId)
|
connectionId: z.string().uuid().describe(AppConnections.UPDATE(app).connectionId)
|
||||||
@ -292,6 +304,8 @@ export const registerAppConnectionEndpoints = <T extends TAppConnection, I exten
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AppConnections],
|
||||||
description: `Delete the specified ${appName} Connection.`,
|
description: `Delete the specified ${appName} Connection.`,
|
||||||
params: z.object({
|
params: z.object({
|
||||||
connectionId: z.string().uuid().describe(AppConnections.DELETE(app).connectionId)
|
connectionId: z.string().uuid().describe(AppConnections.DELETE(app).connectionId)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
|
import { ApiDocsTags } from "@app/lib/api-docs";
|
||||||
import { readLimit } from "@app/server/config/rateLimiter";
|
import { readLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { Auth0ConnectionListItemSchema, SanitizedAuth0ConnectionSchema } from "@app/services/app-connection/auth0";
|
import { Auth0ConnectionListItemSchema, SanitizedAuth0ConnectionSchema } from "@app/services/app-connection/auth0";
|
||||||
@ -27,11 +28,16 @@ import {
|
|||||||
HumanitecConnectionListItemSchema,
|
HumanitecConnectionListItemSchema,
|
||||||
SanitizedHumanitecConnectionSchema
|
SanitizedHumanitecConnectionSchema
|
||||||
} from "@app/services/app-connection/humanitec";
|
} from "@app/services/app-connection/humanitec";
|
||||||
|
import { LdapConnectionListItemSchema, SanitizedLdapConnectionSchema } from "@app/services/app-connection/ldap";
|
||||||
import { MsSqlConnectionListItemSchema, SanitizedMsSqlConnectionSchema } from "@app/services/app-connection/mssql";
|
import { MsSqlConnectionListItemSchema, SanitizedMsSqlConnectionSchema } from "@app/services/app-connection/mssql";
|
||||||
import {
|
import {
|
||||||
PostgresConnectionListItemSchema,
|
PostgresConnectionListItemSchema,
|
||||||
SanitizedPostgresConnectionSchema
|
SanitizedPostgresConnectionSchema
|
||||||
} from "@app/services/app-connection/postgres";
|
} from "@app/services/app-connection/postgres";
|
||||||
|
import {
|
||||||
|
SanitizedTeamCityConnectionSchema,
|
||||||
|
TeamCityConnectionListItemSchema
|
||||||
|
} from "@app/services/app-connection/teamcity";
|
||||||
import {
|
import {
|
||||||
SanitizedTerraformCloudConnectionSchema,
|
SanitizedTerraformCloudConnectionSchema,
|
||||||
TerraformCloudConnectionListItemSchema
|
TerraformCloudConnectionListItemSchema
|
||||||
@ -58,7 +64,9 @@ const SanitizedAppConnectionSchema = z.union([
|
|||||||
...SanitizedMsSqlConnectionSchema.options,
|
...SanitizedMsSqlConnectionSchema.options,
|
||||||
...SanitizedCamundaConnectionSchema.options,
|
...SanitizedCamundaConnectionSchema.options,
|
||||||
...SanitizedWindmillConnectionSchema.options,
|
...SanitizedWindmillConnectionSchema.options,
|
||||||
...SanitizedAuth0ConnectionSchema.options
|
...SanitizedAuth0ConnectionSchema.options,
|
||||||
|
...SanitizedLdapConnectionSchema.options,
|
||||||
|
...SanitizedTeamCityConnectionSchema.options
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const AppConnectionOptionsSchema = z.discriminatedUnion("app", [
|
const AppConnectionOptionsSchema = z.discriminatedUnion("app", [
|
||||||
@ -75,7 +83,9 @@ const AppConnectionOptionsSchema = z.discriminatedUnion("app", [
|
|||||||
MsSqlConnectionListItemSchema,
|
MsSqlConnectionListItemSchema,
|
||||||
CamundaConnectionListItemSchema,
|
CamundaConnectionListItemSchema,
|
||||||
WindmillConnectionListItemSchema,
|
WindmillConnectionListItemSchema,
|
||||||
Auth0ConnectionListItemSchema
|
Auth0ConnectionListItemSchema,
|
||||||
|
LdapConnectionListItemSchema,
|
||||||
|
TeamCityConnectionListItemSchema
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const registerAppConnectionRouter = async (server: FastifyZodProvider) => {
|
export const registerAppConnectionRouter = async (server: FastifyZodProvider) => {
|
||||||
@ -86,6 +96,8 @@ export const registerAppConnectionRouter = async (server: FastifyZodProvider) =>
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AppConnections],
|
||||||
description: "List the available App Connection Options.",
|
description: "List the available App Connection Options.",
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@ -107,6 +119,8 @@ export const registerAppConnectionRouter = async (server: FastifyZodProvider) =>
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AppConnections],
|
||||||
description: "List all the App Connections for the current organization.",
|
description: "List all the App Connections for the current organization.",
|
||||||
response: {
|
response: {
|
||||||
200: z.object({ appConnections: SanitizedAppConnectionSchema.array() })
|
200: z.object({ appConnections: SanitizedAppConnectionSchema.array() })
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { registerAuth0ConnectionRouter } from "@app/server/routes/v1/app-connection-routers/auth0-connection-router";
|
|
||||||
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||||
|
|
||||||
|
import { registerAuth0ConnectionRouter } from "./auth0-connection-router";
|
||||||
import { registerAwsConnectionRouter } from "./aws-connection-router";
|
import { registerAwsConnectionRouter } from "./aws-connection-router";
|
||||||
import { registerAzureAppConfigurationConnectionRouter } from "./azure-app-configuration-connection-router";
|
import { registerAzureAppConfigurationConnectionRouter } from "./azure-app-configuration-connection-router";
|
||||||
import { registerAzureKeyVaultConnectionRouter } from "./azure-key-vault-connection-router";
|
import { registerAzureKeyVaultConnectionRouter } from "./azure-key-vault-connection-router";
|
||||||
@ -9,8 +9,10 @@ import { registerDatabricksConnectionRouter } from "./databricks-connection-rout
|
|||||||
import { registerGcpConnectionRouter } from "./gcp-connection-router";
|
import { registerGcpConnectionRouter } from "./gcp-connection-router";
|
||||||
import { registerGitHubConnectionRouter } from "./github-connection-router";
|
import { registerGitHubConnectionRouter } from "./github-connection-router";
|
||||||
import { registerHumanitecConnectionRouter } from "./humanitec-connection-router";
|
import { registerHumanitecConnectionRouter } from "./humanitec-connection-router";
|
||||||
|
import { registerLdapConnectionRouter } from "./ldap-connection-router";
|
||||||
import { registerMsSqlConnectionRouter } from "./mssql-connection-router";
|
import { registerMsSqlConnectionRouter } from "./mssql-connection-router";
|
||||||
import { registerPostgresConnectionRouter } from "./postgres-connection-router";
|
import { registerPostgresConnectionRouter } from "./postgres-connection-router";
|
||||||
|
import { registerTeamCityConnectionRouter } from "./teamcity-connection-router";
|
||||||
import { registerTerraformCloudConnectionRouter } from "./terraform-cloud-router";
|
import { registerTerraformCloudConnectionRouter } from "./terraform-cloud-router";
|
||||||
import { registerVercelConnectionRouter } from "./vercel-connection-router";
|
import { registerVercelConnectionRouter } from "./vercel-connection-router";
|
||||||
import { registerWindmillConnectionRouter } from "./windmill-connection-router";
|
import { registerWindmillConnectionRouter } from "./windmill-connection-router";
|
||||||
@ -32,5 +34,7 @@ export const APP_CONNECTION_REGISTER_ROUTER_MAP: Record<AppConnection, (server:
|
|||||||
[AppConnection.MsSql]: registerMsSqlConnectionRouter,
|
[AppConnection.MsSql]: registerMsSqlConnectionRouter,
|
||||||
[AppConnection.Camunda]: registerCamundaConnectionRouter,
|
[AppConnection.Camunda]: registerCamundaConnectionRouter,
|
||||||
[AppConnection.Windmill]: registerWindmillConnectionRouter,
|
[AppConnection.Windmill]: registerWindmillConnectionRouter,
|
||||||
[AppConnection.Auth0]: registerAuth0ConnectionRouter
|
[AppConnection.Auth0]: registerAuth0ConnectionRouter,
|
||||||
|
[AppConnection.LDAP]: registerLdapConnectionRouter,
|
||||||
|
[AppConnection.TeamCity]: registerTeamCityConnectionRouter
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||||
|
import {
|
||||||
|
CreateLdapConnectionSchema,
|
||||||
|
SanitizedLdapConnectionSchema,
|
||||||
|
UpdateLdapConnectionSchema
|
||||||
|
} from "@app/services/app-connection/ldap";
|
||||||
|
|
||||||
|
import { registerAppConnectionEndpoints } from "./app-connection-endpoints";
|
||||||
|
|
||||||
|
export const registerLdapConnectionRouter = async (server: FastifyZodProvider) => {
|
||||||
|
registerAppConnectionEndpoints({
|
||||||
|
app: AppConnection.LDAP,
|
||||||
|
server,
|
||||||
|
sanitizedResponseSchema: SanitizedLdapConnectionSchema,
|
||||||
|
createSchema: CreateLdapConnectionSchema,
|
||||||
|
updateSchema: UpdateLdapConnectionSchema
|
||||||
|
});
|
||||||
|
};
|
@ -0,0 +1,60 @@
|
|||||||
|
import z from "zod";
|
||||||
|
|
||||||
|
import { readLimit } from "@app/server/config/rateLimiter";
|
||||||
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
|
import { AppConnection } from "@app/services/app-connection/app-connection-enums";
|
||||||
|
import {
|
||||||
|
CreateTeamCityConnectionSchema,
|
||||||
|
SanitizedTeamCityConnectionSchema,
|
||||||
|
UpdateTeamCityConnectionSchema
|
||||||
|
} from "@app/services/app-connection/teamcity";
|
||||||
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
|
import { registerAppConnectionEndpoints } from "./app-connection-endpoints";
|
||||||
|
|
||||||
|
export const registerTeamCityConnectionRouter = async (server: FastifyZodProvider) => {
|
||||||
|
registerAppConnectionEndpoints({
|
||||||
|
app: AppConnection.TeamCity,
|
||||||
|
server,
|
||||||
|
sanitizedResponseSchema: SanitizedTeamCityConnectionSchema,
|
||||||
|
createSchema: CreateTeamCityConnectionSchema,
|
||||||
|
updateSchema: UpdateTeamCityConnectionSchema
|
||||||
|
});
|
||||||
|
|
||||||
|
// The following endpoints are for internal Infisical App use only and not part of the public API
|
||||||
|
server.route({
|
||||||
|
method: "GET",
|
||||||
|
url: `/:connectionId/projects`,
|
||||||
|
config: {
|
||||||
|
rateLimit: readLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
params: z.object({
|
||||||
|
connectionId: z.string().uuid()
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z
|
||||||
|
.object({
|
||||||
|
id: z.string(),
|
||||||
|
name: z.string(),
|
||||||
|
buildTypes: z.object({
|
||||||
|
buildType: z
|
||||||
|
.object({
|
||||||
|
id: z.string(),
|
||||||
|
name: z.string()
|
||||||
|
})
|
||||||
|
.array()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.array()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const { connectionId } = req.params;
|
||||||
|
const projects = await server.services.appConnection.teamcity.listProjects(connectionId, req.permission);
|
||||||
|
|
||||||
|
return projects;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
@ -33,6 +33,14 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
|
|||||||
secure: appCfg.HTTPS_ENABLED
|
secure: appCfg.HTTPS_ENABLED
|
||||||
});
|
});
|
||||||
|
|
||||||
|
void res.cookie("infisical-project-assume-privileges", "", {
|
||||||
|
httpOnly: true,
|
||||||
|
path: "/",
|
||||||
|
sameSite: "strict",
|
||||||
|
secure: appCfg.HTTPS_ENABLED,
|
||||||
|
maxAge: 0
|
||||||
|
});
|
||||||
|
|
||||||
return { message: "Successfully logged out" };
|
return { message: "Successfully logged out" };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -3,7 +3,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { CertificateAuthoritiesSchema, CertificateTemplatesSchema } from "@app/db/schemas";
|
import { CertificateAuthoritiesSchema, CertificateTemplatesSchema } from "@app/db/schemas";
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
|
import { ApiDocsTags, CERTIFICATE_AUTHORITIES } from "@app/lib/api-docs";
|
||||||
import { ms } from "@app/lib/ms";
|
import { ms } from "@app/lib/ms";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||||
@ -26,6 +26,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Create CA",
|
description: "Create CA",
|
||||||
body: z
|
body: z
|
||||||
.object({
|
.object({
|
||||||
@ -105,6 +107,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Get CA",
|
description: "Get CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET.caId)
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET.caId)
|
||||||
@ -151,6 +155,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Get DER-encoded certificate of CA",
|
description: "Get DER-encoded certificate of CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT_BY_ID.caId),
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT_BY_ID.caId),
|
||||||
@ -177,6 +183,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Update CA",
|
description: "Update CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.UPDATE.caId)
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.UPDATE.caId)
|
||||||
@ -231,6 +239,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Delete CA",
|
description: "Delete CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.DELETE.caId)
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.DELETE.caId)
|
||||||
@ -276,6 +286,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Get CA CSR",
|
description: "Get CA CSR",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CSR.caId)
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CSR.caId)
|
||||||
@ -321,6 +333,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Perform CA certificate renewal",
|
description: "Perform CA certificate renewal",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.RENEW_CA_CERT.caId)
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.RENEW_CA_CERT.caId)
|
||||||
@ -376,6 +390,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Get list of past and current CA certificates for a CA",
|
description: "Get list of past and current CA certificates for a CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CA_CERTS.caId)
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CA_CERTS.caId)
|
||||||
@ -424,6 +440,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Get current CA cert and cert chain of a CA",
|
description: "Get current CA cert and cert chain of a CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT.caId)
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CERT.caId)
|
||||||
@ -473,6 +491,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Create intermediate CA certificate from parent CA",
|
description: "Create intermediate CA certificate from parent CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.caId)
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_INTERMEDIATE.caId)
|
||||||
@ -536,6 +556,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Import certificate and chain to CA",
|
description: "Import certificate and chain to CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.IMPORT_CERT.caId)
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.IMPORT_CERT.caId)
|
||||||
@ -588,6 +610,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Issue certificate from CA",
|
description: "Issue certificate from CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.caId)
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.ISSUE_CERT.caId)
|
||||||
@ -679,6 +703,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Sign certificate from CA",
|
description: "Sign certificate from CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.caId)
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.caId)
|
||||||
@ -770,6 +796,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Get list of certificate templates for the CA",
|
description: "Get list of certificate templates for the CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.caId)
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.SIGN_CERT.caId)
|
||||||
@ -815,6 +843,8 @@ export const registerCaRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateAuthorities],
|
||||||
description: "Get list of CRLs of the CA",
|
description: "Get list of CRLs of the CA",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CRLS.caId)
|
caId: z.string().trim().describe(CERTIFICATE_AUTHORITIES.GET_CRLS.caId)
|
||||||
|
@ -2,7 +2,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { CertificatesSchema } from "@app/db/schemas";
|
import { CertificatesSchema } from "@app/db/schemas";
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { CERTIFICATE_AUTHORITIES, CERTIFICATES } from "@app/lib/api-docs";
|
import { ApiDocsTags, CERTIFICATE_AUTHORITIES, CERTIFICATES } from "@app/lib/api-docs";
|
||||||
import { ms } from "@app/lib/ms";
|
import { ms } from "@app/lib/ms";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
import { getTelemetryDistinctId } from "@app/server/lib/telemetry";
|
||||||
@ -24,6 +24,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificates],
|
||||||
description: "Get certificate",
|
description: "Get certificate",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
serialNumber: z.string().trim().describe(CERTIFICATES.GET.serialNumber)
|
serialNumber: z.string().trim().describe(CERTIFICATES.GET.serialNumber)
|
||||||
@ -70,6 +72,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificates],
|
||||||
description: "Issue certificate",
|
description: "Issue certificate",
|
||||||
body: z
|
body: z
|
||||||
.object({
|
.object({
|
||||||
@ -181,6 +185,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificates],
|
||||||
description: "Sign certificate",
|
description: "Sign certificate",
|
||||||
body: z
|
body: z
|
||||||
.object({
|
.object({
|
||||||
@ -292,6 +298,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificates],
|
||||||
description: "Revoke",
|
description: "Revoke",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
serialNumber: z.string().trim().describe(CERTIFICATES.REVOKE.serialNumber)
|
serialNumber: z.string().trim().describe(CERTIFICATES.REVOKE.serialNumber)
|
||||||
@ -346,6 +354,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificates],
|
||||||
description: "Delete certificate",
|
description: "Delete certificate",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
serialNumber: z.string().trim().describe(CERTIFICATES.DELETE.serialNumber)
|
serialNumber: z.string().trim().describe(CERTIFICATES.DELETE.serialNumber)
|
||||||
@ -392,6 +402,8 @@ export const registerCertRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificates],
|
||||||
description: "Get certificate body of certificate",
|
description: "Get certificate body of certificate",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
serialNumber: z.string().trim().describe(CERTIFICATES.GET_CERT.serialNumber)
|
serialNumber: z.string().trim().describe(CERTIFICATES.GET_CERT.serialNumber)
|
||||||
|
@ -2,7 +2,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { CertificateTemplateEstConfigsSchema } from "@app/db/schemas";
|
import { CertificateTemplateEstConfigsSchema } from "@app/db/schemas";
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { CERTIFICATE_TEMPLATES } from "@app/lib/api-docs";
|
import { ApiDocsTags, CERTIFICATE_TEMPLATES } from "@app/lib/api-docs";
|
||||||
import { ms } from "@app/lib/ms";
|
import { ms } from "@app/lib/ms";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
@ -26,6 +26,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.GET.certificateTemplateId)
|
certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.GET.certificateTemplateId)
|
||||||
}),
|
}),
|
||||||
@ -65,6 +67,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||||
body: z.object({
|
body: z.object({
|
||||||
caId: z.string().describe(CERTIFICATE_TEMPLATES.CREATE.caId),
|
caId: z.string().describe(CERTIFICATE_TEMPLATES.CREATE.caId),
|
||||||
pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.CREATE.pkiCollectionId),
|
pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.CREATE.pkiCollectionId),
|
||||||
@ -132,6 +136,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||||
body: z.object({
|
body: z.object({
|
||||||
caId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.caId),
|
caId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.caId),
|
||||||
pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.pkiCollectionId),
|
pkiCollectionId: z.string().optional().describe(CERTIFICATE_TEMPLATES.UPDATE.pkiCollectionId),
|
||||||
@ -198,6 +204,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||||
params: z.object({
|
params: z.object({
|
||||||
certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.DELETE.certificateTemplateId)
|
certificateTemplateId: z.string().describe(CERTIFICATE_TEMPLATES.DELETE.certificateTemplateId)
|
||||||
}),
|
}),
|
||||||
@ -238,6 +246,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||||
description: "Create Certificate Template EST configuration",
|
description: "Create Certificate Template EST configuration",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
certificateTemplateId: z.string().trim()
|
certificateTemplateId: z.string().trim()
|
||||||
@ -292,6 +302,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||||
description: "Update Certificate Template EST configuration",
|
description: "Update Certificate Template EST configuration",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
certificateTemplateId: z.string().trim()
|
certificateTemplateId: z.string().trim()
|
||||||
@ -340,6 +352,8 @@ export const registerCertificateTemplateRouter = async (server: FastifyZodProvid
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.PkiCertificateTemplates],
|
||||||
description: "Get Certificate Template EST configuration",
|
description: "Get Certificate Template EST configuration",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
certificateTemplateId: z.string().trim()
|
certificateTemplateId: z.string().trim()
|
||||||
|
@ -2,7 +2,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { InternalKmsSchema, KmsKeysSchema } from "@app/db/schemas";
|
import { InternalKmsSchema, KmsKeysSchema } from "@app/db/schemas";
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { KMS } from "@app/lib/api-docs";
|
import { ApiDocsTags, KMS } from "@app/lib/api-docs";
|
||||||
import { getBase64SizeInBytes, isBase64 } from "@app/lib/base64";
|
import { getBase64SizeInBytes, isBase64 } from "@app/lib/base64";
|
||||||
import { AllowedEncryptionKeyAlgorithms, SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher";
|
import { AllowedEncryptionKeyAlgorithms, SymmetricKeyAlgorithm } from "@app/lib/crypto/cipher";
|
||||||
import { AsymmetricKeyAlgorithm, SigningAlgorithm } from "@app/lib/crypto/sign";
|
import { AsymmetricKeyAlgorithm, SigningAlgorithm } from "@app/lib/crypto/sign";
|
||||||
@ -46,6 +46,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.KmsKeys],
|
||||||
description: "Create KMS key",
|
description: "Create KMS key",
|
||||||
body: z
|
body: z
|
||||||
.object({
|
.object({
|
||||||
@ -138,6 +140,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.KmsKeys],
|
||||||
description: "Update KMS key",
|
description: "Update KMS key",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
keyId: z.string().uuid().describe(KMS.UPDATE_KEY.keyId)
|
keyId: z.string().uuid().describe(KMS.UPDATE_KEY.keyId)
|
||||||
@ -187,6 +191,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.KmsKeys],
|
||||||
description: "Delete KMS key",
|
description: "Delete KMS key",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
keyId: z.string().uuid().describe(KMS.DELETE_KEY.keyId)
|
keyId: z.string().uuid().describe(KMS.DELETE_KEY.keyId)
|
||||||
@ -229,6 +235,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.KmsKeys],
|
||||||
description: "List KMS keys",
|
description: "List KMS keys",
|
||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
projectId: z.string().describe(KMS.LIST_KEYS.projectId),
|
projectId: z.string().describe(KMS.LIST_KEYS.projectId),
|
||||||
@ -280,6 +288,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.KmsKeys],
|
||||||
description: "Get KMS key by ID",
|
description: "Get KMS key by ID",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
keyId: z.string().uuid().describe(KMS.GET_KEY_BY_ID.keyId)
|
keyId: z.string().uuid().describe(KMS.GET_KEY_BY_ID.keyId)
|
||||||
@ -321,6 +331,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.KmsKeys],
|
||||||
description: "Get KMS key by name",
|
description: "Get KMS key by name",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
keyName: slugSchema({ field: "Key name" }).describe(KMS.GET_KEY_BY_NAME.keyName)
|
keyName: slugSchema({ field: "Key name" }).describe(KMS.GET_KEY_BY_NAME.keyName)
|
||||||
@ -367,6 +379,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.KmsEncryption],
|
||||||
description: "Encrypt data with KMS key",
|
description: "Encrypt data with KMS key",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
keyId: z.string().uuid().describe(KMS.ENCRYPT.keyId)
|
keyId: z.string().uuid().describe(KMS.ENCRYPT.keyId)
|
||||||
@ -412,6 +426,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.KmsSigning],
|
||||||
description:
|
description:
|
||||||
"Get the public key for a KMS key that is used for signing and verifying data. This endpoint is only available for asymmetric keys.",
|
"Get the public key for a KMS key that is used for signing and verifying data. This endpoint is only available for asymmetric keys.",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
@ -454,6 +470,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: readLimit
|
rateLimit: readLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.KmsSigning],
|
||||||
description: "List all available signing algorithms for a KMS key",
|
description: "List all available signing algorithms for a KMS key",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
keyId: z.string().uuid().describe(KMS.LIST_SIGNING_ALGORITHMS.keyId)
|
keyId: z.string().uuid().describe(KMS.LIST_SIGNING_ALGORITHMS.keyId)
|
||||||
@ -495,6 +513,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.KmsSigning],
|
||||||
description: "Sign data with a KMS key.",
|
description: "Sign data with a KMS key.",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
keyId: z.string().uuid().describe(KMS.SIGN.keyId)
|
keyId: z.string().uuid().describe(KMS.SIGN.keyId)
|
||||||
@ -548,6 +568,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.KmsSigning],
|
||||||
description: "Verify data signatures with a KMS key.",
|
description: "Verify data signatures with a KMS key.",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
keyId: z.string().uuid().describe(KMS.VERIFY.keyId)
|
keyId: z.string().uuid().describe(KMS.VERIFY.keyId)
|
||||||
@ -604,6 +626,8 @@ export const registerCmekRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.KmsEncryption],
|
||||||
description: "Decrypt data with KMS key",
|
description: "Decrypt data with KMS key",
|
||||||
params: z.object({
|
params: z.object({
|
||||||
keyId: z.string().uuid().describe(KMS.DECRYPT.keyId)
|
keyId: z.string().uuid().describe(KMS.DECRYPT.keyId)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { ForbiddenError } from "@casl/ability";
|
import { ForbiddenError } from "@casl/ability";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { SecretFoldersSchema, SecretImportsSchema } from "@app/db/schemas";
|
import { SecretFoldersSchema, SecretImportsSchema, UsersSchema } from "@app/db/schemas";
|
||||||
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType, UserAgentType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { ProjectPermissionSecretActions } from "@app/ee/services/permission/project-permission";
|
import { ProjectPermissionSecretActions } from "@app/ee/services/permission/project-permission";
|
||||||
import { SecretRotationV2Schema } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-union-schema";
|
import { SecretRotationV2Schema } from "@app/ee/services/secret-rotation-v2/secret-rotation-v2-union-schema";
|
||||||
@ -594,6 +594,12 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
|
|||||||
.optional(),
|
.optional(),
|
||||||
secrets: secretRawSchema
|
secrets: secretRawSchema
|
||||||
.extend({
|
.extend({
|
||||||
|
secretReminderRecipients: z
|
||||||
|
.object({
|
||||||
|
user: UsersSchema.pick({ id: true, email: true, username: true }),
|
||||||
|
id: z.string()
|
||||||
|
})
|
||||||
|
.array(),
|
||||||
secretValueHidden: z.boolean(),
|
secretValueHidden: z.boolean(),
|
||||||
secretPath: z.string().optional(),
|
secretPath: z.string().optional(),
|
||||||
secretMetadata: ResourceMetadataSchema.optional(),
|
secretMetadata: ResourceMetadataSchema.optional(),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { UNIVERSAL_AUTH } from "@app/lib/api-docs";
|
import { ApiDocsTags, UNIVERSAL_AUTH } from "@app/lib/api-docs";
|
||||||
import { writeLimit } from "@app/server/config/rateLimiter";
|
import { writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
|
||||||
export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvider) => {
|
export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvider) => {
|
||||||
@ -11,6 +11,8 @@ export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvid
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.UniversalAuth],
|
||||||
description: "Renew access token",
|
description: "Renew access token",
|
||||||
body: z.object({
|
body: z.object({
|
||||||
accessToken: z.string().trim().describe(UNIVERSAL_AUTH.RENEW_ACCESS_TOKEN.accessToken)
|
accessToken: z.string().trim().describe(UNIVERSAL_AUTH.RENEW_ACCESS_TOKEN.accessToken)
|
||||||
@ -44,6 +46,8 @@ export const registerIdentityAccessTokenRouter = async (server: FastifyZodProvid
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.UniversalAuth],
|
||||||
description: "Revoke access token",
|
description: "Revoke access token",
|
||||||
body: z.object({
|
body: z.object({
|
||||||
accessToken: z.string().trim().describe(UNIVERSAL_AUTH.REVOKE_ACCESS_TOKEN.accessToken)
|
accessToken: z.string().trim().describe(UNIVERSAL_AUTH.REVOKE_ACCESS_TOKEN.accessToken)
|
||||||
|
@ -2,7 +2,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
import { IdentityAwsAuthsSchema } from "@app/db/schemas";
|
import { IdentityAwsAuthsSchema } from "@app/db/schemas";
|
||||||
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
import { EventType } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
import { AWS_AUTH } from "@app/lib/api-docs";
|
import { ApiDocsTags, AWS_AUTH } from "@app/lib/api-docs";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@ -21,6 +21,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
|
|||||||
rateLimit: writeLimit
|
rateLimit: writeLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AwsAuth],
|
||||||
description: "Login with AWS Auth",
|
description: "Login with AWS Auth",
|
||||||
body: z.object({
|
body: z.object({
|
||||||
identityId: z.string().trim().describe(AWS_AUTH.LOGIN.identityId),
|
identityId: z.string().trim().describe(AWS_AUTH.LOGIN.identityId),
|
||||||
@ -71,6 +73,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AwsAuth],
|
||||||
description: "Attach AWS Auth configuration onto identity",
|
description: "Attach AWS Auth configuration onto identity",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -165,6 +169,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AwsAuth],
|
||||||
description: "Update AWS Auth configuration on identity",
|
description: "Update AWS Auth configuration on identity",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -247,6 +253,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AwsAuth],
|
||||||
description: "Retrieve AWS Auth configuration on identity",
|
description: "Retrieve AWS Auth configuration on identity",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
@ -293,6 +301,8 @@ export const registerIdentityAwsAuthRouter = async (server: FastifyZodProvider)
|
|||||||
},
|
},
|
||||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
schema: {
|
schema: {
|
||||||
|
hide: false,
|
||||||
|
tags: [ApiDocsTags.AwsAuth],
|
||||||
description: "Delete AWS Auth configuration on identity",
|
description: "Delete AWS Auth configuration on identity",
|
||||||
security: [
|
security: [
|
||||||
{
|
{
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user