mirror of
https://github.com/Infisical/infisical.git
synced 2025-07-13 09:35:39 +00:00
Compare commits
1392 Commits
daniel/err
...
infisical/
Author | SHA1 | Date | |
---|---|---|---|
9d66659f72 | |||
70c9761abe | |||
c9d7559983 | |||
66251403bf | |||
b9c4407507 | |||
624be80768 | |||
8d7b5968d3 | |||
7154b19703 | |||
9ce465b3e2 | |||
598e5c0be5 | |||
72f08a6b89 | |||
55d8762351 | |||
3c92ec4dc3 | |||
f2224262a4 | |||
23eac40740 | |||
4ae88c0447 | |||
7aecaad050 | |||
cf61390e52 | |||
3f02481e78 | |||
7adc103ed2 | |||
5bdbf37171 | |||
4f874734ab | |||
eb6fd8259b | |||
1766a44dd0 | |||
624c9ef8da | |||
dfd4b13574 | |||
22b57b7a74 | |||
1ba0b9c204 | |||
a903537441 | |||
92c4d83714 | |||
a6414104ad | |||
071f37666e | |||
cd5078d8b7 | |||
110d0e95b0 | |||
a8c0bbb7ca | |||
6af8a4fab8 | |||
407fd8eda7 | |||
9d976de19b | |||
43ecd31b74 | |||
be99e40050 | |||
800d2c0454 | |||
6d0534b165 | |||
ccee0f5428 | |||
14586c7cd0 | |||
7090eea716 | |||
01d3443139 | |||
c4b23a8d4f | |||
90a2a11fff | |||
95d7c2082c | |||
ab5eb4c696 | |||
65aeb81934 | |||
a406511405 | |||
61da0db49e | |||
0968893d4b | |||
59666740ca | |||
9cc7edc869 | |||
e1b016f76d | |||
1175b9b5af | |||
09521144ec | |||
8759944077 | |||
aac3c355e9 | |||
2a28a462a5 | |||
3328e0850f | |||
216cae9b33 | |||
d24a5d96e3 | |||
89d4d4bc92 | |||
cffcb28bc9 | |||
61388753cf | |||
a6145120e6 | |||
dacffbef08 | |||
4db3e5d208 | |||
2a84d61862 | |||
a5945204ad | |||
55b0dc7f81 | |||
ba03fc256b | |||
ea28c374a7 | |||
e99eb47cf4 | |||
cf107c0c0d | |||
9fcb1c2161 | |||
70515a1ca2 | |||
955cf9303a | |||
a24ef46d7d | |||
ee49f714b9 | |||
657aca516f | |||
b5d60398d6 | |||
c3d515bb95 | |||
7f89a7c860 | |||
23cb05c16d | |||
d74b819f57 | |||
457056b600 | |||
7dc9ea4f6a | |||
3b4b520d42 | |||
23f605bda7 | |||
1c3c8dbdce | |||
317c95384e | |||
7dd959e124 | |||
2049e5668f | |||
0a3e99b334 | |||
c4ad0aa163 | |||
5bb0b7a508 | |||
96bcd42753 | |||
2c75e23acf | |||
907dd4880a | |||
6af7c5c371 | |||
72468d5428 | |||
939ee892e0 | |||
c7ec9ff816 | |||
554e268f88 | |||
a8a27c3045 | |||
27af943ee1 | |||
9b772ad55a | |||
94a1fc2809 | |||
10c10642a1 | |||
3e0f04273c | |||
91f2d0384e | |||
811dc8dd75 | |||
4ee9375a8d | |||
92f697e195 | |||
8062f0238b | |||
1181c684db | |||
dda436bcd9 | |||
89124b18d2 | |||
effd88c4bd | |||
27efc908e2 | |||
8e4226038b | |||
27425a1a64 | |||
18cf3c89c1 | |||
49e6d7a861 | |||
c4446389b0 | |||
7c21dec54d | |||
2ea5710896 | |||
f9ac7442df | |||
a534a4975c | |||
79a616dc1c | |||
a93bfa69c9 | |||
598d14fc54 | |||
08a0550cd7 | |||
d7503573b1 | |||
b5a89edeed | |||
860eaae4c8 | |||
c7a4b6c4e9 | |||
c12c6dcc6e | |||
99c9b644df | |||
d0d5556bd0 | |||
753c28a2d3 | |||
8741414cfa | |||
b8d29793ec | |||
92013dbfbc | |||
c5319588fe | |||
9efb8eaf78 | |||
dfc973c7f7 | |||
3013d1977c | |||
f358e8942d | |||
58f51411c0 | |||
c3970d1ea2 | |||
2dc00a638a | |||
94aed485a5 | |||
e382941424 | |||
bab9c1f454 | |||
2bd4770fb4 | |||
31905fab6e | |||
784acf16d0 | |||
114b89c952 | |||
81420198cb | |||
b949708f45 | |||
2a6b6b03b9 | |||
0ff18e277f | |||
e093f70301 | |||
8e2ff18f35 | |||
3fbfecf7a9 | |||
9087def21c | |||
89c6ab591a | |||
235a33a01c | |||
dd6c217dc8 | |||
78b1b5583a | |||
8f2a504fd0 | |||
1d5b629d8f | |||
14f895cae2 | |||
b7be6bd1d9 | |||
58a97852f6 | |||
980aa9eaae | |||
a35d1aa72b | |||
52d801bce5 | |||
c92c160709 | |||
71ca7a82db | |||
6f799b478d | |||
a89e6b6e58 | |||
99ca9e04f8 | |||
586dbd79b0 | |||
6cdc71b9b1 | |||
f88d6a183f | |||
fa82d4953e | |||
12d9fe9ffd | |||
86acf88a13 | |||
63c7c39e21 | |||
151edc7efa | |||
5fa7f56285 | |||
810b27d121 | |||
51fe7450ae | |||
938c06a2ed | |||
38d431ec77 | |||
d202fdf5c8 | |||
f1b2028542 | |||
5c9b46dfba | |||
a516e50984 | |||
3c1fc024c2 | |||
569439f208 | |||
9afc282679 | |||
8db85cfb84 | |||
664b2f0089 | |||
5e9bd3a7c6 | |||
2c13af6db3 | |||
ec9171d0bc | |||
81362bec8f | |||
5a4d7541a2 | |||
3c97c45455 | |||
4f015d77fb | |||
78e894c2bb | |||
23513158ed | |||
934ef8ab27 | |||
23e9c52f67 | |||
e276752e7c | |||
01ae19fa2b | |||
9df8cf60ef | |||
1b1fe2a700 | |||
338961480c | |||
03debcab5a | |||
645dfafba0 | |||
4a6f759900 | |||
b9d06ff686 | |||
5cc5a4f03d | |||
5ef2be1a9c | |||
8de9ddfb8b | |||
5b40de16cf | |||
11aac3f5dc | |||
9823c7d1aa | |||
d627ecf05d | |||
3ba396f7fa | |||
9c561266ed | |||
36fef11d91 | |||
742932c4a0 | |||
57a77ae5f1 | |||
7c9564c7dc | |||
736aecebf8 | |||
16748357d7 | |||
12863b389b | |||
6341b7e989 | |||
c592ff00a6 | |||
ef87086272 | |||
bd459d994c | |||
440f93f392 | |||
bc32d6cbbf | |||
0cf3115830 | |||
65f2e626ae | |||
8b3e3152a4 | |||
661b31f762 | |||
e78ad1147b | |||
473efa91f0 | |||
b440e918ac | |||
439f253350 | |||
4e68304262 | |||
c4d0896609 | |||
b8115d481c | |||
5fdec97319 | |||
755bb1679a | |||
7142e7a6c6 | |||
11ade92b5b | |||
4147725260 | |||
c359cf162f | |||
9d04b648fa | |||
9edfdb7234 | |||
ff74e020fc | |||
6ee446e574 | |||
c806059b11 | |||
3a5bb31bde | |||
6f38d6c76f | |||
d721a46ec9 | |||
989065ba34 | |||
5ad419c079 | |||
80f72e8040 | |||
0cef728617 | |||
0a735422ed | |||
8370a0d9c0 | |||
71af662998 | |||
27e391f7e0 | |||
2187c7588c | |||
8ab7e8360d | |||
957cab3117 | |||
4bf16f68fc | |||
ab3ee775bb | |||
2a86e6f4d1 | |||
194fbb79f2 | |||
faaba8deb7 | |||
ae21b157a9 | |||
6167c70a74 | |||
0ecf75cbdb | |||
3f8aa0fa4b | |||
6487c83bda | |||
c08fbbdab2 | |||
a4aa65bb81 | |||
258d19cbe4 | |||
de91356127 | |||
ccb07942de | |||
3d278b0925 | |||
956fb2efb4 | |||
13894261ce | |||
d7ffa70906 | |||
b8fa7c5bb6 | |||
2baacfcd8f | |||
31c11f7d2a | |||
c5f06dece4 | |||
662e79ac98 | |||
17249d603b | |||
9bdff9c504 | |||
4552ce6ca4 | |||
ba4b8801eb | |||
36a5f728a1 | |||
502429d914 | |||
27abfa4fff | |||
4bc9bca287 | |||
612c29225d | |||
4d43accc8a | |||
3c89a69410 | |||
e741b63e63 | |||
9cde1995c7 | |||
3ed3856c85 | |||
8054d93851 | |||
02dc23425c | |||
01534c3525 | |||
325ce73b9f | |||
1639bda3f6 | |||
b5b91c929f | |||
9bc549ca8c | |||
cedc88d83a | |||
f866a810c1 | |||
0c034d69ac | |||
e29f7f656c | |||
858e569d4d | |||
5d8f32b774 | |||
bb71f5eb7e | |||
30b431a255 | |||
fd32118685 | |||
8528f3fd2a | |||
60749cfc43 | |||
eb358bcafd | |||
ffbd29c575 | |||
a74f0170da | |||
a0fad34a6d | |||
f0dc5ec876 | |||
c2453f0c84 | |||
2819c8519e | |||
616b013b12 | |||
0b9d890a51 | |||
5ba507bc1c | |||
0ecc196e5d | |||
ddac9f7cc4 | |||
f5adc4d9f3 | |||
34354994d8 | |||
d7c3192099 | |||
1576358805 | |||
e6103d2d3f | |||
8bf8bc77c9 | |||
3219723149 | |||
74b95d92ab | |||
6d3793beff | |||
0df41f3391 | |||
1acac9d479 | |||
0cefd6f837 | |||
5e9dc0b98d | |||
f632847dc6 | |||
faa6d1cf40 | |||
7fb18870e3 | |||
ae841715e5 | |||
baac87c16a | |||
291d29ec41 | |||
b726187ba3 | |||
d98ff32b07 | |||
1fa510b32f | |||
c57f0d8120 | |||
00490f2cff | |||
ee58f538c0 | |||
0fa20f7839 | |||
40ef75d3bd | |||
26af13453c | |||
ad1f71883d | |||
aa39451bc2 | |||
f5548b3e8c | |||
2659ea7170 | |||
d2e3f504fd | |||
ca4151a34d | |||
d4bc104fd1 | |||
7e3a3fcdb0 | |||
7f67912d2f | |||
a7f4020c08 | |||
d2d89034ba | |||
2fc6c564c0 | |||
240b86c1d5 | |||
30d66cef89 | |||
b7d11444a9 | |||
0a6aef0afa | |||
0ac7ec460b | |||
808a901aee | |||
d5412f916f | |||
d0648ca596 | |||
3291f1f908 | |||
965d30bd03 | |||
68fe7c589a | |||
54377a44d3 | |||
8c902d7699 | |||
c25c84aeb3 | |||
4359eb7313 | |||
322536d738 | |||
6c5db3a187 | |||
a337e6badd | |||
524a97e9a6 | |||
c56f598115 | |||
19d32a1a3b | |||
7e5417a0eb | |||
afd6de27fe | |||
7781a6b7e7 | |||
b3b4e41d92 | |||
5225f5136a | |||
398adfaf76 | |||
d77c26fa38 | |||
ef7b81734a | |||
09b489a348 | |||
6b5c50def0 | |||
1f2d52176c | |||
7002e297c8 | |||
71864a131f | |||
9964d2ecaa | |||
3ebbaefc2a | |||
dd5c494bdb | |||
bace8af5a1 | |||
f56196b820 | |||
7042d73410 | |||
cb22ee315e | |||
701eb7cfc6 | |||
bf8df14b01 | |||
1ba8b6394b | |||
c442c8483a | |||
0435305a68 | |||
febf11f502 | |||
64fd15c32d | |||
a2c9494d52 | |||
18460e0678 | |||
3d03fece74 | |||
234e7eb9be | |||
04af313bf0 | |||
9b038ccc45 | |||
9beb384546 | |||
12ec9b4b4e | |||
96b8e7fda8 | |||
93b9108aa3 | |||
99017ea1ae | |||
f32588112e | |||
f9b0b6700a | |||
b45d9398f0 | |||
1d1140237f | |||
937560fd8d | |||
5f4b7b9ea7 | |||
05139820a5 | |||
7f6bc3ecfe | |||
d8cc000ad1 | |||
8fc03c06d9 | |||
50ceedf39f | |||
550096e72b | |||
1190ca2d77 | |||
2fb60201bc | |||
e763a6f683 | |||
cb1b006118 | |||
356e7c5958 | |||
634b500244 | |||
54b4d4ae55 | |||
1a68765f15 | |||
2f6dab3f63 | |||
ae07d38c19 | |||
e9564f5231 | |||
05cdca9202 | |||
5ab0c66dee | |||
f5a0641671 | |||
2843818395 | |||
2357f3bc1f | |||
cde813aafb | |||
bbc8091d44 | |||
ce5e591457 | |||
5ae74f9761 | |||
eef331bbd1 | |||
d5c2e9236a | |||
025b4b8761 | |||
13eef7e524 | |||
ef688efc8d | |||
8c98565715 | |||
f97f98b2c3 | |||
e9358cd1d8 | |||
3fa84c578c | |||
c22ed04733 | |||
64fac1979f | |||
2d60f389c2 | |||
7798e5a2ad | |||
ed78227725 | |||
89848a2f5c | |||
1936f7cc4f | |||
1adeb5a70d | |||
058475fc3f | |||
ee4eb7f84b | |||
8122433f5c | |||
a0411e3ba8 | |||
62968c5e43 | |||
f3cf1a3f50 | |||
b4b417658f | |||
fed99a14a8 | |||
d4cfee99a6 | |||
e70ca57510 | |||
06f321e4bf | |||
3c3fcd0db8 | |||
21eb2bed7e | |||
31a21a432d | |||
381960b0bd | |||
7eb05afe2a | |||
0b54948b15 | |||
39e598e408 | |||
b735618601 | |||
3a5e862def | |||
d1c4a9c75a | |||
5532844ee7 | |||
dd5aab973f | |||
ced12baf5d | |||
7db1e62654 | |||
0ab3ae442e | |||
ed9472efc8 | |||
e094844601 | |||
e761b49964 | |||
6a8be75b79 | |||
4daaf80caa | |||
cf7768d8e5 | |||
e76d2f58ea | |||
a92e61575d | |||
761007208d | |||
cc3e0d1922 | |||
765280eef6 | |||
215761ca6b | |||
0977ff1e36 | |||
c6081900a4 | |||
86800c0cdb | |||
1fa99e5585 | |||
7947e73569 | |||
8f5bb44ff4 | |||
3f70f08e8c | |||
078eaff164 | |||
221aa99374 | |||
6a681dcf6a | |||
b99b98b6a4 | |||
d7271b9631 | |||
379e526200 | |||
1f151a9b05 | |||
6b2eb9c6c9 | |||
52ce90846a | |||
be36827392 | |||
68a3291235 | |||
471f47d260 | |||
ccb757ec3e | |||
b669b0a9f8 | |||
9e768640cd | |||
35f7420447 | |||
c6a0e36318 | |||
181ba75f2a | |||
c00f6601bd | |||
111605a945 | |||
2ac110f00e | |||
0366506213 | |||
e3d29b637d | |||
9cd0dc8970 | |||
f8f5000bad | |||
40919ccf59 | |||
44303aca6a | |||
4bd50c3548 | |||
fb253d00eb | |||
097512c691 | |||
64a982d5e0 | |||
1080438ad8 | |||
eb3acae332 | |||
a0b3520899 | |||
2f6f359ddf | |||
df8c1e54e0 | |||
cac060deff | |||
47269bc95b | |||
8502e9a1d8 | |||
d89eb4fa84 | |||
ca7ab4eaf1 | |||
c57fc5e3f1 | |||
9b4e1f561e | |||
097fcad5ae | |||
d1547564f9 | |||
24acb98978 | |||
0fd8274ff0 | |||
a857375cc1 | |||
69bf9dc20f | |||
5151c91760 | |||
f12d8b6f89 | |||
695c499448 | |||
1cbf030e6c | |||
dc715cc238 | |||
d873f2e50f | |||
16ea757928 | |||
8713643bc1 | |||
c35657ed49 | |||
5b4487fae8 | |||
474731d8ef | |||
e9f254f81b | |||
639057415f | |||
c38dae2319 | |||
25191cff38 | |||
a6898717f4 | |||
36a13d182f | |||
cc77175188 | |||
fcb944d964 | |||
a8ad8707ac | |||
4568370552 | |||
c000a6f707 | |||
1ace8eebf8 | |||
8b26670d73 | |||
35d3581e23 | |||
3b3482b280 | |||
422fd27b9a | |||
a7b25f3bd8 | |||
7896b4e85e | |||
ba5e6fe28a | |||
8d79fa3529 | |||
1a55909b73 | |||
b2efb2845a | |||
c680030f01 | |||
cf1070c65e | |||
3a8219db03 | |||
f5920f416a | |||
3b2154bab4 | |||
7c8f2e5548 | |||
9d9f6ec268 | |||
c5816014a6 | |||
a730b16318 | |||
cc3d132f5d | |||
56aab172d3 | |||
c8ee06341a | |||
e32716c258 | |||
7f0d27e3dc | |||
48174e2500 | |||
7cf297344b | |||
5d9b99bee7 | |||
8fdc438940 | |||
0edf0dac98 | |||
d2b909b72b | |||
68988a3e78 | |||
3c954ea257 | |||
a92de1273e | |||
97f85fa8d9 | |||
84c26581a6 | |||
a808b6d4a0 | |||
826916399b | |||
7d5aba258a | |||
40d69d4620 | |||
42249726d4 | |||
3f6b1fe3bd | |||
a757ea22a1 | |||
74df374998 | |||
925a594a1b | |||
36af975594 | |||
c648235390 | |||
ee54d460a0 | |||
3c32d8dd90 | |||
9b50d451ec | |||
7ede4e2cf5 | |||
4552f0efa4 | |||
0d35273857 | |||
5ad8dab250 | |||
92a80b3314 | |||
3c588beebe | |||
01dcbb0122 | |||
adb0819102 | |||
41ba111a69 | |||
1b48ce21be | |||
2f922d6343 | |||
e67b0540dd | |||
a78455fde6 | |||
967dac9be6 | |||
922b245780 | |||
6614721d34 | |||
bbd8a049fb | |||
a91f64f742 | |||
1bc508b286 | |||
ec1ce3dc06 | |||
82a4b89bb5 | |||
ff3d8c896b | |||
6e720c2f64 | |||
d3d30eba80 | |||
623a99be0e | |||
f80023f8f3 | |||
98289f56ae | |||
c40f195c1d | |||
fbfe694fc0 | |||
2098bd3be2 | |||
39f71f9488 | |||
ef82c664a6 | |||
fcbedfaf1b | |||
882f6b22f5 | |||
bcd778457d | |||
0a1242db75 | |||
a078cb6059 | |||
095b26c8c9 | |||
fcdfcd0219 | |||
5b618b07fa | |||
a5a1f57284 | |||
132de1479d | |||
d4a76b3621 | |||
331dcd4d79 | |||
025f64f068 | |||
05d7f94518 | |||
b58e32c754 | |||
4ace30aecd | |||
8b2a866994 | |||
b4386af2e0 | |||
2b44e32ac1 | |||
ec5e6eb7b4 | |||
48cb5f6e9b | |||
3c63312944 | |||
0842901d4f | |||
32d6826ade | |||
a750f48922 | |||
67662686f3 | |||
11c96245a7 | |||
a63191e11d | |||
7a13c155f5 | |||
8327f6154e | |||
20a9fc113c | |||
8edfa9ad0b | |||
00ce755996 | |||
3b2173a098 | |||
07d9398aad | |||
fb6a085bf9 | |||
6c533f89d3 | |||
5ceb30f43f | |||
7728a4793b | |||
d3523ed1d6 | |||
35a9b2a38d | |||
4fc8c509ac | |||
16a9f8c194 | |||
9557639bfe | |||
1049f95952 | |||
e618d5ca5f | |||
d659250ce8 | |||
87363eabfe | |||
d1b9c316d8 | |||
b9867c0d06 | |||
afa2f383c5 | |||
39f7354fec | |||
c46c0cb1e8 | |||
6905ffba4e | |||
64fd423c61 | |||
da1a7466d1 | |||
d3f3f34129 | |||
c8fba7ce4c | |||
82c3e943eb | |||
dc3903ff15 | |||
a9c01dcf1f | |||
ae51fbb8f2 | |||
62910e93ca | |||
586b9d9a56 | |||
9e3c632a1f | |||
bb094f60c1 | |||
6d709fba62 | |||
27beca7099 | |||
28e7e4c52d | |||
cfc0ca1f03 | |||
b96593d0ab | |||
2de5896ba4 | |||
3455ad3898 | |||
c7a32a3b05 | |||
1ebfed8c11 | |||
a18f3c2919 | |||
16d215b588 | |||
a852b15a1e | |||
cacd9041b0 | |||
cfeffebd46 | |||
1dceedcdb4 | |||
14f03c38c3 | |||
be9f096e75 | |||
49133a044f | |||
b7fe3743db | |||
c5fded361c | |||
e676acbadf | |||
9b31a7bbb1 | |||
345be85825 | |||
f82b11851a | |||
b466b3073b | |||
46105fc315 | |||
3cf8fd2ff8 | |||
5277a50b3e | |||
dab8f0b261 | |||
4293665130 | |||
8afa65c272 | |||
4c739fd57f | |||
bcc2840020 | |||
8b3af92d23 | |||
9ca58894f0 | |||
d131314de0 | |||
9c03144f19 | |||
5495ffd78e | |||
a200469c72 | |||
85c3074216 | |||
cfc55ff283 | |||
7179b7a540 | |||
6c4cb5e084 | |||
9cfb044178 | |||
105eb70fd9 | |||
18a2547b24 | |||
588b3c77f9 | |||
a04834c7c9 | |||
9df9f4a5da | |||
afdc704423 | |||
57261cf0c8 | |||
06f6004993 | |||
f3bfb9cc5a | |||
48fb77be49 | |||
c3956c60e9 | |||
f55bcb93ba | |||
d3fb2a6a74 | |||
6a23b74481 | |||
602cf4b3c4 | |||
84ff71fef2 | |||
4c01bddf0e | |||
add5742b8c | |||
68f3964206 | |||
90374971ae | |||
3a1eadba8c | |||
5305017ce2 | |||
cf5f49d14e | |||
4f4b5be8ea | |||
ecea79f040 | |||
586b901318 | |||
ad8d247cdc | |||
3b47d7698b | |||
aa9a86df71 | |||
33411335ed | |||
ca55f19926 | |||
3794521c56 | |||
728f023263 | |||
229706f57f | |||
6cf2488326 | |||
2c402fbbb6 | |||
92ce05283b | |||
39d92ce6ff | |||
44a026446e | |||
bbf52c9a48 | |||
539e5b1907 | |||
44b02d5324 | |||
71fb6f1d11 | |||
e64100fab1 | |||
e4b149a849 | |||
5bcf07b32b | |||
3b0c48052b | |||
df50e3b0f9 | |||
bdf2ae40b6 | |||
b6c05a2f25 | |||
960efb9cf9 | |||
aa8d58abad | |||
cfb0cc4fea | |||
7712df296c | |||
7c38932121 | |||
69ad9845e1 | |||
7321c237d7 | |||
32430a6a16 | |||
3d6ea3251e | |||
f034adba76 | |||
463eb0014e | |||
be39e63832 | |||
21403f6fe5 | |||
2f9e542b31 | |||
089d6812fd | |||
464a3ccd53 | |||
71c9c0fa1e | |||
242595fceb | |||
46ad1d47a9 | |||
2b977eeb33 | |||
a692148597 | |||
b762816e66 | |||
cf275979ba | |||
64bfa4f334 | |||
e3eb14bfd9 | |||
24b50651c9 | |||
1cd459fda7 | |||
38917327d9 | |||
63fac39fff | |||
7c62a776fb | |||
d7b494c6f8 | |||
93208afb36 | |||
1a084d8fcf | |||
269f851cbf | |||
7a61995dd4 | |||
dd4f133c6c | |||
c41d27e1ae | |||
1866ed8d23 | |||
7b3b232dde | |||
9d618b4ae9 | |||
5330ab2171 | |||
662e588c22 | |||
90057d80ff | |||
1eda7aaaac | |||
00dcadbc08 | |||
7a7289ebd0 | |||
e5d4677fd6 | |||
bce3f3d676 | |||
300372fa98 | |||
47a4f8bae9 | |||
863719f296 | |||
7317dc1cf5 | |||
75df898e78 | |||
0de6add3f7 | |||
0c008b6393 | |||
0c3894496c | |||
35fbd5d49d | |||
d03b453e3d | |||
96e331b678 | |||
d4d468660d | |||
75a4965928 | |||
660c09ded4 | |||
b5287d91c0 | |||
6a17763237 | |||
f2bd3daea2 | |||
7f70f96936 | |||
73e0a54518 | |||
0d295a2824 | |||
9a62efea4f | |||
506c30bcdb | |||
735ad4ff65 | |||
41e36dfcef | |||
421d8578b7 | |||
6685f8aa0a | |||
d6c37c1065 | |||
54f3f94185 | |||
907537f7c0 | |||
61263b9384 | |||
d71c85e052 | |||
b6d8be2105 | |||
0693f81d0a | |||
61d516ef35 | |||
31fc64fb4c | |||
8bf7e4c4d1 | |||
2027d4b44e | |||
d401c9074e | |||
afe35dbbb5 | |||
6ff1602fd5 | |||
6603364749 | |||
53bea22b85 | |||
7c84adc1c2 | |||
fa8d6735a1 | |||
a6137f267d | |||
d521ee7b7e | |||
827931e416 | |||
faa83344a7 | |||
3be3d807d2 | |||
9f7ea3c4e5 | |||
e67218f170 | |||
269c40c67c | |||
089a7e880b | |||
64ec741f1a | |||
c98233ddaf | |||
ae17981c41 | |||
6c49c7da3c | |||
2de04b6fe5 | |||
5c9ec1e4be | |||
ba89491d4c | |||
483e596a7a | |||
65f122bd41 | |||
682b552fdc | |||
d4cfd0b6ed | |||
ba1fd8a3f7 | |||
e8f09d2c7b | |||
774371a218 | |||
c4b54de303 | |||
433971a72d | |||
ed7fc0e5cd | |||
1ae6213387 | |||
4acf9413f0 | |||
f0549cab98 | |||
d75e49dce5 | |||
8819abd710 | |||
796f76da46 | |||
d6e1ed4d1e | |||
1295b68d80 | |||
c79f84c064 | |||
d0c50960ef | |||
85089a08e1 | |||
bf97294dad | |||
4053078d95 | |||
4ba3899861 | |||
6bae3628c0 | |||
4cb935dae7 | |||
ccad684ab2 | |||
fd77708cad | |||
9aebd712d1 | |||
05f07b25ac | |||
5b0dbf04b2 | |||
b050db84ab | |||
8fef6911f1 | |||
44ba31a743 | |||
6bdbac4750 | |||
60fb195706 | |||
c8109b4e84 | |||
1f2b0443cc | |||
dd1cabf9f6 | |||
8b781b925a | |||
ddcf5b576b | |||
7138b392f2 | |||
bfce1021fb | |||
93c0313b28 | |||
8cfc217519 | |||
d272c6217a | |||
2fe2ddd9fc | |||
e330ddd5ee | |||
7aba9c1a50 | |||
4cd8e0fa67 | |||
ea3d164ead | |||
df468e4865 | |||
66e96018c4 | |||
3b02eedca6 | |||
a55fe2b788 | |||
5d7a267f1d | |||
b16ab6f763 | |||
2d2ad0724f | |||
e90efb7fc8 | |||
17d5e4bdab | |||
f22a5580a6 | |||
334a728259 | |||
4a3143e689 | |||
14810de054 | |||
8cfcbaa12c | |||
0e946f73bd | |||
7b8551f883 | |||
3b1ce86ee6 | |||
c649661133 | |||
70e44d04ef | |||
0dddd58be1 | |||
148f522c58 | |||
d4c911a28f | |||
603fcd8ab5 | |||
a1474145ae | |||
7c055f71f7 | |||
14884cd6b0 | |||
98fd146e85 | |||
1d3dca11e7 | |||
22f8a3daa7 | |||
395b3d9e05 | |||
1041e136fb | |||
21024b0d72 | |||
00e68dc0bf | |||
5e068cd8a0 | |||
abdf8f46a3 | |||
1cf046f6b3 | |||
0fda6d6f4d | |||
8d4115925c | |||
d0b3c6b66a | |||
a1685af119 | |||
8d4a06e9e4 | |||
6dbe3c8793 | |||
a3ec1a27de | |||
472f02e8b1 | |||
3989646b80 | |||
472f5eb8b4 | |||
f5b039f939 | |||
b7b3d07e9f | |||
891a1ea2b9 | |||
a807f0cf6c | |||
cfc0b2fb8d | |||
f096a567de | |||
65d642113d | |||
92e7e90c21 | |||
f9f6ec0a8d | |||
d9621b0b17 | |||
d80a70731d | |||
ada63b9e7d | |||
bd99b4e356 | |||
7db0bd7daa | |||
8bc538af93 | |||
8ef078872e | |||
d5f718c6ad | |||
5f93016d22 | |||
f220246eb4 | |||
829b399cda | |||
3f6a0c77f1 | |||
f91f9c9487 | |||
f0d19e4701 | |||
9e4b66e215 | |||
7eeff6c406 | |||
132c3080bb | |||
8a14914bc3 | |||
bf09fa33fa | |||
a87e7b792c | |||
e8ca020903 | |||
a603938488 | |||
cff7981fe0 | |||
b39d5c6682 | |||
829ae7d3c0 | |||
19c26c680c | |||
dd1f1d07cc | |||
027b200b1a | |||
c3f8c55672 | |||
75aeef3897 | |||
e761e65322 | |||
c97fe77aec | |||
370ed45abb | |||
3e16d7e160 | |||
6bf4b4a380 | |||
61f786e8d8 | |||
26064e3a08 | |||
9b246166a1 | |||
9dedaa6779 | |||
8eab7d2f01 | |||
4e796e7e41 | |||
c6fa647825 | |||
496cebb08f | |||
33db6df7f2 | |||
88d25e97e9 | |||
4ad9fa1ad1 | |||
1642fb42d8 | |||
3983c2bc4a | |||
34d87ca30f | |||
12b6f27151 | |||
ea426e8b2d | |||
4d567f0b08 | |||
6548372e3b | |||
77af640c4c | |||
90f85152bc | |||
cfa8770bdc | |||
be8562824d | |||
6956d14e2e | |||
4f1fe8a9fa | |||
b0031b71e0 | |||
bae7c6c3d7 | |||
7503876ca0 | |||
36b5a3dc90 | |||
dfe36f346f | |||
b1b61842c6 | |||
f9ca9b51b2 | |||
e8b33f27fc | |||
7e7e6ade5c | |||
4010817916 | |||
eea367c3bc | |||
860ebb73a9 | |||
56567ee7c9 | |||
1cd17a451c | |||
6b7bc2a3c4 | |||
cb52568ebd | |||
9d30fb3870 | |||
161ac5e097 | |||
bb5b585cf6 | |||
fa94191c40 | |||
6a5eabc411 | |||
c956a0f91f | |||
df7b55606e | |||
5f14b27f41 | |||
02b2395276 | |||
402fa2b0e0 | |||
3725241f52 | |||
10b457a695 | |||
3912e2082d | |||
7dd6eac20a | |||
5664e1ff26 | |||
a27a428329 | |||
b196251c19 | |||
b18d8d542f | |||
3c287600ab | |||
759d11ff21 | |||
2bd817765c | |||
7aa9c5dd00 | |||
b693c035ce | |||
c65a991943 | |||
3a3811cb3c | |||
332ca61f5d | |||
64f43e59d0 | |||
ccaf4c00af | |||
e3ba1c59bf | |||
ce0bc191d8 | |||
489ccb8e15 | |||
ae8f695b6f | |||
19357d4bd7 | |||
776d0a0fe1 | |||
85dec28667 | |||
21ea7dd317 | |||
57e214ef50 | |||
1986fe9617 | |||
1309f30af9 | |||
89a4fc91ca | |||
af0ec2400d | |||
770e73e40b | |||
39fdeabdea | |||
25c26f2cde | |||
1ca8b9ba08 | |||
14d9fe01e0 | |||
216810f289 | |||
f530b78eb8 | |||
c3809ed22b | |||
9f85d8bba1 | |||
1056645ee3 | |||
5e9914b738 | |||
1ea52e6a80 | |||
20da697de8 | |||
16abf48081 | |||
e73ae485bc | |||
621f73e223 | |||
93e69bd34e | |||
e382135384 | |||
f2a554b5fd | |||
df5bdf3773 | |||
8401048daf | |||
335a87d856 | |||
1add9dd965 | |||
df46daf93d | |||
f82f7ae8d0 | |||
8536a1c987 | |||
b3cf43b46d | |||
9d4dbb63ae | |||
9c6f23fba6 | |||
babe483ca9 | |||
38ede687cd | |||
5f465c4832 | |||
a0618086b0 | |||
9a9bb4ca43 | |||
b68ddfae1b | |||
7646670378 | |||
d18be0f74c | |||
ec96db3503 | |||
7245aaa9ec | |||
d32f69e052 | |||
726477e3d7 | |||
a4ca996a1b | |||
303312fe91 | |||
f3f2879d6d | |||
d0f3d96b3e | |||
70d2a21fbc | |||
418ae42d94 | |||
273c6b3842 | |||
6be8d5d2a7 | |||
9eb7640755 | |||
741138c4bd | |||
bed620aad0 | |||
2ddf75d2e6 | |||
02d9dbb987 | |||
0ed333c2b2 | |||
55db45cd36 | |||
2d82273158 | |||
b3e61f579d | |||
d0bcbe15c6 | |||
657130eb80 | |||
3841394eb7 | |||
b1ba770a71 | |||
3552119c7d | |||
7a46725523 | |||
0515c994c7 | |||
e0d0e22e39 | |||
2f79ae42ab | |||
3bc39c6cec | |||
b5b1e57fe7 | |||
1a5f66fe46 | |||
a01f235808 | |||
b9a1629db0 | |||
203422c131 | |||
35826c288e | |||
fae4e1fa55 | |||
8094ef607a | |||
104bff0586 | |||
0fb5fa0c8b | |||
f407022e16 | |||
34d6525418 | |||
911479baff | |||
05bdbbf59d | |||
c8e47771d4 | |||
e0cbcb0318 | |||
f8d65f44e3 | |||
58ce623a2c | |||
7ae28596ec | |||
833398ef39 | |||
4e6ebcc8d9 | |||
ce8689f568 | |||
e9ab19b7f9 | |||
f2b852a09e | |||
a1c2bc695c | |||
00573ebfda | |||
3b2b8ca013 | |||
2afc6b133e | |||
b6a1ab2376 | |||
d03f890471 | |||
5ef81cd935 | |||
3e8f1d8de7 | |||
558a809b4c | |||
a749e70815 | |||
6f44f3ae21 | |||
b062ca3075 | |||
a1397f0a66 | |||
91c11d61f1 | |||
93218d5a3f | |||
5f2144eca5 | |||
45b9de63f0 | |||
114966ded4 | |||
71081d8e9a | |||
dad3d50f3e | |||
e5ca5d3da2 | |||
301cd54dc3 | |||
ac0cb6d96f | |||
593bda8bc6 | |||
4db79edf19 | |||
e3a356cda9 | |||
521b24debf | |||
f71f894de8 | |||
66d2cc8947 | |||
e034aa381a | |||
d6ffd4fa5f | |||
ca3b64bf6c | |||
b7e48fd556 | |||
c01ea048ce | |||
7e7d9a2bd5 | |||
782e3a8985 | |||
1c32dd5d8a | |||
8497ac831f | |||
e5821122d5 | |||
c183ef2b4f | |||
340693cfcd | |||
014b9585e0 | |||
67373b0883 | |||
2101040a77 | |||
2e2fea304b | |||
571709370d | |||
e1dbe769a8 | |||
e7e0d84c8e | |||
4c2ed1cc8b | |||
067b0f4232 | |||
6ed786e6d0 | |||
d187cc3d4d | |||
614e4934a2 | |||
14e92f895a | |||
0a38374a73 | |||
ec3b94a335 | |||
ca0241bb51 | |||
7403385e7c | |||
b6955d0e9b | |||
f4ba441ec3 | |||
2cd1141a65 | |||
256627b2cc | |||
fd7e196f8b | |||
212748f140 | |||
b61582a60e | |||
9ca8da152b | |||
c5aa1b8664 | |||
90dbb417ac | |||
7fb3076238 | |||
946651496f | |||
5a8ac850b5 | |||
77a88f1575 | |||
be00d13a46 | |||
84814a0012 | |||
a0865cda2e | |||
de03692469 | |||
fb2d3e4eb7 | |||
29150e809d | |||
e18a606b23 | |||
67708411cd | |||
1e7b1ccf22 | |||
3e4bd28916 | |||
a2e16370fa | |||
d677654311 | |||
903fac1005 | |||
ff045214d6 | |||
57dcf5ab28 | |||
959a5ec55b | |||
b22a93a175 | |||
5debeb421d | |||
25b30e441a | |||
0f314c45b4 | |||
d7d88f3356 | |||
dbaef9d227 | |||
8eb668cd72 | |||
bb079b3e46 | |||
d94b4b2a3c | |||
9d90c35629 | |||
7a77dc7343 | |||
bd1ed2614e | |||
9192c5caa2 | |||
8da2213bf1 | |||
9f6d837a9b | |||
fc3a409164 | |||
ffc58b0313 | |||
9a7e05369c | |||
33b49f4466 | |||
60895537a7 |
33
.env.example
33
.env.example
@ -26,7 +26,8 @@ SITE_URL=http://localhost:8080
|
|||||||
# Mail/SMTP
|
# Mail/SMTP
|
||||||
SMTP_HOST=
|
SMTP_HOST=
|
||||||
SMTP_PORT=
|
SMTP_PORT=
|
||||||
SMTP_NAME=
|
SMTP_FROM_ADDRESS=
|
||||||
|
SMTP_FROM_NAME=
|
||||||
SMTP_USERNAME=
|
SMTP_USERNAME=
|
||||||
SMTP_PASSWORD=
|
SMTP_PASSWORD=
|
||||||
|
|
||||||
@ -74,7 +75,37 @@ CAPTCHA_SECRET=
|
|||||||
|
|
||||||
NEXT_PUBLIC_CAPTCHA_SITE_KEY=
|
NEXT_PUBLIC_CAPTCHA_SITE_KEY=
|
||||||
|
|
||||||
|
OTEL_TELEMETRY_COLLECTION_ENABLED=false
|
||||||
|
OTEL_EXPORT_TYPE=prometheus
|
||||||
|
OTEL_EXPORT_OTLP_ENDPOINT=
|
||||||
|
OTEL_OTLP_PUSH_INTERVAL=
|
||||||
|
|
||||||
|
OTEL_COLLECTOR_BASIC_AUTH_USERNAME=
|
||||||
|
OTEL_COLLECTOR_BASIC_AUTH_PASSWORD=
|
||||||
|
|
||||||
PLAIN_API_KEY=
|
PLAIN_API_KEY=
|
||||||
PLAIN_WISH_LABEL_IDS=
|
PLAIN_WISH_LABEL_IDS=
|
||||||
|
|
||||||
SSL_CLIENT_CERTIFICATE_HEADER_KEY=
|
SSL_CLIENT_CERTIFICATE_HEADER_KEY=
|
||||||
|
|
||||||
|
ENABLE_MSSQL_SECRET_ROTATION_ENCRYPT=true
|
||||||
|
|
||||||
|
# App Connections
|
||||||
|
|
||||||
|
# aws assume-role
|
||||||
|
INF_APP_CONNECTION_AWS_ACCESS_KEY_ID=
|
||||||
|
INF_APP_CONNECTION_AWS_SECRET_ACCESS_KEY=
|
||||||
|
|
||||||
|
# github oauth
|
||||||
|
INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_ID=
|
||||||
|
INF_APP_CONNECTION_GITHUB_OAUTH_CLIENT_SECRET=
|
||||||
|
|
||||||
|
#github app
|
||||||
|
INF_APP_CONNECTION_GITHUB_APP_CLIENT_ID=
|
||||||
|
INF_APP_CONNECTION_GITHUB_APP_CLIENT_SECRET=
|
||||||
|
INF_APP_CONNECTION_GITHUB_APP_PRIVATE_KEY=
|
||||||
|
INF_APP_CONNECTION_GITHUB_APP_SLUG=
|
||||||
|
INF_APP_CONNECTION_GITHUB_APP_ID=
|
||||||
|
|
||||||
|
#gcp app
|
||||||
|
INF_APP_CONNECTION_GCP_SERVICE_ACCOUNT_CREDENTIAL=
|
||||||
|
8
.github/workflows/check-fe-ts-and-lint.yml
vendored
8
.github/workflows/check-fe-ts-and-lint.yml
vendored
@ -18,18 +18,18 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: ☁️ Checkout source
|
- name: ☁️ Checkout source
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: 🔧 Setup Node 16
|
- name: 🔧 Setup Node 20
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: "16"
|
node-version: "20"
|
||||||
cache: "npm"
|
cache: "npm"
|
||||||
cache-dependency-path: frontend/package-lock.json
|
cache-dependency-path: frontend/package-lock.json
|
||||||
- name: 📦 Install dependencies
|
- name: 📦 Install dependencies
|
||||||
run: npm install
|
run: npm install
|
||||||
working-directory: frontend
|
working-directory: frontend
|
||||||
- name: 🏗️ Run Type check
|
- name: 🏗️ Run Type check
|
||||||
run: npm run type:check
|
run: npm run type:check
|
||||||
working-directory: frontend
|
working-directory: frontend
|
||||||
- name: 🏗️ Run Link check
|
- name: 🏗️ Run Link check
|
||||||
run: npm run lint:fix
|
run: npm run lint:fix
|
||||||
working-directory: frontend
|
working-directory: frontend
|
||||||
|
@ -5,14 +5,18 @@ permissions:
|
|||||||
id-token: write
|
id-token: write
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: "infisical-core-deployment"
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
infisical-tests:
|
infisical-tests:
|
||||||
name: Run tests before deployment
|
name: Integration tests
|
||||||
# https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview
|
# https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview
|
||||||
uses: ./.github/workflows/run-backend-tests.yml
|
uses: ./.github/workflows/run-backend-tests.yml
|
||||||
|
|
||||||
infisical-image:
|
infisical-image:
|
||||||
name: Build backend image
|
name: Build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [infisical-tests]
|
needs: [infisical-tests]
|
||||||
steps:
|
steps:
|
||||||
@ -97,15 +101,15 @@ jobs:
|
|||||||
image: infisical/staging_infisical:${{ steps.commit.outputs.short }}
|
image: infisical/staging_infisical:${{ steps.commit.outputs.short }}
|
||||||
environment-variables: "LOG_LEVEL=info"
|
environment-variables: "LOG_LEVEL=info"
|
||||||
- name: Deploy to Amazon ECS service
|
- name: Deploy to Amazon ECS service
|
||||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
|
||||||
with:
|
with:
|
||||||
task-definition: ${{ steps.render-web-container.outputs.task-definition }}
|
task-definition: ${{ steps.render-web-container.outputs.task-definition }}
|
||||||
service: infisical-core-gamma-stage
|
service: infisical-core-gamma-stage
|
||||||
cluster: infisical-gamma-stage
|
cluster: infisical-gamma-stage
|
||||||
wait-for-service-stability: true
|
wait-for-service-stability: true
|
||||||
|
|
||||||
production-postgres-deployment:
|
production-us:
|
||||||
name: Deploy to production
|
name: US production deploy
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [gamma-deployment]
|
needs: [gamma-deployment]
|
||||||
environment:
|
environment:
|
||||||
@ -113,10 +117,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: twingate/github-action@v1
|
- uses: twingate/github-action@v1
|
||||||
with:
|
with:
|
||||||
# The Twingate Service Key used to connect Twingate to the proper service
|
|
||||||
# Learn more about [Twingate Services](https://docs.twingate.com/docs/services)
|
|
||||||
#
|
|
||||||
# Required
|
|
||||||
service-key: ${{ secrets.TWINGATE_SERVICE_KEY }}
|
service-key: ${{ secrets.TWINGATE_SERVICE_KEY }}
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
@ -153,9 +153,110 @@ jobs:
|
|||||||
image: infisical/staging_infisical:${{ steps.commit.outputs.short }}
|
image: infisical/staging_infisical:${{ steps.commit.outputs.short }}
|
||||||
environment-variables: "LOG_LEVEL=info"
|
environment-variables: "LOG_LEVEL=info"
|
||||||
- name: Deploy to Amazon ECS service
|
- name: Deploy to Amazon ECS service
|
||||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
|
||||||
with:
|
with:
|
||||||
task-definition: ${{ steps.render-web-container.outputs.task-definition }}
|
task-definition: ${{ steps.render-web-container.outputs.task-definition }}
|
||||||
service: infisical-core-platform
|
service: infisical-core-platform
|
||||||
cluster: infisical-core-platform
|
cluster: infisical-core-platform
|
||||||
wait-for-service-stability: true
|
wait-for-service-stability: true
|
||||||
|
- name: Post slack message
|
||||||
|
uses: slackapi/slack-github-action@v2.0.0
|
||||||
|
with:
|
||||||
|
webhook: ${{ secrets.SLACK_DEPLOYMENT_WEBHOOK_URL }}
|
||||||
|
webhook-type: incoming-webhook
|
||||||
|
payload: |
|
||||||
|
text: "*Deployment Status Update*: ${{ job.status }}"
|
||||||
|
blocks:
|
||||||
|
- type: "section"
|
||||||
|
text:
|
||||||
|
type: "mrkdwn"
|
||||||
|
text: "*Deployment Status Update*: ${{ job.status }}"
|
||||||
|
- type: "section"
|
||||||
|
fields:
|
||||||
|
- type: "mrkdwn"
|
||||||
|
text: "*Application:*\nInfisical Core"
|
||||||
|
- type: "mrkdwn"
|
||||||
|
text: "*Instance Type:*\nShared Infisical Cloud"
|
||||||
|
- type: "section"
|
||||||
|
fields:
|
||||||
|
- type: "mrkdwn"
|
||||||
|
text: "*Region:*\nUS"
|
||||||
|
- type: "mrkdwn"
|
||||||
|
text: "*Git Tag:*\n<https://github.com/Infisical/infisical/commit/${{ steps.commit.outputs.short }}>"
|
||||||
|
|
||||||
|
|
||||||
|
production-eu:
|
||||||
|
name: EU production deploy
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [production-us]
|
||||||
|
environment:
|
||||||
|
name: production-eu
|
||||||
|
steps:
|
||||||
|
- uses: twingate/github-action@v1
|
||||||
|
with:
|
||||||
|
service-key: ${{ secrets.TWINGATE_SERVICE_KEY }}
|
||||||
|
- name: Configure AWS Credentials
|
||||||
|
uses: aws-actions/configure-aws-credentials@v4
|
||||||
|
with:
|
||||||
|
audience: sts.amazonaws.com
|
||||||
|
aws-region: eu-central-1
|
||||||
|
role-to-assume: arn:aws:iam::345594589636:role/gha-make-prod-deployment
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Setup Node.js environment
|
||||||
|
uses: actions/setup-node@v2
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
- name: Change directory to backend and install dependencies
|
||||||
|
env:
|
||||||
|
DB_CONNECTION_URI: ${{ secrets.DB_CONNECTION_URI }}
|
||||||
|
run: |
|
||||||
|
cd backend
|
||||||
|
npm install
|
||||||
|
npm run migration:latest
|
||||||
|
- name: Save commit hashes for tag
|
||||||
|
id: commit
|
||||||
|
uses: pr-mpt/actions-commit-hash@v2
|
||||||
|
- name: Download task definition
|
||||||
|
run: |
|
||||||
|
aws ecs describe-task-definition --task-definition infisical-core-platform --query taskDefinition > task-definition.json
|
||||||
|
- name: Render Amazon ECS task definition
|
||||||
|
id: render-web-container
|
||||||
|
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||||
|
with:
|
||||||
|
task-definition: task-definition.json
|
||||||
|
container-name: infisical-core-platform
|
||||||
|
image: infisical/staging_infisical:${{ steps.commit.outputs.short }}
|
||||||
|
environment-variables: "LOG_LEVEL=info"
|
||||||
|
- name: Deploy to Amazon ECS service
|
||||||
|
uses: aws-actions/amazon-ecs-deploy-task-definition@v2
|
||||||
|
with:
|
||||||
|
task-definition: ${{ steps.render-web-container.outputs.task-definition }}
|
||||||
|
service: infisical-core-platform
|
||||||
|
cluster: infisical-core-platform
|
||||||
|
wait-for-service-stability: true
|
||||||
|
- name: Post slack message
|
||||||
|
uses: slackapi/slack-github-action@v2.0.0
|
||||||
|
with:
|
||||||
|
webhook: ${{ secrets.SLACK_DEPLOYMENT_WEBHOOK_URL }}
|
||||||
|
webhook-type: incoming-webhook
|
||||||
|
payload: |
|
||||||
|
text: "*Deployment Status Update*: ${{ job.status }}"
|
||||||
|
blocks:
|
||||||
|
- type: "section"
|
||||||
|
text:
|
||||||
|
type: "mrkdwn"
|
||||||
|
text: "*Deployment Status Update*: ${{ job.status }}"
|
||||||
|
- type: "section"
|
||||||
|
fields:
|
||||||
|
- type: "mrkdwn"
|
||||||
|
text: "*Application:*\nInfisical Core"
|
||||||
|
- type: "mrkdwn"
|
||||||
|
text: "*Instance Type:*\nShared Infisical Cloud"
|
||||||
|
- type: "section"
|
||||||
|
fields:
|
||||||
|
- type: "mrkdwn"
|
||||||
|
text: "*Region:*\nEU"
|
||||||
|
- type: "mrkdwn"
|
||||||
|
text: "*Git Tag:*\n<https://github.com/Infisical/infisical/commit/${{ steps.commit.outputs.short }}>"
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
name: Release Helm Charts
|
name: Release Infisical Core Helm chart
|
||||||
|
|
||||||
on: [workflow_dispatch]
|
on: [workflow_dispatch]
|
||||||
|
|
||||||
@ -17,6 +17,6 @@ jobs:
|
|||||||
- name: Install Cloudsmith CLI
|
- name: Install Cloudsmith CLI
|
||||||
run: pip install --upgrade cloudsmith-cli
|
run: pip install --upgrade cloudsmith-cli
|
||||||
- name: Build and push helm package to Cloudsmith
|
- name: Build and push helm package to Cloudsmith
|
||||||
run: cd helm-charts && sh upload-to-cloudsmith.sh
|
run: cd helm-charts && sh upload-infisical-core-helm-cloudsmith.sh
|
||||||
env:
|
env:
|
||||||
CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }}
|
CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }}
|
@ -1,62 +1,115 @@
|
|||||||
name: Release standalone docker image
|
name: Release standalone docker image
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- "infisical/v*.*.*-postgres"
|
- "infisical/v*.*.*-postgres"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
infisical-tests:
|
infisical-tests:
|
||||||
name: Run tests before deployment
|
name: Run tests before deployment
|
||||||
# https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview
|
# https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview
|
||||||
uses: ./.github/workflows/run-backend-tests.yml
|
uses: ./.github/workflows/run-backend-tests.yml
|
||||||
infisical-standalone:
|
|
||||||
name: Build infisical standalone image postgres
|
infisical-standalone:
|
||||||
runs-on: ubuntu-latest
|
name: Build infisical standalone image postgres
|
||||||
needs: [infisical-tests]
|
runs-on: ubuntu-latest
|
||||||
steps:
|
needs: [infisical-tests]
|
||||||
- name: Extract version from tag
|
steps:
|
||||||
id: extract_version
|
- name: Extract version from tag
|
||||||
run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical/}"
|
id: extract_version
|
||||||
- name: ☁️ Checkout source
|
run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical/}"
|
||||||
uses: actions/checkout@v3
|
- name: ☁️ Checkout source
|
||||||
with:
|
uses: actions/checkout@v3
|
||||||
fetch-depth: 0
|
with:
|
||||||
- name: 📦 Install dependencies to test all dependencies
|
fetch-depth: 0
|
||||||
run: npm ci --only-production
|
- name: 📦 Install dependencies to test all dependencies
|
||||||
working-directory: backend
|
run: npm ci --only-production
|
||||||
- name: version output
|
working-directory: backend
|
||||||
run: |
|
- name: version output
|
||||||
echo "Output Value: ${{ steps.version.outputs.major }}"
|
run: |
|
||||||
echo "Output Value: ${{ steps.version.outputs.minor }}"
|
echo "Output Value: ${{ steps.version.outputs.major }}"
|
||||||
echo "Output Value: ${{ steps.version.outputs.patch }}"
|
echo "Output Value: ${{ steps.version.outputs.minor }}"
|
||||||
echo "Output Value: ${{ steps.version.outputs.version }}"
|
echo "Output Value: ${{ steps.version.outputs.patch }}"
|
||||||
echo "Output Value: ${{ steps.version.outputs.version_type }}"
|
echo "Output Value: ${{ steps.version.outputs.version }}"
|
||||||
echo "Output Value: ${{ steps.version.outputs.increment }}"
|
echo "Output Value: ${{ steps.version.outputs.version_type }}"
|
||||||
- name: Save commit hashes for tag
|
echo "Output Value: ${{ steps.version.outputs.increment }}"
|
||||||
id: commit
|
- name: Save commit hashes for tag
|
||||||
uses: pr-mpt/actions-commit-hash@v2
|
id: commit
|
||||||
- name: 🔧 Set up Docker Buildx
|
uses: pr-mpt/actions-commit-hash@v2
|
||||||
uses: docker/setup-buildx-action@v2
|
- name: 🔧 Set up Docker Buildx
|
||||||
- name: 🐋 Login to Docker Hub
|
uses: docker/setup-buildx-action@v2
|
||||||
uses: docker/login-action@v2
|
- name: 🐋 Login to Docker Hub
|
||||||
with:
|
uses: docker/login-action@v2
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
with:
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
- name: Set up Depot CLI
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
uses: depot/setup-action@v1
|
- name: Set up Depot CLI
|
||||||
- name: 📦 Build backend and export to Docker
|
uses: depot/setup-action@v1
|
||||||
uses: depot/build-push-action@v1
|
- name: 📦 Build backend and export to Docker
|
||||||
with:
|
uses: depot/build-push-action@v1
|
||||||
project: 64mmf0n610
|
with:
|
||||||
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
project: 64mmf0n610
|
||||||
push: true
|
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||||
context: .
|
push: true
|
||||||
tags: |
|
context: .
|
||||||
infisical/infisical:latest-postgres
|
tags: |
|
||||||
infisical/infisical:${{ steps.commit.outputs.short }}
|
infisical/infisical:latest-postgres
|
||||||
infisical/infisical:${{ steps.extract_version.outputs.version }}
|
infisical/infisical:${{ steps.commit.outputs.short }}
|
||||||
platforms: linux/amd64,linux/arm64
|
infisical/infisical:${{ steps.extract_version.outputs.version }}
|
||||||
file: Dockerfile.standalone-infisical
|
platforms: linux/amd64,linux/arm64
|
||||||
build-args: |
|
file: Dockerfile.standalone-infisical
|
||||||
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
|
build-args: |
|
||||||
INFISICAL_PLATFORM_VERSION=${{ steps.extract_version.outputs.version }}
|
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
|
||||||
|
INFISICAL_PLATFORM_VERSION=${{ steps.extract_version.outputs.version }}
|
||||||
|
|
||||||
|
infisical-fips-standalone:
|
||||||
|
name: Build infisical standalone image postgres
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [infisical-tests]
|
||||||
|
steps:
|
||||||
|
- name: Extract version from tag
|
||||||
|
id: extract_version
|
||||||
|
run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical/}"
|
||||||
|
- name: ☁️ Checkout source
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: 📦 Install dependencies to test all dependencies
|
||||||
|
run: npm ci --only-production
|
||||||
|
working-directory: backend
|
||||||
|
- name: version output
|
||||||
|
run: |
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.major }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.minor }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.patch }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.version }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.version_type }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.increment }}"
|
||||||
|
- name: Save commit hashes for tag
|
||||||
|
id: commit
|
||||||
|
uses: pr-mpt/actions-commit-hash@v2
|
||||||
|
- name: 🔧 Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: 🐋 Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Set up Depot CLI
|
||||||
|
uses: depot/setup-action@v1
|
||||||
|
- name: 📦 Build backend and export to Docker
|
||||||
|
uses: depot/build-push-action@v1
|
||||||
|
with:
|
||||||
|
project: 64mmf0n610
|
||||||
|
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||||
|
push: true
|
||||||
|
context: .
|
||||||
|
tags: |
|
||||||
|
infisical/infisical-fips:latest-postgres
|
||||||
|
infisical/infisical-fips:${{ steps.commit.outputs.short }}
|
||||||
|
infisical/infisical-fips:${{ steps.extract_version.outputs.version }}
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
file: Dockerfile.fips.standalone-infisical
|
||||||
|
build-args: |
|
||||||
|
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
|
||||||
|
INFISICAL_PLATFORM_VERSION=${{ steps.extract_version.outputs.version }}
|
||||||
|
@ -10,8 +10,7 @@ on:
|
|||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
# packages: write
|
|
||||||
# issues: write
|
|
||||||
jobs:
|
jobs:
|
||||||
cli-integration-tests:
|
cli-integration-tests:
|
||||||
name: Run tests before deployment
|
name: Run tests before deployment
|
||||||
@ -26,6 +25,63 @@ jobs:
|
|||||||
CLI_TESTS_USER_PASSWORD: ${{ secrets.CLI_TESTS_USER_PASSWORD }}
|
CLI_TESTS_USER_PASSWORD: ${{ secrets.CLI_TESTS_USER_PASSWORD }}
|
||||||
CLI_TESTS_INFISICAL_VAULT_FILE_PASSPHRASE: ${{ secrets.CLI_TESTS_INFISICAL_VAULT_FILE_PASSPHRASE }}
|
CLI_TESTS_INFISICAL_VAULT_FILE_PASSPHRASE: ${{ secrets.CLI_TESTS_INFISICAL_VAULT_FILE_PASSPHRASE }}
|
||||||
|
|
||||||
|
npm-release:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
env:
|
||||||
|
working-directory: ./npm
|
||||||
|
needs:
|
||||||
|
- cli-integration-tests
|
||||||
|
- goreleaser
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Extract version
|
||||||
|
run: |
|
||||||
|
VERSION=$(echo ${{ github.ref_name }} | sed 's/infisical-cli\/v//')
|
||||||
|
echo "Version extracted: $VERSION"
|
||||||
|
echo "CLI_VERSION=$VERSION" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Print version
|
||||||
|
run: echo ${{ env.CLI_VERSION }}
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4.0.0
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: "npm"
|
||||||
|
cache-dependency-path: ./npm/package-lock.json
|
||||||
|
- name: Install dependencies
|
||||||
|
working-directory: ${{ env.working-directory }}
|
||||||
|
run: npm install --ignore-scripts
|
||||||
|
|
||||||
|
- name: Set NPM version
|
||||||
|
working-directory: ${{ env.working-directory }}
|
||||||
|
run: npm version ${{ env.CLI_VERSION }} --allow-same-version --no-git-tag-version
|
||||||
|
|
||||||
|
- name: Setup NPM
|
||||||
|
working-directory: ${{ env.working-directory }}
|
||||||
|
run: |
|
||||||
|
echo 'registry="https://registry.npmjs.org/"' > ./.npmrc
|
||||||
|
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ./.npmrc
|
||||||
|
|
||||||
|
echo 'registry="https://registry.npmjs.org/"' > ~/.npmrc
|
||||||
|
echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc
|
||||||
|
env:
|
||||||
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|
||||||
|
- name: Pack NPM
|
||||||
|
working-directory: ${{ env.working-directory }}
|
||||||
|
run: npm pack
|
||||||
|
|
||||||
|
- name: Publish NPM
|
||||||
|
working-directory: ${{ env.working-directory }}
|
||||||
|
run: npm publish --tarball=./infisical-sdk-${{github.ref_name}} --access public --registry=https://registry.npmjs.org/
|
||||||
|
env:
|
||||||
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|
||||||
goreleaser:
|
goreleaser:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
needs: [cli-integration-tests]
|
needs: [cli-integration-tests]
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
name: Release Docker image for K8 operator
|
name: Release image + Helm chart K8s Operator
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
@ -35,3 +35,18 @@ jobs:
|
|||||||
tags: |
|
tags: |
|
||||||
infisical/kubernetes-operator:latest
|
infisical/kubernetes-operator:latest
|
||||||
infisical/kubernetes-operator:${{ steps.extract_version.outputs.version }}
|
infisical/kubernetes-operator:${{ steps.extract_version.outputs.version }}
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Install Helm
|
||||||
|
uses: azure/setup-helm@v3
|
||||||
|
with:
|
||||||
|
version: v3.10.0
|
||||||
|
- name: Install python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
- name: Install Cloudsmith CLI
|
||||||
|
run: pip install --upgrade cloudsmith-cli
|
||||||
|
- name: Build and push helm package to Cloudsmith
|
||||||
|
run: cd helm-charts && sh upload-k8s-operator-cloudsmith.sh
|
||||||
|
env:
|
||||||
|
CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }}
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -71,3 +71,5 @@ frontend-build
|
|||||||
cli/infisical-merge
|
cli/infisical-merge
|
||||||
cli/test/infisical-merge
|
cli/test/infisical-merge
|
||||||
/backend/binary
|
/backend/binary
|
||||||
|
|
||||||
|
/npm/bin
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
. "$(dirname -- "$0")/_/husky.sh"
|
. "$(dirname -- "$0")/_/husky.sh"
|
||||||
|
|
||||||
|
# Check if infisical is installed
|
||||||
|
if ! command -v infisical >/dev/null 2>&1; then
|
||||||
|
echo "\nError: Infisical CLI is not installed. Please install the Infisical CLI before comitting.\n You can refer to the documentation at https://infisical.com/docs/cli/overview\n\n"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
npx lint-staged
|
npx lint-staged
|
||||||
|
|
||||||
infisical scan git-changes --staged -v
|
infisical scan git-changes --staged -v
|
||||||
|
@ -6,3 +6,5 @@ frontend/src/views/Project/MembersPage/components/MemberListTab/MemberRoleForm/S
|
|||||||
docs/self-hosting/configuration/envars.mdx:generic-api-key:106
|
docs/self-hosting/configuration/envars.mdx:generic-api-key:106
|
||||||
frontend/src/views/Project/MembersPage/components/MemberListTab/MemberRoleForm/SpecificPrivilegeSection.tsx:generic-api-key:451
|
frontend/src/views/Project/MembersPage/components/MemberListTab/MemberRoleForm/SpecificPrivilegeSection.tsx:generic-api-key:451
|
||||||
docs/mint.json:generic-api-key:651
|
docs/mint.json:generic-api-key:651
|
||||||
|
backend/src/ee/services/hsm/hsm-service.ts:generic-api-key:134
|
||||||
|
docs/documentation/platform/audit-log-streams/audit-log-streams.mdx:generic-api-key:104
|
||||||
|
181
Dockerfile.fips.standalone-infisical
Normal file
181
Dockerfile.fips.standalone-infisical
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
ARG POSTHOG_HOST=https://app.posthog.com
|
||||||
|
ARG POSTHOG_API_KEY=posthog-api-key
|
||||||
|
ARG INTERCOM_ID=intercom-id
|
||||||
|
ARG CAPTCHA_SITE_KEY=captcha-site-key
|
||||||
|
|
||||||
|
FROM node:20-slim AS base
|
||||||
|
|
||||||
|
FROM base AS frontend-dependencies
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY frontend/package.json frontend/package-lock.json ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm ci --only-production --ignore-scripts
|
||||||
|
|
||||||
|
# Rebuild the source code only when needed
|
||||||
|
FROM base AS frontend-builder
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy dependencies
|
||||||
|
COPY --from=frontend-dependencies /app/node_modules ./node_modules
|
||||||
|
# Copy all files
|
||||||
|
COPY /frontend .
|
||||||
|
|
||||||
|
ENV NODE_ENV production
|
||||||
|
ARG POSTHOG_HOST
|
||||||
|
ENV VITE_POSTHOG_HOST $POSTHOG_HOST
|
||||||
|
ARG POSTHOG_API_KEY
|
||||||
|
ENV VITE_POSTHOG_API_KEY $POSTHOG_API_KEY
|
||||||
|
ARG INTERCOM_ID
|
||||||
|
ENV VITE_INTERCOM_ID $INTERCOM_ID
|
||||||
|
ARG INFISICAL_PLATFORM_VERSION
|
||||||
|
ENV VITE_INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION
|
||||||
|
ARG CAPTCHA_SITE_KEY
|
||||||
|
ENV VITE_CAPTCHA_SITE_KEY $CAPTCHA_SITE_KEY
|
||||||
|
|
||||||
|
# Build
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production image
|
||||||
|
FROM base AS frontend-runner
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN groupadd -r -g 1001 nodejs && useradd -r -u 1001 -g nodejs non-root-user
|
||||||
|
|
||||||
|
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/dist ./
|
||||||
|
|
||||||
|
USER non-root-user
|
||||||
|
|
||||||
|
##
|
||||||
|
## BACKEND
|
||||||
|
##
|
||||||
|
FROM base AS backend-build
|
||||||
|
|
||||||
|
ENV ChrystokiConfigurationPath=/usr/safenet/lunaclient/
|
||||||
|
|
||||||
|
RUN groupadd -r -g 1001 nodejs && useradd -r -u 1001 -g nodejs non-root-user
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Required for pkcs11js and ODBC
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
unixodbc \
|
||||||
|
unixodbc-dev \
|
||||||
|
freetds-dev \
|
||||||
|
freetds-bin \
|
||||||
|
tdsodbc \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Configure ODBC
|
||||||
|
RUN printf "[FreeTDS]\nDescription = FreeTDS Driver\nDriver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so\nSetup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so\nFileUsage = 1\n" > /etc/odbcinst.ini
|
||||||
|
|
||||||
|
COPY backend/package*.json ./
|
||||||
|
RUN npm ci --only-production
|
||||||
|
|
||||||
|
COPY /backend .
|
||||||
|
COPY --chown=non-root-user:nodejs standalone-entrypoint.sh standalone-entrypoint.sh
|
||||||
|
RUN npm i -D tsconfig-paths
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM base AS backend-runner
|
||||||
|
|
||||||
|
ENV ChrystokiConfigurationPath=/usr/safenet/lunaclient/
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Required for pkcs11js and ODBC
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
unixodbc \
|
||||||
|
unixodbc-dev \
|
||||||
|
freetds-dev \
|
||||||
|
freetds-bin \
|
||||||
|
tdsodbc \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Configure ODBC
|
||||||
|
RUN printf "[FreeTDS]\nDescription = FreeTDS Driver\nDriver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so\nSetup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so\nFileUsage = 1\n" > /etc/odbcinst.ini
|
||||||
|
|
||||||
|
COPY backend/package*.json ./
|
||||||
|
RUN npm ci --only-production
|
||||||
|
|
||||||
|
COPY --from=backend-build /app .
|
||||||
|
|
||||||
|
RUN mkdir frontend-build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM base AS production
|
||||||
|
|
||||||
|
# Install necessary packages including ODBC
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
git \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
unixodbc \
|
||||||
|
unixodbc-dev \
|
||||||
|
freetds-dev \
|
||||||
|
freetds-bin \
|
||||||
|
tdsodbc \
|
||||||
|
openssh-client \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Configure ODBC in production
|
||||||
|
RUN printf "[FreeTDS]\nDescription = FreeTDS Driver\nDriver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so\nSetup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so\nFileUsage = 1\n" > /etc/odbcinst.ini
|
||||||
|
|
||||||
|
# Install Infisical CLI
|
||||||
|
RUN curl -1sLf 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' | bash \
|
||||||
|
&& apt-get update && apt-get install -y infisical=0.31.1 \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN groupadd -r -g 1001 nodejs && useradd -r -u 1001 -g nodejs non-root-user
|
||||||
|
|
||||||
|
# Give non-root-user permission to update SSL certs
|
||||||
|
RUN chown -R non-root-user /etc/ssl/certs
|
||||||
|
RUN chown non-root-user /etc/ssl/certs/ca-certificates.crt
|
||||||
|
RUN chmod -R u+rwx /etc/ssl/certs
|
||||||
|
RUN chmod u+rw /etc/ssl/certs/ca-certificates.crt
|
||||||
|
RUN chown non-root-user /usr/sbin/update-ca-certificates
|
||||||
|
RUN chmod u+rx /usr/sbin/update-ca-certificates
|
||||||
|
|
||||||
|
## set pre baked keys
|
||||||
|
ARG POSTHOG_API_KEY
|
||||||
|
ENV POSTHOG_API_KEY=$POSTHOG_API_KEY
|
||||||
|
ARG INTERCOM_ID=intercom-id
|
||||||
|
ENV INTERCOM_ID=$INTERCOM_ID
|
||||||
|
ARG CAPTCHA_SITE_KEY
|
||||||
|
ENV CAPTCHA_SITE_KEY=$CAPTCHA_SITE_KEY
|
||||||
|
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
|
COPY --from=backend-runner /app /backend
|
||||||
|
|
||||||
|
COPY --from=frontend-runner /app ./backend/frontend-build
|
||||||
|
|
||||||
|
ENV PORT 8080
|
||||||
|
ENV HOST=0.0.0.0
|
||||||
|
ENV HTTPS_ENABLED false
|
||||||
|
ENV NODE_ENV production
|
||||||
|
ENV STANDALONE_BUILD true
|
||||||
|
ENV STANDALONE_MODE true
|
||||||
|
ENV ChrystokiConfigurationPath=/usr/safenet/lunaclient/
|
||||||
|
|
||||||
|
WORKDIR /backend
|
||||||
|
|
||||||
|
ENV TELEMETRY_ENABLED true
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
EXPOSE 443
|
||||||
|
|
||||||
|
USER non-root-user
|
||||||
|
|
||||||
|
CMD ["./standalone-entrypoint.sh"]
|
@ -12,7 +12,7 @@ RUN apk add --no-cache libc6-compat
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY frontend/package.json frontend/package-lock.json frontend/next.config.js ./
|
COPY frontend/package.json frontend/package-lock.json ./
|
||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
RUN npm ci --only-production --ignore-scripts
|
RUN npm ci --only-production --ignore-scripts
|
||||||
@ -27,17 +27,16 @@ COPY --from=frontend-dependencies /app/node_modules ./node_modules
|
|||||||
COPY /frontend .
|
COPY /frontend .
|
||||||
|
|
||||||
ENV NODE_ENV production
|
ENV NODE_ENV production
|
||||||
ENV NEXT_PUBLIC_ENV production
|
|
||||||
ARG POSTHOG_HOST
|
ARG POSTHOG_HOST
|
||||||
ENV NEXT_PUBLIC_POSTHOG_HOST $POSTHOG_HOST
|
ENV VITE_POSTHOG_HOST $POSTHOG_HOST
|
||||||
ARG POSTHOG_API_KEY
|
ARG POSTHOG_API_KEY
|
||||||
ENV NEXT_PUBLIC_POSTHOG_API_KEY $POSTHOG_API_KEY
|
ENV VITE_POSTHOG_API_KEY $POSTHOG_API_KEY
|
||||||
ARG INTERCOM_ID
|
ARG INTERCOM_ID
|
||||||
ENV NEXT_PUBLIC_INTERCOM_ID $INTERCOM_ID
|
ENV VITE_INTERCOM_ID $INTERCOM_ID
|
||||||
ARG INFISICAL_PLATFORM_VERSION
|
ARG INFISICAL_PLATFORM_VERSION
|
||||||
ENV NEXT_PUBLIC_INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION
|
ENV VITE_INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION
|
||||||
ARG CAPTCHA_SITE_KEY
|
ARG CAPTCHA_SITE_KEY
|
||||||
ENV NEXT_PUBLIC_CAPTCHA_SITE_KEY $CAPTCHA_SITE_KEY
|
ENV VITE_CAPTCHA_SITE_KEY $CAPTCHA_SITE_KEY
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
@ -49,20 +48,10 @@ WORKDIR /app
|
|||||||
RUN addgroup --system --gid 1001 nodejs
|
RUN addgroup --system --gid 1001 nodejs
|
||||||
RUN adduser --system --uid 1001 non-root-user
|
RUN adduser --system --uid 1001 non-root-user
|
||||||
|
|
||||||
RUN mkdir -p /app/.next/cache/images && chown non-root-user:nodejs /app/.next/cache/images
|
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/dist ./
|
||||||
VOLUME /app/.next/cache/images
|
|
||||||
|
|
||||||
COPY --chown=non-root-user:nodejs --chmod=555 frontend/scripts ./scripts
|
|
||||||
COPY --from=frontend-builder /app/public ./public
|
|
||||||
RUN chown non-root-user:nodejs ./public/data
|
|
||||||
|
|
||||||
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/.next/standalone ./
|
|
||||||
COPY --from=frontend-builder --chown=non-root-user:nodejs /app/.next/static ./.next/static
|
|
||||||
|
|
||||||
USER non-root-user
|
USER non-root-user
|
||||||
|
|
||||||
ENV NEXT_TELEMETRY_DISABLED 1
|
|
||||||
|
|
||||||
##
|
##
|
||||||
## BACKEND
|
## BACKEND
|
||||||
##
|
##
|
||||||
@ -72,6 +61,17 @@ RUN addgroup --system --gid 1001 nodejs \
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install all required dependencies for build
|
||||||
|
RUN apk --update add \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
unixodbc \
|
||||||
|
freetds \
|
||||||
|
unixodbc-dev \
|
||||||
|
libc-dev \
|
||||||
|
freetds-dev
|
||||||
|
|
||||||
COPY backend/package*.json ./
|
COPY backend/package*.json ./
|
||||||
RUN npm ci --only-production
|
RUN npm ci --only-production
|
||||||
|
|
||||||
@ -85,6 +85,20 @@ FROM base AS backend-runner
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Install all required dependencies for runtime
|
||||||
|
RUN apk --update add \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
unixodbc \
|
||||||
|
freetds \
|
||||||
|
unixodbc-dev \
|
||||||
|
libc-dev \
|
||||||
|
freetds-dev
|
||||||
|
|
||||||
|
# Configure ODBC
|
||||||
|
RUN printf "[FreeTDS]\nDescription = FreeTDS Driver\nDriver = /usr/lib/libtdsodbc.so\nSetup = /usr/lib/libtdsodbc.so\nFileUsage = 1\n" > /etc/odbcinst.ini
|
||||||
|
|
||||||
COPY backend/package*.json ./
|
COPY backend/package*.json ./
|
||||||
RUN npm ci --only-production
|
RUN npm ci --only-production
|
||||||
|
|
||||||
@ -94,7 +108,33 @@ RUN mkdir frontend-build
|
|||||||
|
|
||||||
# Production stage
|
# Production stage
|
||||||
FROM base AS production
|
FROM base AS production
|
||||||
|
|
||||||
RUN apk add --upgrade --no-cache ca-certificates
|
RUN apk add --upgrade --no-cache ca-certificates
|
||||||
|
RUN apk add --no-cache bash curl && curl -1sLf \
|
||||||
|
'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash \
|
||||||
|
&& apk add infisical=0.31.1 && apk add --no-cache git
|
||||||
|
|
||||||
|
WORKDIR /
|
||||||
|
|
||||||
|
# Install all required runtime dependencies
|
||||||
|
RUN apk --update add \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
unixodbc \
|
||||||
|
freetds \
|
||||||
|
unixodbc-dev \
|
||||||
|
libc-dev \
|
||||||
|
freetds-dev \
|
||||||
|
bash \
|
||||||
|
curl \
|
||||||
|
git \
|
||||||
|
openssh
|
||||||
|
|
||||||
|
# Configure ODBC in production
|
||||||
|
RUN printf "[FreeTDS]\nDescription = FreeTDS Driver\nDriver = /usr/lib/libtdsodbc.so\nSetup = /usr/lib/libtdsodbc.so\nFileUsage = 1\n" > /etc/odbcinst.ini
|
||||||
|
|
||||||
|
# Setup user permissions
|
||||||
RUN addgroup --system --gid 1001 nodejs \
|
RUN addgroup --system --gid 1001 nodejs \
|
||||||
&& adduser --system --uid 1001 non-root-user
|
&& adduser --system --uid 1001 non-root-user
|
||||||
|
|
||||||
@ -108,16 +148,12 @@ RUN chmod u+rx /usr/sbin/update-ca-certificates
|
|||||||
|
|
||||||
## set pre baked keys
|
## set pre baked keys
|
||||||
ARG POSTHOG_API_KEY
|
ARG POSTHOG_API_KEY
|
||||||
ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \
|
ENV POSTHOG_API_KEY=$POSTHOG_API_KEY
|
||||||
BAKED_NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY
|
|
||||||
ARG INTERCOM_ID=intercom-id
|
ARG INTERCOM_ID=intercom-id
|
||||||
ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
|
ENV INTERCOM_ID=$INTERCOM_ID
|
||||||
BAKED_NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID
|
|
||||||
ARG CAPTCHA_SITE_KEY
|
ARG CAPTCHA_SITE_KEY
|
||||||
ENV NEXT_PUBLIC_CAPTCHA_SITE_KEY=$CAPTCHA_SITE_KEY \
|
ENV CAPTCHA_SITE_KEY=$CAPTCHA_SITE_KEY
|
||||||
BAKED_NEXT_PUBLIC_CAPTCHA_SITE_KEY=$CAPTCHA_SITE_KEY
|
|
||||||
|
|
||||||
WORKDIR /
|
|
||||||
|
|
||||||
COPY --from=backend-runner /app /backend
|
COPY --from=backend-runner /app /backend
|
||||||
|
|
||||||
|
5
Makefile
5
Makefile
@ -10,6 +10,9 @@ up-dev:
|
|||||||
up-dev-ldap:
|
up-dev-ldap:
|
||||||
docker compose -f docker-compose.dev.yml --profile ldap up --build
|
docker compose -f docker-compose.dev.yml --profile ldap up --build
|
||||||
|
|
||||||
|
up-dev-metrics:
|
||||||
|
docker compose -f docker-compose.dev.yml --profile metrics up --build
|
||||||
|
|
||||||
up-prod:
|
up-prod:
|
||||||
docker-compose -f docker-compose.prod.yml up --build
|
docker-compose -f docker-compose.prod.yml up --build
|
||||||
|
|
||||||
@ -28,3 +31,5 @@ reviewable-api:
|
|||||||
|
|
||||||
reviewable: reviewable-ui reviewable-api
|
reviewable: reviewable-ui reviewable-api
|
||||||
|
|
||||||
|
up-dev-sso:
|
||||||
|
docker compose -f docker-compose.dev.yml --profile sso up --build
|
||||||
|
22
README.md
22
README.md
@ -14,15 +14,6 @@
|
|||||||
<a href="https://infisical.com/careers">Hiring (Remote/SF)</a>
|
<a href="https://infisical.com/careers">Hiring (Remote/SF)</a>
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<a href="https://infisical.com/docs/self-hosting/deployment-options/aws-ec2">
|
|
||||||
<img src=".github/images/deploy-to-aws.png" width="137" />
|
|
||||||
</a>
|
|
||||||
<a href="https://infisical.com/docs/self-hosting/deployment-options/digital-ocean-marketplace" alt="Deploy to DigitalOcean">
|
|
||||||
<img width="200" alt="Deploy to DO" src="https://www.deploytodo.com/do-btn-blue.svg"/>
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h4 align="center">
|
<h4 align="center">
|
||||||
<a href="https://github.com/Infisical/infisical/blob/main/LICENSE">
|
<a href="https://github.com/Infisical/infisical/blob/main/LICENSE">
|
||||||
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="Infisical is released under the MIT license." />
|
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="Infisical is released under the MIT license." />
|
||||||
@ -65,7 +56,7 @@ We're on a mission to make security tooling more accessible to everyone, not jus
|
|||||||
- **[Infisical Kubernetes Operator](https://infisical.com/docs/documentation/getting-started/kubernetes)**: Deliver secrets to your Kubernetes workloads and automatically reload deployments.
|
- **[Infisical Kubernetes Operator](https://infisical.com/docs/documentation/getting-started/kubernetes)**: Deliver secrets to your Kubernetes workloads and automatically reload deployments.
|
||||||
- **[Infisical Agent](https://infisical.com/docs/infisical-agent/overview)**: Inject secrets into applications without modifying any code logic.
|
- **[Infisical Agent](https://infisical.com/docs/infisical-agent/overview)**: Inject secrets into applications without modifying any code logic.
|
||||||
|
|
||||||
### Internal PKI:
|
### Infisical (Internal) PKI:
|
||||||
|
|
||||||
- **[Private Certificate Authority](https://infisical.com/docs/documentation/platform/pki/private-ca)**: Create CA hierarchies, configure [certificate templates](https://infisical.com/docs/documentation/platform/pki/certificates#guide-to-issuing-certificates) for policy enforcement, and start issuing X.509 certificates.
|
- **[Private Certificate Authority](https://infisical.com/docs/documentation/platform/pki/private-ca)**: Create CA hierarchies, configure [certificate templates](https://infisical.com/docs/documentation/platform/pki/certificates#guide-to-issuing-certificates) for policy enforcement, and start issuing X.509 certificates.
|
||||||
- **[Certificate Management](https://infisical.com/docs/documentation/platform/pki/certificates)**: Manage the certificate lifecycle from [issuance](https://infisical.com/docs/documentation/platform/pki/certificates#guide-to-issuing-certificates) to [revocation](https://infisical.com/docs/documentation/platform/pki/certificates#guide-to-revoking-certificates) with support for CRL.
|
- **[Certificate Management](https://infisical.com/docs/documentation/platform/pki/certificates)**: Manage the certificate lifecycle from [issuance](https://infisical.com/docs/documentation/platform/pki/certificates#guide-to-issuing-certificates) to [revocation](https://infisical.com/docs/documentation/platform/pki/certificates#guide-to-revoking-certificates) with support for CRL.
|
||||||
@ -73,12 +64,17 @@ We're on a mission to make security tooling more accessible to everyone, not jus
|
|||||||
- **[Infisical PKI Issuer for Kubernetes](https://infisical.com/docs/documentation/platform/pki/pki-issuer)**: Deliver TLS certificates to your Kubernetes workloads with automatic renewal.
|
- **[Infisical PKI Issuer for Kubernetes](https://infisical.com/docs/documentation/platform/pki/pki-issuer)**: Deliver TLS certificates to your Kubernetes workloads with automatic renewal.
|
||||||
- **[Enrollment over Secure Transport](https://infisical.com/docs/documentation/platform/pki/est)**: Enroll and manage certificates via EST protocol.
|
- **[Enrollment over Secure Transport](https://infisical.com/docs/documentation/platform/pki/est)**: Enroll and manage certificates via EST protocol.
|
||||||
|
|
||||||
### Key Management (KMS):
|
### Infisical Key Management System (KMS):
|
||||||
|
|
||||||
- **[Cryptograhic Keys](https://infisical.com/docs/documentation/platform/kms)**: Centrally manage keys across projects through a user-friendly interface or via the API.
|
- **[Cryptographic Keys](https://infisical.com/docs/documentation/platform/kms)**: Centrally manage keys across projects through a user-friendly interface or via the API.
|
||||||
- **[Encrypt and Decrypt Data](https://infisical.com/docs/documentation/platform/kms#guide-to-encrypting-data)**: Use symmetric keys to encrypt and decrypt data.
|
- **[Encrypt and Decrypt Data](https://infisical.com/docs/documentation/platform/kms#guide-to-encrypting-data)**: Use symmetric keys to encrypt and decrypt data.
|
||||||
|
|
||||||
|
### Infisical SSH
|
||||||
|
|
||||||
|
- **[Signed SSH Certificates](https://infisical.com/docs/documentation/platform/ssh)**: Issue ephemeral SSH credentials for secure, short-lived, and centralized access to infrastructure.
|
||||||
|
|
||||||
### General Platform:
|
### General Platform:
|
||||||
|
|
||||||
- **Authentication Methods**: Authenticate machine identities with Infisical using a cloud-native or platform agnostic authentication method ([Kubernetes Auth](https://infisical.com/docs/documentation/platform/identities/kubernetes-auth), [GCP Auth](https://infisical.com/docs/documentation/platform/identities/gcp-auth), [Azure Auth](https://infisical.com/docs/documentation/platform/identities/azure-auth), [AWS Auth](https://infisical.com/docs/documentation/platform/identities/aws-auth), [OIDC Auth](https://infisical.com/docs/documentation/platform/identities/oidc-auth/general), [Universal Auth](https://infisical.com/docs/documentation/platform/identities/universal-auth)).
|
- **Authentication Methods**: Authenticate machine identities with Infisical using a cloud-native or platform agnostic authentication method ([Kubernetes Auth](https://infisical.com/docs/documentation/platform/identities/kubernetes-auth), [GCP Auth](https://infisical.com/docs/documentation/platform/identities/gcp-auth), [Azure Auth](https://infisical.com/docs/documentation/platform/identities/azure-auth), [AWS Auth](https://infisical.com/docs/documentation/platform/identities/aws-auth), [OIDC Auth](https://infisical.com/docs/documentation/platform/identities/oidc-auth/general), [Universal Auth](https://infisical.com/docs/documentation/platform/identities/universal-auth)).
|
||||||
- **[Access Controls](https://infisical.com/docs/documentation/platform/access-controls/overview)**: Define advanced authorization controls for users and machine identities with [RBAC](https://infisical.com/docs/documentation/platform/access-controls/role-based-access-controls), [additional privileges](https://infisical.com/docs/documentation/platform/access-controls/additional-privileges), [temporary access](https://infisical.com/docs/documentation/platform/access-controls/temporary-access), [access requests](https://infisical.com/docs/documentation/platform/access-controls/access-requests), [approval workflows](https://infisical.com/docs/documentation/platform/pr-workflows), and more.
|
- **[Access Controls](https://infisical.com/docs/documentation/platform/access-controls/overview)**: Define advanced authorization controls for users and machine identities with [RBAC](https://infisical.com/docs/documentation/platform/access-controls/role-based-access-controls), [additional privileges](https://infisical.com/docs/documentation/platform/access-controls/additional-privileges), [temporary access](https://infisical.com/docs/documentation/platform/access-controls/temporary-access), [access requests](https://infisical.com/docs/documentation/platform/access-controls/access-requests), [approval workflows](https://infisical.com/docs/documentation/platform/pr-workflows), and more.
|
||||||
- **[Audit logs](https://infisical.com/docs/documentation/platform/audit-logs)**: Track every action taken on the platform.
|
- **[Audit logs](https://infisical.com/docs/documentation/platform/audit-logs)**: Track every action taken on the platform.
|
||||||
@ -129,7 +125,7 @@ Install pre commit hook to scan each commit before you push to your repository
|
|||||||
infisical scan install --pre-commit-hook
|
infisical scan install --pre-commit-hook
|
||||||
```
|
```
|
||||||
|
|
||||||
Lean about Infisical's code scanning feature [here](https://infisical.com/docs/cli/scanning-overview)
|
Learn about Infisical's code scanning feature [here](https://infisical.com/docs/cli/scanning-overview)
|
||||||
|
|
||||||
## Open-source vs. paid
|
## Open-source vs. paid
|
||||||
|
|
||||||
|
@ -3,6 +3,22 @@ FROM node:20-alpine AS build
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Required for pkcs11js
|
||||||
|
RUN apk --update add \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
openssh
|
||||||
|
|
||||||
|
# install dependencies for TDS driver (required for SAP ASE dynamic secrets)
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
unixodbc \
|
||||||
|
freetds \
|
||||||
|
unixodbc-dev \
|
||||||
|
libc-dev \
|
||||||
|
freetds-dev
|
||||||
|
|
||||||
|
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
RUN npm ci --only-production
|
RUN npm ci --only-production
|
||||||
|
|
||||||
@ -11,12 +27,28 @@ RUN npm run build
|
|||||||
|
|
||||||
# Production stage
|
# Production stage
|
||||||
FROM node:20-alpine
|
FROM node:20-alpine
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
ENV npm_config_cache /home/node/.npm
|
ENV npm_config_cache /home/node/.npm
|
||||||
|
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
|
|
||||||
|
RUN apk --update add \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++
|
||||||
|
|
||||||
|
# install dependencies for TDS driver (required for SAP ASE dynamic secrets)
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
unixodbc \
|
||||||
|
freetds \
|
||||||
|
unixodbc-dev \
|
||||||
|
libc-dev \
|
||||||
|
freetds-dev
|
||||||
|
|
||||||
|
|
||||||
|
RUN printf "[FreeTDS]\nDescription = FreeTDS Driver\nDriver = /usr/lib/libtdsodbc.so\nSetup = /usr/lib/libtdsodbc.so\nFileUsage = 1\n" > /etc/odbcinst.ini
|
||||||
|
|
||||||
RUN npm ci --only-production && npm cache clean --force
|
RUN npm ci --only-production && npm cache clean --force
|
||||||
|
|
||||||
COPY --from=build /app .
|
COPY --from=build /app .
|
||||||
|
@ -1,5 +1,57 @@
|
|||||||
FROM node:20-alpine
|
FROM node:20-alpine
|
||||||
|
|
||||||
|
# ? Setup a test SoftHSM module. In production a real HSM is used.
|
||||||
|
|
||||||
|
ARG SOFTHSM2_VERSION=2.5.0
|
||||||
|
|
||||||
|
ENV SOFTHSM2_VERSION=${SOFTHSM2_VERSION} \
|
||||||
|
SOFTHSM2_SOURCES=/tmp/softhsm2
|
||||||
|
|
||||||
|
# install build dependencies including python3 (required for pkcs11js and partially TDS driver)
|
||||||
|
RUN apk --update add \
|
||||||
|
alpine-sdk \
|
||||||
|
autoconf \
|
||||||
|
automake \
|
||||||
|
git \
|
||||||
|
libtool \
|
||||||
|
openssl-dev \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++ \
|
||||||
|
openssh
|
||||||
|
|
||||||
|
# install dependencies for TDS driver (required for SAP ASE dynamic secrets)
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
unixodbc \
|
||||||
|
freetds \
|
||||||
|
unixodbc-dev \
|
||||||
|
libc-dev \
|
||||||
|
freetds-dev
|
||||||
|
|
||||||
|
|
||||||
|
RUN printf "[FreeTDS]\nDescription = FreeTDS Driver\nDriver = /usr/lib/libtdsodbc.so\nSetup = /usr/lib/libtdsodbc.so\nFileUsage = 1\n" > /etc/odbcinst.ini
|
||||||
|
|
||||||
|
# build and install SoftHSM2
|
||||||
|
|
||||||
|
RUN git clone https://github.com/opendnssec/SoftHSMv2.git ${SOFTHSM2_SOURCES}
|
||||||
|
WORKDIR ${SOFTHSM2_SOURCES}
|
||||||
|
|
||||||
|
RUN git checkout ${SOFTHSM2_VERSION} -b ${SOFTHSM2_VERSION} \
|
||||||
|
&& sh autogen.sh \
|
||||||
|
&& ./configure --prefix=/usr/local --disable-gost \
|
||||||
|
&& make \
|
||||||
|
&& make install
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
RUN rm -fr ${SOFTHSM2_SOURCES}
|
||||||
|
|
||||||
|
# install pkcs11-tool
|
||||||
|
RUN apk --update add opensc
|
||||||
|
|
||||||
|
RUN softhsm2-util --init-token --slot 0 --label "auth-app" --pin 1234 --so-pin 0000
|
||||||
|
|
||||||
|
# ? App setup
|
||||||
|
|
||||||
RUN apk add --no-cache bash curl && curl -1sLf \
|
RUN apk add --no-cache bash curl && curl -1sLf \
|
||||||
'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash \
|
'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash \
|
||||||
&& apk add infisical=0.8.1 && apk add --no-cache git
|
&& apk add infisical=0.8.1 && apk add --no-cache git
|
||||||
|
@ -10,17 +10,22 @@ export const mockQueue = (): TQueueServiceFactory => {
|
|||||||
queue: async (name, jobData) => {
|
queue: async (name, jobData) => {
|
||||||
job[name] = jobData;
|
job[name] = jobData;
|
||||||
},
|
},
|
||||||
|
queuePg: async () => {},
|
||||||
|
initialize: async () => {},
|
||||||
shutdown: async () => undefined,
|
shutdown: async () => undefined,
|
||||||
stopRepeatableJob: async () => true,
|
stopRepeatableJob: async () => true,
|
||||||
start: (name, jobFn) => {
|
start: (name, jobFn) => {
|
||||||
queues[name] = jobFn;
|
queues[name] = jobFn;
|
||||||
workers[name] = jobFn;
|
workers[name] = jobFn;
|
||||||
},
|
},
|
||||||
|
startPg: async () => {},
|
||||||
listen: (name, event) => {
|
listen: (name, event) => {
|
||||||
events[name] = event;
|
events[name] = event;
|
||||||
},
|
},
|
||||||
|
getRepeatableJobs: async () => [],
|
||||||
clearQueue: async () => {},
|
clearQueue: async () => {},
|
||||||
stopJobById: async () => {},
|
stopJobById: async () => {},
|
||||||
stopRepeatableJobByJobId: async () => true
|
stopRepeatableJobByJobId: async () => true,
|
||||||
|
stopRepeatableJobByKey: async () => true
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,9 @@ export const mockSmtpServer = (): TSmtpService => {
|
|||||||
return {
|
return {
|
||||||
sendMail: async (data) => {
|
sendMail: async (data) => {
|
||||||
storage.push(data);
|
storage.push(data);
|
||||||
|
},
|
||||||
|
verify: async () => {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -34,7 +34,7 @@ describe("Identity v1", async () => {
|
|||||||
test("Create identity", async () => {
|
test("Create identity", async () => {
|
||||||
const newIdentity = await createIdentity("mac1", OrgMembershipRole.Admin);
|
const newIdentity = await createIdentity("mac1", OrgMembershipRole.Admin);
|
||||||
expect(newIdentity.name).toBe("mac1");
|
expect(newIdentity.name).toBe("mac1");
|
||||||
expect(newIdentity.authMethod).toBeNull();
|
expect(newIdentity.authMethods).toEqual([]);
|
||||||
|
|
||||||
await deleteIdentity(newIdentity.id);
|
await deleteIdentity(newIdentity.id);
|
||||||
});
|
});
|
||||||
@ -42,7 +42,7 @@ describe("Identity v1", async () => {
|
|||||||
test("Update identity", async () => {
|
test("Update identity", async () => {
|
||||||
const newIdentity = await createIdentity("mac1", OrgMembershipRole.Admin);
|
const newIdentity = await createIdentity("mac1", OrgMembershipRole.Admin);
|
||||||
expect(newIdentity.name).toBe("mac1");
|
expect(newIdentity.name).toBe("mac1");
|
||||||
expect(newIdentity.authMethod).toBeNull();
|
expect(newIdentity.authMethods).toEqual([]);
|
||||||
|
|
||||||
const updatedIdentity = await testServer.inject({
|
const updatedIdentity = await testServer.inject({
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
|
@ -39,8 +39,6 @@ describe("Login V1 Router", async () => {
|
|||||||
});
|
});
|
||||||
expect(res.statusCode).toBe(200);
|
expect(res.statusCode).toBe(200);
|
||||||
const payload = JSON.parse(res.payload);
|
const payload = JSON.parse(res.payload);
|
||||||
expect(payload).toHaveProperty("mfaEnabled");
|
|
||||||
expect(payload).toHaveProperty("token");
|
expect(payload).toHaveProperty("token");
|
||||||
expect(payload.mfaEnabled).toBeFalsy();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -118,9 +118,9 @@ describe.each([{ secretPath: "/" }, { secretPath: "/deep" }])(
|
|||||||
value: "stage-value"
|
value: "stage-value"
|
||||||
});
|
});
|
||||||
|
|
||||||
// wait for 5 second for replication to finish
|
// wait for 10 second for replication to finish
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
setTimeout(resolve, 5000); // time to breathe for db
|
setTimeout(resolve, 10000); // time to breathe for db
|
||||||
});
|
});
|
||||||
|
|
||||||
const secret = await getSecretByNameV2({
|
const secret = await getSecretByNameV2({
|
||||||
@ -173,9 +173,9 @@ describe.each([{ secretPath: "/" }, { secretPath: "/deep" }])(
|
|||||||
value: "prod-value"
|
value: "prod-value"
|
||||||
});
|
});
|
||||||
|
|
||||||
// wait for 5 second for replication to finish
|
// wait for 10 second for replication to finish
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
setTimeout(resolve, 5000); // time to breathe for db
|
setTimeout(resolve, 10000); // time to breathe for db
|
||||||
});
|
});
|
||||||
|
|
||||||
const secret = await getSecretByNameV2({
|
const secret = await getSecretByNameV2({
|
||||||
@ -343,9 +343,9 @@ describe.each([{ path: "/" }, { path: "/deep" }])(
|
|||||||
value: "prod-value"
|
value: "prod-value"
|
||||||
});
|
});
|
||||||
|
|
||||||
// wait for 5 second for replication to finish
|
// wait for 10 second for replication to finish
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
setTimeout(resolve, 5000); // time to breathe for db
|
setTimeout(resolve, 10000); // time to breathe for db
|
||||||
});
|
});
|
||||||
|
|
||||||
const secret = await getSecretByNameV2({
|
const secret = await getSecretByNameV2({
|
||||||
|
86
backend/e2e-test/routes/v3/secret-recursive.spec.ts
Normal file
86
backend/e2e-test/routes/v3/secret-recursive.spec.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import { createFolder, deleteFolder } from "e2e-test/testUtils/folders";
|
||||||
|
import { createSecretV2, deleteSecretV2, getSecretsV2 } from "e2e-test/testUtils/secrets";
|
||||||
|
|
||||||
|
import { seedData1 } from "@app/db/seed-data";
|
||||||
|
|
||||||
|
describe("Secret Recursive Testing", async () => {
|
||||||
|
const projectId = seedData1.projectV3.id;
|
||||||
|
const folderAndSecretNames = [
|
||||||
|
{ name: "deep1", path: "/", expectedSecretCount: 4 },
|
||||||
|
{ name: "deep21", path: "/deep1", expectedSecretCount: 2 },
|
||||||
|
{ name: "deep3", path: "/deep1/deep2", expectedSecretCount: 1 },
|
||||||
|
{ name: "deep22", path: "/deep2", expectedSecretCount: 1 }
|
||||||
|
];
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
const rootFolderIds: string[] = [];
|
||||||
|
for (const folder of folderAndSecretNames) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
const createdFolder = await createFolder({
|
||||||
|
authToken: jwtAuthToken,
|
||||||
|
environmentSlug: "prod",
|
||||||
|
workspaceId: projectId,
|
||||||
|
secretPath: folder.path,
|
||||||
|
name: folder.name
|
||||||
|
});
|
||||||
|
|
||||||
|
if (folder.path === "/") {
|
||||||
|
rootFolderIds.push(createdFolder.id);
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await createSecretV2({
|
||||||
|
secretPath: folder.path,
|
||||||
|
authToken: jwtAuthToken,
|
||||||
|
environmentSlug: "prod",
|
||||||
|
workspaceId: projectId,
|
||||||
|
key: folder.name,
|
||||||
|
value: folder.name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return async () => {
|
||||||
|
await Promise.all(
|
||||||
|
rootFolderIds.map((id) =>
|
||||||
|
deleteFolder({
|
||||||
|
authToken: jwtAuthToken,
|
||||||
|
secretPath: "/",
|
||||||
|
id,
|
||||||
|
workspaceId: projectId,
|
||||||
|
environmentSlug: "prod"
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
await deleteSecretV2({
|
||||||
|
authToken: jwtAuthToken,
|
||||||
|
secretPath: "/",
|
||||||
|
workspaceId: projectId,
|
||||||
|
environmentSlug: "prod",
|
||||||
|
key: folderAndSecretNames[0].name
|
||||||
|
});
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each(folderAndSecretNames)("$path recursive secret fetching", async ({ path, expectedSecretCount }) => {
|
||||||
|
const secrets = await getSecretsV2({
|
||||||
|
authToken: jwtAuthToken,
|
||||||
|
secretPath: path,
|
||||||
|
workspaceId: projectId,
|
||||||
|
environmentSlug: "prod",
|
||||||
|
recursive: true
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(secrets.secrets.length).toEqual(expectedSecretCount);
|
||||||
|
expect(secrets.secrets.sort((a, b) => a.secretKey.localeCompare(b.secretKey))).toEqual(
|
||||||
|
folderAndSecretNames
|
||||||
|
.filter((el) => el.path.startsWith(path))
|
||||||
|
.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
.map((el) =>
|
||||||
|
expect.objectContaining({
|
||||||
|
secretKey: el.name,
|
||||||
|
secretValue: el.name
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -56,7 +56,10 @@ describe("Secret expansion", () => {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
await Promise.all(secrets.map((el) => createSecretV2(el)));
|
for (const secret of secrets) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await createSecretV2(secret);
|
||||||
|
}
|
||||||
|
|
||||||
const expandedSecret = await getSecretByNameV2({
|
const expandedSecret = await getSecretByNameV2({
|
||||||
environmentSlug: seedData1.environment.slug,
|
environmentSlug: seedData1.environment.slug,
|
||||||
@ -123,7 +126,10 @@ describe("Secret expansion", () => {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
await Promise.all(secrets.map((el) => createSecretV2(el)));
|
for (const secret of secrets) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await createSecretV2(secret);
|
||||||
|
}
|
||||||
|
|
||||||
const expandedSecret = await getSecretByNameV2({
|
const expandedSecret = await getSecretByNameV2({
|
||||||
environmentSlug: seedData1.environment.slug,
|
environmentSlug: seedData1.environment.slug,
|
||||||
@ -190,7 +196,11 @@ describe("Secret expansion", () => {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
await Promise.all(secrets.map((el) => createSecretV2(el)));
|
for (const secret of secrets) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await createSecretV2(secret);
|
||||||
|
}
|
||||||
|
|
||||||
const secretImportFromProdToDev = await createSecretImport({
|
const secretImportFromProdToDev = await createSecretImport({
|
||||||
environmentSlug: seedData1.environment.slug,
|
environmentSlug: seedData1.environment.slug,
|
||||||
workspaceId: projectId,
|
workspaceId: projectId,
|
||||||
@ -275,7 +285,11 @@ describe("Secret expansion", () => {
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
await Promise.all(secrets.map((el) => createSecretV2(el)));
|
for (const secret of secrets) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await createSecretV2(secret);
|
||||||
|
}
|
||||||
|
|
||||||
const secretImportFromProdToDev = await createSecretImport({
|
const secretImportFromProdToDev = await createSecretImport({
|
||||||
environmentSlug: seedData1.environment.slug,
|
environmentSlug: seedData1.environment.slug,
|
||||||
workspaceId: projectId,
|
workspaceId: projectId,
|
||||||
|
@ -97,6 +97,7 @@ export const getSecretsV2 = async (dto: {
|
|||||||
environmentSlug: string;
|
environmentSlug: string;
|
||||||
secretPath: string;
|
secretPath: string;
|
||||||
authToken: string;
|
authToken: string;
|
||||||
|
recursive?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const getSecretsResponse = await testServer.inject({
|
const getSecretsResponse = await testServer.inject({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@ -109,7 +110,8 @@ export const getSecretsV2 = async (dto: {
|
|||||||
environment: dto.environmentSlug,
|
environment: dto.environmentSlug,
|
||||||
secretPath: dto.secretPath,
|
secretPath: dto.secretPath,
|
||||||
expandSecretReferences: "true",
|
expandSecretReferences: "true",
|
||||||
include_imports: "true"
|
include_imports: "true",
|
||||||
|
recursive: String(dto.recursive || false)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
expect(getSecretsResponse.statusCode).toBe(200);
|
expect(getSecretsResponse.statusCode).toBe(200);
|
||||||
|
@ -16,6 +16,7 @@ import { initDbConnection } from "@app/db";
|
|||||||
import { queueServiceFactory } from "@app/queue";
|
import { queueServiceFactory } from "@app/queue";
|
||||||
import { keyStoreFactory } from "@app/keystore/keystore";
|
import { keyStoreFactory } from "@app/keystore/keystore";
|
||||||
import { Redis } from "ioredis";
|
import { Redis } from "ioredis";
|
||||||
|
import { initializeHsmModule } from "@app/ee/services/hsm/hsm-fns";
|
||||||
|
|
||||||
dotenv.config({ path: path.join(__dirname, "../../.env.test"), debug: true });
|
dotenv.config({ path: path.join(__dirname, "../../.env.test"), debug: true });
|
||||||
export default {
|
export default {
|
||||||
@ -52,9 +53,14 @@ export default {
|
|||||||
extension: "ts"
|
extension: "ts"
|
||||||
});
|
});
|
||||||
const smtp = mockSmtpServer();
|
const smtp = mockSmtpServer();
|
||||||
const queue = queueServiceFactory(cfg.REDIS_URL);
|
const queue = queueServiceFactory(cfg.REDIS_URL, { dbConnectionUrl: cfg.DB_CONNECTION_URI });
|
||||||
const keyStore = keyStoreFactory(cfg.REDIS_URL);
|
const keyStore = keyStoreFactory(cfg.REDIS_URL);
|
||||||
const server = await main({ db, smtp, logger, queue, keyStore });
|
|
||||||
|
const hsmModule = initializeHsmModule();
|
||||||
|
hsmModule.initialize();
|
||||||
|
|
||||||
|
const server = await main({ db, smtp, logger, queue, keyStore, hsmModule: hsmModule.getModule(), redis });
|
||||||
|
|
||||||
// @ts-expect-error type
|
// @ts-expect-error type
|
||||||
globalThis.testServer = server;
|
globalThis.testServer = server;
|
||||||
// @ts-expect-error type
|
// @ts-expect-error type
|
||||||
|
5354
backend/package-lock.json
generated
5354
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -44,12 +44,13 @@
|
|||||||
"test:e2e-watch": "vitest -c vitest.e2e.config.ts --bail=1",
|
"test:e2e-watch": "vitest -c vitest.e2e.config.ts --bail=1",
|
||||||
"test:e2e-coverage": "vitest run --coverage -c vitest.e2e.config.ts",
|
"test:e2e-coverage": "vitest run --coverage -c vitest.e2e.config.ts",
|
||||||
"generate:component": "tsx ./scripts/create-backend-file.ts",
|
"generate:component": "tsx ./scripts/create-backend-file.ts",
|
||||||
"generate:schema": "tsx ./scripts/generate-schema-types.ts",
|
"generate:schema": "tsx ./scripts/generate-schema-types.ts && eslint --fix --ext ts ./src/db/schemas",
|
||||||
"auditlog-migration:latest": "knex --knexfile ./src/db/auditlog-knexfile.ts --client pg migrate:latest",
|
"auditlog-migration:latest": "knex --knexfile ./src/db/auditlog-knexfile.ts --client pg migrate:latest",
|
||||||
"auditlog-migration:up": "knex --knexfile ./src/db/auditlog-knexfile.ts --client pg migrate:up",
|
"auditlog-migration:up": "knex --knexfile ./src/db/auditlog-knexfile.ts --client pg migrate:up",
|
||||||
"auditlog-migration:down": "knex --knexfile ./src/db/auditlog-knexfile.ts --client pg migrate:down",
|
"auditlog-migration:down": "knex --knexfile ./src/db/auditlog-knexfile.ts --client pg migrate:down",
|
||||||
"auditlog-migration:list": "knex --knexfile ./src/db/auditlog-knexfile.ts --client pg migrate:list",
|
"auditlog-migration:list": "knex --knexfile ./src/db/auditlog-knexfile.ts --client pg migrate:list",
|
||||||
"auditlog-migration:status": "knex --knexfile ./src/db/auditlog-knexfile.ts --client pg migrate:status",
|
"auditlog-migration:status": "knex --knexfile ./src/db/auditlog-knexfile.ts --client pg migrate:status",
|
||||||
|
"auditlog-migration:unlock": "knex --knexfile ./src/db/auditlog-knexfile.ts migrate:unlock",
|
||||||
"auditlog-migration:rollback": "knex --knexfile ./src/db/auditlog-knexfile.ts migrate:rollback",
|
"auditlog-migration:rollback": "knex --knexfile ./src/db/auditlog-knexfile.ts migrate:rollback",
|
||||||
"migration:new": "tsx ./scripts/create-migration.ts",
|
"migration:new": "tsx ./scripts/create-migration.ts",
|
||||||
"migration:up": "npm run auditlog-migration:up && knex --knexfile ./src/db/knexfile.ts --client pg migrate:up",
|
"migration:up": "npm run auditlog-migration:up && knex --knexfile ./src/db/knexfile.ts --client pg migrate:up",
|
||||||
@ -58,6 +59,8 @@
|
|||||||
"migration:latest": "npm run auditlog-migration:latest && knex --knexfile ./src/db/knexfile.ts --client pg migrate:latest",
|
"migration:latest": "npm run auditlog-migration:latest && knex --knexfile ./src/db/knexfile.ts --client pg migrate:latest",
|
||||||
"migration:status": "npm run auditlog-migration:status && knex --knexfile ./src/db/knexfile.ts --client pg migrate:status",
|
"migration:status": "npm run auditlog-migration:status && knex --knexfile ./src/db/knexfile.ts --client pg migrate:status",
|
||||||
"migration:rollback": "npm run auditlog-migration:rollback && knex --knexfile ./src/db/knexfile.ts migrate:rollback",
|
"migration:rollback": "npm run auditlog-migration:rollback && knex --knexfile ./src/db/knexfile.ts migrate:rollback",
|
||||||
|
"migration:unlock": "npm run auditlog-migration:unlock && knex --knexfile ./src/db/knexfile.ts migrate:unlock",
|
||||||
|
"migrate:org": "tsx ./scripts/migrate-organization.ts",
|
||||||
"seed:new": "tsx ./scripts/create-seed-file.ts",
|
"seed:new": "tsx ./scripts/create-seed-file.ts",
|
||||||
"seed": "knex --knexfile ./src/db/knexfile.ts --client pg seed:run",
|
"seed": "knex --knexfile ./src/db/knexfile.ts --client pg seed:run",
|
||||||
"db:reset": "npm run migration:rollback -- --all && npm run migration:latest"
|
"db:reset": "npm run migration:rollback -- --all && npm run migration:latest"
|
||||||
@ -83,6 +86,7 @@
|
|||||||
"@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",
|
||||||
|
"@types/pkcs11js": "^1.0.4",
|
||||||
"@types/prompt-sync": "^4.2.3",
|
"@types/prompt-sync": "^4.2.3",
|
||||||
"@types/resolve": "^1.20.6",
|
"@types/resolve": "^1.20.6",
|
||||||
"@types/safe-regex": "^1.1.6",
|
"@types/safe-regex": "^1.1.6",
|
||||||
@ -128,21 +132,32 @@
|
|||||||
"@fastify/multipart": "8.3.0",
|
"@fastify/multipart": "8.3.0",
|
||||||
"@fastify/passport": "^2.4.0",
|
"@fastify/passport": "^2.4.0",
|
||||||
"@fastify/rate-limit": "^9.0.0",
|
"@fastify/rate-limit": "^9.0.0",
|
||||||
|
"@fastify/request-context": "^5.1.0",
|
||||||
"@fastify/session": "^10.7.0",
|
"@fastify/session": "^10.7.0",
|
||||||
|
"@fastify/static": "^7.0.4",
|
||||||
"@fastify/swagger": "^8.14.0",
|
"@fastify/swagger": "^8.14.0",
|
||||||
"@fastify/swagger-ui": "^2.1.0",
|
"@fastify/swagger-ui": "^2.1.0",
|
||||||
|
"@google-cloud/kms": "^4.5.0",
|
||||||
"@node-saml/passport-saml": "^4.0.4",
|
"@node-saml/passport-saml": "^4.0.4",
|
||||||
"@octokit/auth-app": "^7.1.1",
|
"@octokit/auth-app": "^7.1.1",
|
||||||
"@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",
|
||||||
|
"@octopusdeploy/api-client": "^3.4.1",
|
||||||
|
"@opentelemetry/api": "^1.9.0",
|
||||||
|
"@opentelemetry/auto-instrumentations-node": "^0.53.0",
|
||||||
|
"@opentelemetry/exporter-metrics-otlp-proto": "^0.55.0",
|
||||||
|
"@opentelemetry/exporter-prometheus": "^0.55.0",
|
||||||
|
"@opentelemetry/instrumentation": "^0.55.0",
|
||||||
|
"@opentelemetry/resources": "^1.28.0",
|
||||||
|
"@opentelemetry/sdk-metrics": "^1.28.0",
|
||||||
|
"@opentelemetry/semantic-conventions": "^1.27.0",
|
||||||
"@peculiar/asn1-schema": "^2.3.8",
|
"@peculiar/asn1-schema": "^2.3.8",
|
||||||
"@peculiar/x509": "^1.12.1",
|
"@peculiar/x509": "^1.12.1",
|
||||||
"@serdnam/pino-cloudwatch-transport": "^1.0.4",
|
"@serdnam/pino-cloudwatch-transport": "^1.0.4",
|
||||||
"@sindresorhus/slugify": "1.1.0",
|
"@sindresorhus/slugify": "1.1.0",
|
||||||
"@slack/oauth": "^3.0.1",
|
"@slack/oauth": "^3.0.1",
|
||||||
"@slack/web-api": "^7.3.4",
|
"@slack/web-api": "^7.3.4",
|
||||||
"@team-plain/typescript-sdk": "^4.6.1",
|
|
||||||
"@ucast/mongo2js": "^1.3.4",
|
"@ucast/mongo2js": "^1.3.4",
|
||||||
"ajv": "^8.12.0",
|
"ajv": "^8.12.0",
|
||||||
"argon2": "^0.31.2",
|
"argon2": "^0.31.2",
|
||||||
@ -155,11 +170,12 @@
|
|||||||
"connect-redis": "^7.1.1",
|
"connect-redis": "^7.1.1",
|
||||||
"cron": "^3.1.7",
|
"cron": "^3.1.7",
|
||||||
"dotenv": "^16.4.1",
|
"dotenv": "^16.4.1",
|
||||||
"fastify": "^4.26.0",
|
"fastify": "^4.28.1",
|
||||||
"fastify-plugin": "^4.5.1",
|
"fastify-plugin": "^4.5.1",
|
||||||
"google-auth-library": "^9.9.0",
|
"google-auth-library": "^9.9.0",
|
||||||
"googleapis": "^137.1.0",
|
"googleapis": "^137.1.0",
|
||||||
"handlebars": "^4.7.8",
|
"handlebars": "^4.7.8",
|
||||||
|
"hdb": "^0.19.10",
|
||||||
"ioredis": "^5.3.2",
|
"ioredis": "^5.3.2",
|
||||||
"jmespath": "^0.16.0",
|
"jmespath": "^0.16.0",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
@ -175,17 +191,21 @@
|
|||||||
"mysql2": "^3.9.8",
|
"mysql2": "^3.9.8",
|
||||||
"nanoid": "^3.3.4",
|
"nanoid": "^3.3.4",
|
||||||
"nodemailer": "^6.9.9",
|
"nodemailer": "^6.9.9",
|
||||||
|
"odbc": "^2.4.9",
|
||||||
"openid-client": "^5.6.5",
|
"openid-client": "^5.6.5",
|
||||||
"ora": "^7.0.1",
|
"ora": "^7.0.1",
|
||||||
"oracledb": "^6.4.0",
|
"oracledb": "^6.4.0",
|
||||||
|
"otplib": "^12.0.1",
|
||||||
"passport-github": "^1.1.0",
|
"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",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
|
"pg-boss": "^10.1.5",
|
||||||
"pg-query-stream": "^4.5.3",
|
"pg-query-stream": "^4.5.3",
|
||||||
"picomatch": "^3.0.1",
|
"picomatch": "^3.0.1",
|
||||||
"pino": "^8.16.2",
|
"pino": "^8.16.2",
|
||||||
|
"pkcs11js": "^2.1.6",
|
||||||
"pkijs": "^3.2.4",
|
"pkijs": "^3.2.4",
|
||||||
"posthog-node": "^3.6.2",
|
"posthog-node": "^3.6.2",
|
||||||
"probot": "^13.3.8",
|
"probot": "^13.3.8",
|
||||||
@ -194,6 +214,7 @@
|
|||||||
"scim2-parse-filter": "^0.2.10",
|
"scim2-parse-filter": "^0.2.10",
|
||||||
"sjcl": "^1.0.8",
|
"sjcl": "^1.0.8",
|
||||||
"smee-client": "^2.0.0",
|
"smee-client": "^2.0.0",
|
||||||
|
"snowflake-sdk": "^1.14.0",
|
||||||
"tedious": "^18.2.1",
|
"tedious": "^18.2.1",
|
||||||
"tweetnacl": "^1.0.3",
|
"tweetnacl": "^1.0.3",
|
||||||
"tweetnacl-util": "^0.15.1",
|
"tweetnacl-util": "^0.15.1",
|
||||||
|
103
backend/scripts/migrate-organization.ts
Normal file
103
backend/scripts/migrate-organization.ts
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
import promptSync from "prompt-sync";
|
||||||
|
import { execSync } from "child_process";
|
||||||
|
import path from "path";
|
||||||
|
import { existsSync } from "fs";
|
||||||
|
|
||||||
|
const prompt = promptSync({
|
||||||
|
sigint: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const sanitizeInputParam = (value: string) => {
|
||||||
|
// Escape double quotes and wrap the entire value in double quotes
|
||||||
|
if (value) {
|
||||||
|
return `"${value.replace(/"/g, '\\"')}"`;
|
||||||
|
}
|
||||||
|
return '""';
|
||||||
|
};
|
||||||
|
|
||||||
|
const exportDb = () => {
|
||||||
|
const exportHost = sanitizeInputParam(prompt("Enter your Postgres Host to migrate from: "));
|
||||||
|
const exportPort = sanitizeInputParam(
|
||||||
|
prompt("Enter your Postgres Port to migrate from [Default = 5432]: ") ?? "5432"
|
||||||
|
);
|
||||||
|
const exportUser = sanitizeInputParam(
|
||||||
|
prompt("Enter your Postgres User to migrate from: [Default = infisical]: ") ?? "infisical"
|
||||||
|
);
|
||||||
|
const exportPassword = sanitizeInputParam(prompt("Enter your Postgres Password to migrate from: "));
|
||||||
|
const exportDatabase = sanitizeInputParam(
|
||||||
|
prompt("Enter your Postgres Database to migrate from [Default = infisical]: ") ?? "infisical"
|
||||||
|
);
|
||||||
|
|
||||||
|
// we do not include the audit_log and secret_sharing entries
|
||||||
|
execSync(
|
||||||
|
`PGDATABASE=${exportDatabase} PGPASSWORD=${exportPassword} PGHOST=${exportHost} PGPORT=${exportPort} PGUSER=${exportUser} pg_dump -Fc infisical --exclude-table-data="secret_sharing" --exclude-table-data="audit_log*" > ${path.join(
|
||||||
|
__dirname,
|
||||||
|
"../src/db/backup.dump"
|
||||||
|
)}`,
|
||||||
|
{ stdio: "inherit" }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const importDbForOrg = () => {
|
||||||
|
const importHost = sanitizeInputParam(prompt("Enter your Postgres Host to migrate to: "));
|
||||||
|
const importPort = sanitizeInputParam(prompt("Enter your Postgres Port to migrate to [Default = 5432]: ") ?? "5432");
|
||||||
|
const importUser = sanitizeInputParam(
|
||||||
|
prompt("Enter your Postgres User to migrate to: [Default = infisical]: ") ?? "infisical"
|
||||||
|
);
|
||||||
|
const importPassword = sanitizeInputParam(prompt("Enter your Postgres Password to migrate to: "));
|
||||||
|
const importDatabase = sanitizeInputParam(
|
||||||
|
prompt("Enter your Postgres Database to migrate to [Default = infisical]: ") ?? "infisical"
|
||||||
|
);
|
||||||
|
const orgId = sanitizeInputParam(prompt("Enter the organization ID to migrate: "));
|
||||||
|
|
||||||
|
if (!existsSync(path.join(__dirname, "../src/db/backup.dump"))) {
|
||||||
|
console.log("File not found, please export the database first.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
execSync(
|
||||||
|
`PGDATABASE=${importDatabase} PGPASSWORD=${importPassword} PGHOST=${importHost} PGPORT=${importPort} PGUSER=${importUser} pg_restore -d ${importDatabase} --verbose ${path.join(
|
||||||
|
__dirname,
|
||||||
|
"../src/db/backup.dump"
|
||||||
|
)}`,
|
||||||
|
{ maxBuffer: 1024 * 1024 * 4096 }
|
||||||
|
);
|
||||||
|
|
||||||
|
execSync(
|
||||||
|
`PGDATABASE=${importDatabase} PGPASSWORD=${importPassword} PGHOST=${importHost} PGPORT=${importPort} PGUSER=${importUser} psql -c "DELETE FROM public.organizations WHERE id != '${orgId}'"`
|
||||||
|
);
|
||||||
|
|
||||||
|
// delete global/instance-level resources not relevant to the organization to migrate
|
||||||
|
// users
|
||||||
|
execSync(
|
||||||
|
`PGDATABASE=${importDatabase} PGPASSWORD=${importPassword} PGHOST=${importHost} PGPORT=${importPort} PGUSER=${importUser} psql -c 'DELETE FROM users WHERE users.id NOT IN (SELECT org_memberships."userId" FROM org_memberships)'`
|
||||||
|
);
|
||||||
|
|
||||||
|
// identities
|
||||||
|
execSync(
|
||||||
|
`PGDATABASE=${importDatabase} PGPASSWORD=${importPassword} PGHOST=${importHost} PGPORT=${importPort} PGUSER=${importUser} psql -c 'DELETE FROM identities WHERE id NOT IN (SELECT "identityId" FROM identity_org_memberships)'`
|
||||||
|
);
|
||||||
|
|
||||||
|
// reset slack configuration in superAdmin
|
||||||
|
execSync(
|
||||||
|
`PGDATABASE=${importDatabase} PGPASSWORD=${importPassword} PGHOST=${importHost} PGPORT=${importPort} PGUSER=${importUser} psql -c 'UPDATE super_admin SET "encryptedSlackClientId" = null, "encryptedSlackClientSecret" = null'`
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log("Organization migrated successfully.");
|
||||||
|
};
|
||||||
|
|
||||||
|
const main = () => {
|
||||||
|
const action = prompt(
|
||||||
|
"Enter the action to perform\n 1. Export from existing instance.\n 2. Import org to instance.\n \n Action: "
|
||||||
|
);
|
||||||
|
if (action === "1") {
|
||||||
|
exportDb();
|
||||||
|
} else if (action === "2") {
|
||||||
|
importDbForOrg();
|
||||||
|
} else {
|
||||||
|
console.log("Invalid action");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
main();
|
7
backend/src/@types/fastify-request-context.d.ts
vendored
Normal file
7
backend/src/@types/fastify-request-context.d.ts
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import "@fastify/request-context";
|
||||||
|
|
||||||
|
declare module "@fastify/request-context" {
|
||||||
|
interface RequestContextData {
|
||||||
|
reqId: string;
|
||||||
|
}
|
||||||
|
}
|
4
backend/src/@types/fastify-zod.d.ts
vendored
4
backend/src/@types/fastify-zod.d.ts
vendored
@ -1,6 +1,6 @@
|
|||||||
import { FastifyInstance, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault } from "fastify";
|
import { FastifyInstance, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault } from "fastify";
|
||||||
import { Logger } from "pino";
|
|
||||||
|
|
||||||
|
import { CustomLogger } from "@app/lib/logger/logger";
|
||||||
import { ZodTypeProvider } from "@app/server/plugins/fastify-zod";
|
import { ZodTypeProvider } from "@app/server/plugins/fastify-zod";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
@ -8,7 +8,7 @@ declare global {
|
|||||||
RawServerDefault,
|
RawServerDefault,
|
||||||
RawRequestDefaultExpression<RawServerDefault>,
|
RawRequestDefaultExpression<RawServerDefault>,
|
||||||
RawReplyDefaultExpression<RawServerDefault>,
|
RawReplyDefaultExpression<RawServerDefault>,
|
||||||
Readonly<Logger>,
|
Readonly<CustomLogger>,
|
||||||
ZodTypeProvider
|
ZodTypeProvider
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
25
backend/src/@types/fastify.d.ts
vendored
25
backend/src/@types/fastify.d.ts
vendored
@ -1,5 +1,7 @@
|
|||||||
import "fastify";
|
import "fastify";
|
||||||
|
|
||||||
|
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";
|
||||||
@ -13,10 +15,12 @@ import { TDynamicSecretLeaseServiceFactory } from "@app/ee/services/dynamic-secr
|
|||||||
import { TExternalKmsServiceFactory } from "@app/ee/services/external-kms/external-kms-service";
|
import { TExternalKmsServiceFactory } from "@app/ee/services/external-kms/external-kms-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 { TLdapConfigServiceFactory } from "@app/ee/services/ldap-config/ldap-config-service";
|
import { TLdapConfigServiceFactory } from "@app/ee/services/ldap-config/ldap-config-service";
|
||||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
import { TOidcConfigServiceFactory } from "@app/ee/services/oidc/oidc-config-service";
|
import { TOidcConfigServiceFactory } from "@app/ee/services/oidc/oidc-config-service";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
|
import { TProjectTemplateServiceFactory } from "@app/ee/services/project-template/project-template-service";
|
||||||
import { TProjectUserAdditionalPrivilegeServiceFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-service";
|
import { TProjectUserAdditionalPrivilegeServiceFactory } from "@app/ee/services/project-user-additional-privilege/project-user-additional-privilege-service";
|
||||||
import { TRateLimitServiceFactory } from "@app/ee/services/rate-limit/rate-limit-service";
|
import { TRateLimitServiceFactory } from "@app/ee/services/rate-limit/rate-limit-service";
|
||||||
import { RateLimitConfiguration } from "@app/ee/services/rate-limit/rate-limit-types";
|
import { RateLimitConfiguration } from "@app/ee/services/rate-limit/rate-limit-types";
|
||||||
@ -27,9 +31,12 @@ import { TSecretApprovalRequestServiceFactory } from "@app/ee/services/secret-ap
|
|||||||
import { TSecretRotationServiceFactory } from "@app/ee/services/secret-rotation/secret-rotation-service";
|
import { TSecretRotationServiceFactory } from "@app/ee/services/secret-rotation/secret-rotation-service";
|
||||||
import { TSecretScanningServiceFactory } from "@app/ee/services/secret-scanning/secret-scanning-service";
|
import { TSecretScanningServiceFactory } from "@app/ee/services/secret-scanning/secret-scanning-service";
|
||||||
import { TSecretSnapshotServiceFactory } from "@app/ee/services/secret-snapshot/secret-snapshot-service";
|
import { TSecretSnapshotServiceFactory } from "@app/ee/services/secret-snapshot/secret-snapshot-service";
|
||||||
|
import { TSshCertificateAuthorityServiceFactory } from "@app/ee/services/ssh/ssh-certificate-authority-service";
|
||||||
|
import { TSshCertificateTemplateServiceFactory } from "@app/ee/services/ssh-certificate-template/ssh-certificate-template-service";
|
||||||
import { TTrustedIpServiceFactory } from "@app/ee/services/trusted-ip/trusted-ip-service";
|
import { TTrustedIpServiceFactory } from "@app/ee/services/trusted-ip/trusted-ip-service";
|
||||||
import { TAuthMode } from "@app/server/plugins/auth/inject-identity";
|
import { TAuthMode } from "@app/server/plugins/auth/inject-identity";
|
||||||
import { TApiKeyServiceFactory } from "@app/services/api-key/api-key-service";
|
import { TApiKeyServiceFactory } from "@app/services/api-key/api-key-service";
|
||||||
|
import { TAppConnectionServiceFactory } from "@app/services/app-connection/app-connection-service";
|
||||||
import { TAuthLoginFactory } from "@app/services/auth/auth-login-service";
|
import { TAuthLoginFactory } from "@app/services/auth/auth-login-service";
|
||||||
import { TAuthPasswordFactory } from "@app/services/auth/auth-password-service";
|
import { TAuthPasswordFactory } from "@app/services/auth/auth-password-service";
|
||||||
import { TAuthSignupFactory } from "@app/services/auth/auth-signup-service";
|
import { TAuthSignupFactory } from "@app/services/auth/auth-signup-service";
|
||||||
@ -42,11 +49,13 @@ import { TCmekServiceFactory } from "@app/services/cmek/cmek-service";
|
|||||||
import { TExternalGroupOrgRoleMappingServiceFactory } from "@app/services/external-group-org-role-mapping/external-group-org-role-mapping-service";
|
import { TExternalGroupOrgRoleMappingServiceFactory } from "@app/services/external-group-org-role-mapping/external-group-org-role-mapping-service";
|
||||||
import { TExternalMigrationServiceFactory } from "@app/services/external-migration/external-migration-service";
|
import { TExternalMigrationServiceFactory } from "@app/services/external-migration/external-migration-service";
|
||||||
import { TGroupProjectServiceFactory } from "@app/services/group-project/group-project-service";
|
import { TGroupProjectServiceFactory } from "@app/services/group-project/group-project-service";
|
||||||
|
import { THsmServiceFactory } from "@app/services/hsm/hsm-service";
|
||||||
import { TIdentityServiceFactory } from "@app/services/identity/identity-service";
|
import { TIdentityServiceFactory } from "@app/services/identity/identity-service";
|
||||||
import { TIdentityAccessTokenServiceFactory } from "@app/services/identity-access-token/identity-access-token-service";
|
import { TIdentityAccessTokenServiceFactory } from "@app/services/identity-access-token/identity-access-token-service";
|
||||||
import { TIdentityAwsAuthServiceFactory } from "@app/services/identity-aws-auth/identity-aws-auth-service";
|
import { TIdentityAwsAuthServiceFactory } from "@app/services/identity-aws-auth/identity-aws-auth-service";
|
||||||
import { TIdentityAzureAuthServiceFactory } from "@app/services/identity-azure-auth/identity-azure-auth-service";
|
import { TIdentityAzureAuthServiceFactory } from "@app/services/identity-azure-auth/identity-azure-auth-service";
|
||||||
import { TIdentityGcpAuthServiceFactory } from "@app/services/identity-gcp-auth/identity-gcp-auth-service";
|
import { TIdentityGcpAuthServiceFactory } from "@app/services/identity-gcp-auth/identity-gcp-auth-service";
|
||||||
|
import { TIdentityJwtAuthServiceFactory } from "@app/services/identity-jwt-auth/identity-jwt-auth-service";
|
||||||
import { TIdentityKubernetesAuthServiceFactory } from "@app/services/identity-kubernetes-auth/identity-kubernetes-auth-service";
|
import { TIdentityKubernetesAuthServiceFactory } from "@app/services/identity-kubernetes-auth/identity-kubernetes-auth-service";
|
||||||
import { TIdentityOidcAuthServiceFactory } from "@app/services/identity-oidc-auth/identity-oidc-auth-service";
|
import { TIdentityOidcAuthServiceFactory } from "@app/services/identity-oidc-auth/identity-oidc-auth-service";
|
||||||
import { TIdentityProjectServiceFactory } from "@app/services/identity-project/identity-project-service";
|
import { TIdentityProjectServiceFactory } from "@app/services/identity-project/identity-project-service";
|
||||||
@ -71,11 +80,13 @@ import { TSecretFolderServiceFactory } from "@app/services/secret-folder/secret-
|
|||||||
import { TSecretImportServiceFactory } from "@app/services/secret-import/secret-import-service";
|
import { TSecretImportServiceFactory } from "@app/services/secret-import/secret-import-service";
|
||||||
import { TSecretReplicationServiceFactory } from "@app/services/secret-replication/secret-replication-service";
|
import { TSecretReplicationServiceFactory } from "@app/services/secret-replication/secret-replication-service";
|
||||||
import { TSecretSharingServiceFactory } from "@app/services/secret-sharing/secret-sharing-service";
|
import { TSecretSharingServiceFactory } from "@app/services/secret-sharing/secret-sharing-service";
|
||||||
|
import { TSecretSyncServiceFactory } from "@app/services/secret-sync/secret-sync-service";
|
||||||
import { TSecretTagServiceFactory } from "@app/services/secret-tag/secret-tag-service";
|
import { TSecretTagServiceFactory } from "@app/services/secret-tag/secret-tag-service";
|
||||||
import { TServiceTokenServiceFactory } from "@app/services/service-token/service-token-service";
|
import { TServiceTokenServiceFactory } from "@app/services/service-token/service-token-service";
|
||||||
import { TSlackServiceFactory } from "@app/services/slack/slack-service";
|
import { TSlackServiceFactory } from "@app/services/slack/slack-service";
|
||||||
import { TSuperAdminServiceFactory } from "@app/services/super-admin/super-admin-service";
|
import { TSuperAdminServiceFactory } from "@app/services/super-admin/super-admin-service";
|
||||||
import { TTelemetryServiceFactory } from "@app/services/telemetry/telemetry-service";
|
import { TTelemetryServiceFactory } from "@app/services/telemetry/telemetry-service";
|
||||||
|
import { TTotpServiceFactory } from "@app/services/totp/totp-service";
|
||||||
import { TUserDALFactory } from "@app/services/user/user-dal";
|
import { TUserDALFactory } from "@app/services/user/user-dal";
|
||||||
import { TUserServiceFactory } from "@app/services/user/user-service";
|
import { TUserServiceFactory } from "@app/services/user/user-service";
|
||||||
import { TUserEngagementServiceFactory } from "@app/services/user-engagement/user-engagement-service";
|
import { TUserEngagementServiceFactory } from "@app/services/user-engagement/user-engagement-service";
|
||||||
@ -83,6 +94,10 @@ import { TWebhookServiceFactory } from "@app/services/webhook/webhook-service";
|
|||||||
import { TWorkflowIntegrationServiceFactory } from "@app/services/workflow-integration/workflow-integration-service";
|
import { TWorkflowIntegrationServiceFactory } from "@app/services/workflow-integration/workflow-integration-service";
|
||||||
|
|
||||||
declare module "fastify" {
|
declare module "fastify" {
|
||||||
|
interface Session {
|
||||||
|
callbackPort: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface FastifyRequest {
|
interface FastifyRequest {
|
||||||
realIp: string;
|
realIp: string;
|
||||||
// used for mfa session authentication
|
// used for mfa session authentication
|
||||||
@ -111,6 +126,7 @@ declare module "fastify" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface FastifyInstance {
|
interface FastifyInstance {
|
||||||
|
redis: Redis;
|
||||||
services: {
|
services: {
|
||||||
login: TAuthLoginFactory;
|
login: TAuthLoginFactory;
|
||||||
password: TAuthPasswordFactory;
|
password: TAuthPasswordFactory;
|
||||||
@ -151,6 +167,7 @@ declare module "fastify" {
|
|||||||
identityAwsAuth: TIdentityAwsAuthServiceFactory;
|
identityAwsAuth: TIdentityAwsAuthServiceFactory;
|
||||||
identityAzureAuth: TIdentityAzureAuthServiceFactory;
|
identityAzureAuth: TIdentityAzureAuthServiceFactory;
|
||||||
identityOidcAuth: TIdentityOidcAuthServiceFactory;
|
identityOidcAuth: TIdentityOidcAuthServiceFactory;
|
||||||
|
identityJwtAuth: TIdentityJwtAuthServiceFactory;
|
||||||
accessApprovalPolicy: TAccessApprovalPolicyServiceFactory;
|
accessApprovalPolicy: TAccessApprovalPolicyServiceFactory;
|
||||||
accessApprovalRequest: TAccessApprovalRequestServiceFactory;
|
accessApprovalRequest: TAccessApprovalRequestServiceFactory;
|
||||||
secretApprovalPolicy: TSecretApprovalPolicyServiceFactory;
|
secretApprovalPolicy: TSecretApprovalPolicyServiceFactory;
|
||||||
@ -164,6 +181,8 @@ declare module "fastify" {
|
|||||||
auditLogStream: TAuditLogStreamServiceFactory;
|
auditLogStream: TAuditLogStreamServiceFactory;
|
||||||
certificate: TCertificateServiceFactory;
|
certificate: TCertificateServiceFactory;
|
||||||
certificateTemplate: TCertificateTemplateServiceFactory;
|
certificateTemplate: TCertificateTemplateServiceFactory;
|
||||||
|
sshCertificateAuthority: TSshCertificateAuthorityServiceFactory;
|
||||||
|
sshCertificateTemplate: TSshCertificateTemplateServiceFactory;
|
||||||
certificateAuthority: TCertificateAuthorityServiceFactory;
|
certificateAuthority: TCertificateAuthorityServiceFactory;
|
||||||
certificateAuthorityCrl: TCertificateAuthorityCrlServiceFactory;
|
certificateAuthorityCrl: TCertificateAuthorityCrlServiceFactory;
|
||||||
certificateEst: TCertificateEstServiceFactory;
|
certificateEst: TCertificateEstServiceFactory;
|
||||||
@ -177,16 +196,22 @@ declare module "fastify" {
|
|||||||
dynamicSecretLease: TDynamicSecretLeaseServiceFactory;
|
dynamicSecretLease: TDynamicSecretLeaseServiceFactory;
|
||||||
projectUserAdditionalPrivilege: TProjectUserAdditionalPrivilegeServiceFactory;
|
projectUserAdditionalPrivilege: TProjectUserAdditionalPrivilegeServiceFactory;
|
||||||
identityProjectAdditionalPrivilege: TIdentityProjectAdditionalPrivilegeServiceFactory;
|
identityProjectAdditionalPrivilege: TIdentityProjectAdditionalPrivilegeServiceFactory;
|
||||||
|
identityProjectAdditionalPrivilegeV2: TIdentityProjectAdditionalPrivilegeV2ServiceFactory;
|
||||||
secretSharing: TSecretSharingServiceFactory;
|
secretSharing: TSecretSharingServiceFactory;
|
||||||
rateLimit: TRateLimitServiceFactory;
|
rateLimit: TRateLimitServiceFactory;
|
||||||
userEngagement: TUserEngagementServiceFactory;
|
userEngagement: TUserEngagementServiceFactory;
|
||||||
externalKms: TExternalKmsServiceFactory;
|
externalKms: TExternalKmsServiceFactory;
|
||||||
|
hsm: THsmServiceFactory;
|
||||||
orgAdmin: TOrgAdminServiceFactory;
|
orgAdmin: TOrgAdminServiceFactory;
|
||||||
slack: TSlackServiceFactory;
|
slack: TSlackServiceFactory;
|
||||||
workflowIntegration: TWorkflowIntegrationServiceFactory;
|
workflowIntegration: TWorkflowIntegrationServiceFactory;
|
||||||
cmek: TCmekServiceFactory;
|
cmek: TCmekServiceFactory;
|
||||||
migration: TExternalMigrationServiceFactory;
|
migration: TExternalMigrationServiceFactory;
|
||||||
externalGroupOrgRoleMapping: TExternalGroupOrgRoleMappingServiceFactory;
|
externalGroupOrgRoleMapping: TExternalGroupOrgRoleMappingServiceFactory;
|
||||||
|
projectTemplate: TProjectTemplateServiceFactory;
|
||||||
|
totp: TTotpServiceFactory;
|
||||||
|
appConnection: TAppConnectionServiceFactory;
|
||||||
|
secretSync: TSecretSyncServiceFactory;
|
||||||
};
|
};
|
||||||
// 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
|
||||||
|
4
backend/src/@types/hdb.d.ts
vendored
Normal file
4
backend/src/@types/hdb.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
declare module "hdb" {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Untyped, the function returns `any`.
|
||||||
|
function createClient(options): any;
|
||||||
|
}
|
84
backend/src/@types/knex.d.ts
vendored
84
backend/src/@types/knex.d.ts
vendored
@ -98,6 +98,9 @@ import {
|
|||||||
TIdentityGcpAuths,
|
TIdentityGcpAuths,
|
||||||
TIdentityGcpAuthsInsert,
|
TIdentityGcpAuthsInsert,
|
||||||
TIdentityGcpAuthsUpdate,
|
TIdentityGcpAuthsUpdate,
|
||||||
|
TIdentityJwtAuths,
|
||||||
|
TIdentityJwtAuthsInsert,
|
||||||
|
TIdentityJwtAuthsUpdate,
|
||||||
TIdentityKubernetesAuths,
|
TIdentityKubernetesAuths,
|
||||||
TIdentityKubernetesAuthsInsert,
|
TIdentityKubernetesAuthsInsert,
|
||||||
TIdentityKubernetesAuthsUpdate,
|
TIdentityKubernetesAuthsUpdate,
|
||||||
@ -199,7 +202,13 @@ import {
|
|||||||
TProjectSlackConfigs,
|
TProjectSlackConfigs,
|
||||||
TProjectSlackConfigsInsert,
|
TProjectSlackConfigsInsert,
|
||||||
TProjectSlackConfigsUpdate,
|
TProjectSlackConfigsUpdate,
|
||||||
|
TProjectSplitBackfillIds,
|
||||||
|
TProjectSplitBackfillIdsInsert,
|
||||||
|
TProjectSplitBackfillIdsUpdate,
|
||||||
TProjectsUpdate,
|
TProjectsUpdate,
|
||||||
|
TProjectTemplates,
|
||||||
|
TProjectTemplatesInsert,
|
||||||
|
TProjectTemplatesUpdate,
|
||||||
TProjectUserAdditionalPrivilege,
|
TProjectUserAdditionalPrivilege,
|
||||||
TProjectUserAdditionalPrivilegeInsert,
|
TProjectUserAdditionalPrivilegeInsert,
|
||||||
TProjectUserAdditionalPrivilegeUpdate,
|
TProjectUserAdditionalPrivilegeUpdate,
|
||||||
@ -209,6 +218,9 @@ import {
|
|||||||
TRateLimit,
|
TRateLimit,
|
||||||
TRateLimitInsert,
|
TRateLimitInsert,
|
||||||
TRateLimitUpdate,
|
TRateLimitUpdate,
|
||||||
|
TResourceMetadata,
|
||||||
|
TResourceMetadataInsert,
|
||||||
|
TResourceMetadataUpdate,
|
||||||
TSamlConfigs,
|
TSamlConfigs,
|
||||||
TSamlConfigsInsert,
|
TSamlConfigsInsert,
|
||||||
TSamlConfigsUpdate,
|
TSamlConfigsUpdate,
|
||||||
@ -308,9 +320,27 @@ import {
|
|||||||
TSlackIntegrations,
|
TSlackIntegrations,
|
||||||
TSlackIntegrationsInsert,
|
TSlackIntegrationsInsert,
|
||||||
TSlackIntegrationsUpdate,
|
TSlackIntegrationsUpdate,
|
||||||
|
TSshCertificateAuthorities,
|
||||||
|
TSshCertificateAuthoritiesInsert,
|
||||||
|
TSshCertificateAuthoritiesUpdate,
|
||||||
|
TSshCertificateAuthoritySecrets,
|
||||||
|
TSshCertificateAuthoritySecretsInsert,
|
||||||
|
TSshCertificateAuthoritySecretsUpdate,
|
||||||
|
TSshCertificateBodies,
|
||||||
|
TSshCertificateBodiesInsert,
|
||||||
|
TSshCertificateBodiesUpdate,
|
||||||
|
TSshCertificates,
|
||||||
|
TSshCertificatesInsert,
|
||||||
|
TSshCertificatesUpdate,
|
||||||
|
TSshCertificateTemplates,
|
||||||
|
TSshCertificateTemplatesInsert,
|
||||||
|
TSshCertificateTemplatesUpdate,
|
||||||
TSuperAdmin,
|
TSuperAdmin,
|
||||||
TSuperAdminInsert,
|
TSuperAdminInsert,
|
||||||
TSuperAdminUpdate,
|
TSuperAdminUpdate,
|
||||||
|
TTotpConfigs,
|
||||||
|
TTotpConfigsInsert,
|
||||||
|
TTotpConfigsUpdate,
|
||||||
TTrustedIps,
|
TTrustedIps,
|
||||||
TTrustedIpsInsert,
|
TTrustedIpsInsert,
|
||||||
TTrustedIpsUpdate,
|
TTrustedIpsUpdate,
|
||||||
@ -336,11 +366,13 @@ import {
|
|||||||
TWorkflowIntegrationsInsert,
|
TWorkflowIntegrationsInsert,
|
||||||
TWorkflowIntegrationsUpdate
|
TWorkflowIntegrationsUpdate
|
||||||
} from "@app/db/schemas";
|
} from "@app/db/schemas";
|
||||||
|
import { TAppConnections, TAppConnectionsInsert, TAppConnectionsUpdate } from "@app/db/schemas/app-connections";
|
||||||
import {
|
import {
|
||||||
TExternalGroupOrgRoleMappings,
|
TExternalGroupOrgRoleMappings,
|
||||||
TExternalGroupOrgRoleMappingsInsert,
|
TExternalGroupOrgRoleMappingsInsert,
|
||||||
TExternalGroupOrgRoleMappingsUpdate
|
TExternalGroupOrgRoleMappingsUpdate
|
||||||
} from "@app/db/schemas/external-group-org-role-mappings";
|
} from "@app/db/schemas/external-group-org-role-mappings";
|
||||||
|
import { TSecretSyncs, TSecretSyncsInsert, TSecretSyncsUpdate } from "@app/db/schemas/secret-syncs";
|
||||||
import {
|
import {
|
||||||
TSecretV2TagJunction,
|
TSecretV2TagJunction,
|
||||||
TSecretV2TagJunctionInsert,
|
TSecretV2TagJunctionInsert,
|
||||||
@ -366,6 +398,31 @@ declare module "knex/types/tables" {
|
|||||||
interface Tables {
|
interface Tables {
|
||||||
[TableName.Users]: KnexOriginal.CompositeTableType<TUsers, TUsersInsert, TUsersUpdate>;
|
[TableName.Users]: KnexOriginal.CompositeTableType<TUsers, TUsersInsert, TUsersUpdate>;
|
||||||
[TableName.Groups]: KnexOriginal.CompositeTableType<TGroups, TGroupsInsert, TGroupsUpdate>;
|
[TableName.Groups]: KnexOriginal.CompositeTableType<TGroups, TGroupsInsert, TGroupsUpdate>;
|
||||||
|
[TableName.SshCertificateAuthority]: KnexOriginal.CompositeTableType<
|
||||||
|
TSshCertificateAuthorities,
|
||||||
|
TSshCertificateAuthoritiesInsert,
|
||||||
|
TSshCertificateAuthoritiesUpdate
|
||||||
|
>;
|
||||||
|
[TableName.SshCertificateAuthoritySecret]: KnexOriginal.CompositeTableType<
|
||||||
|
TSshCertificateAuthoritySecrets,
|
||||||
|
TSshCertificateAuthoritySecretsInsert,
|
||||||
|
TSshCertificateAuthoritySecretsUpdate
|
||||||
|
>;
|
||||||
|
[TableName.SshCertificateTemplate]: KnexOriginal.CompositeTableType<
|
||||||
|
TSshCertificateTemplates,
|
||||||
|
TSshCertificateTemplatesInsert,
|
||||||
|
TSshCertificateTemplatesUpdate
|
||||||
|
>;
|
||||||
|
[TableName.SshCertificate]: KnexOriginal.CompositeTableType<
|
||||||
|
TSshCertificates,
|
||||||
|
TSshCertificatesInsert,
|
||||||
|
TSshCertificatesUpdate
|
||||||
|
>;
|
||||||
|
[TableName.SshCertificateBody]: KnexOriginal.CompositeTableType<
|
||||||
|
TSshCertificateBodies,
|
||||||
|
TSshCertificateBodiesInsert,
|
||||||
|
TSshCertificateBodiesUpdate
|
||||||
|
>;
|
||||||
[TableName.CertificateAuthority]: KnexOriginal.CompositeTableType<
|
[TableName.CertificateAuthority]: KnexOriginal.CompositeTableType<
|
||||||
TCertificateAuthorities,
|
TCertificateAuthorities,
|
||||||
TCertificateAuthoritiesInsert,
|
TCertificateAuthoritiesInsert,
|
||||||
@ -584,6 +641,11 @@ declare module "knex/types/tables" {
|
|||||||
TIdentityOidcAuthsInsert,
|
TIdentityOidcAuthsInsert,
|
||||||
TIdentityOidcAuthsUpdate
|
TIdentityOidcAuthsUpdate
|
||||||
>;
|
>;
|
||||||
|
[TableName.IdentityJwtAuth]: KnexOriginal.CompositeTableType<
|
||||||
|
TIdentityJwtAuths,
|
||||||
|
TIdentityJwtAuthsInsert,
|
||||||
|
TIdentityJwtAuthsUpdate
|
||||||
|
>;
|
||||||
[TableName.IdentityUaClientSecret]: KnexOriginal.CompositeTableType<
|
[TableName.IdentityUaClientSecret]: KnexOriginal.CompositeTableType<
|
||||||
TIdentityUaClientSecrets,
|
TIdentityUaClientSecrets,
|
||||||
TIdentityUaClientSecretsInsert,
|
TIdentityUaClientSecretsInsert,
|
||||||
@ -818,5 +880,27 @@ declare module "knex/types/tables" {
|
|||||||
TExternalGroupOrgRoleMappingsInsert,
|
TExternalGroupOrgRoleMappingsInsert,
|
||||||
TExternalGroupOrgRoleMappingsUpdate
|
TExternalGroupOrgRoleMappingsUpdate
|
||||||
>;
|
>;
|
||||||
|
[TableName.ProjectTemplates]: KnexOriginal.CompositeTableType<
|
||||||
|
TProjectTemplates,
|
||||||
|
TProjectTemplatesInsert,
|
||||||
|
TProjectTemplatesUpdate
|
||||||
|
>;
|
||||||
|
[TableName.TotpConfig]: KnexOriginal.CompositeTableType<TTotpConfigs, TTotpConfigsInsert, TTotpConfigsUpdate>;
|
||||||
|
[TableName.ProjectSplitBackfillIds]: KnexOriginal.CompositeTableType<
|
||||||
|
TProjectSplitBackfillIds,
|
||||||
|
TProjectSplitBackfillIdsInsert,
|
||||||
|
TProjectSplitBackfillIdsUpdate
|
||||||
|
>;
|
||||||
|
[TableName.ResourceMetadata]: KnexOriginal.CompositeTableType<
|
||||||
|
TResourceMetadata,
|
||||||
|
TResourceMetadataInsert,
|
||||||
|
TResourceMetadataUpdate
|
||||||
|
>;
|
||||||
|
[TableName.AppConnection]: KnexOriginal.CompositeTableType<
|
||||||
|
TAppConnections,
|
||||||
|
TAppConnectionsInsert,
|
||||||
|
TAppConnectionsUpdate
|
||||||
|
>;
|
||||||
|
[TableName.SecretSync]: KnexOriginal.CompositeTableType<TSecretSyncs, TSecretSyncsInsert, TSecretSyncsUpdate>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
t.string("integration").notNullable();
|
t.string("integration").notNullable();
|
||||||
t.string("teamId"); // vercel-specific
|
t.string("teamId"); // vercel-specific
|
||||||
t.string("url"); // for self hosted
|
t.string("url"); // for self-hosted
|
||||||
t.string("namespace"); // hashicorp specific
|
t.string("namespace"); // hashicorp specific
|
||||||
t.string("accountId"); // netlify
|
t.string("accountId"); // netlify
|
||||||
t.text("refreshCiphertext");
|
t.text("refreshCiphertext");
|
||||||
@ -36,7 +36,7 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
await knex.schema.createTable(TableName.Integration, (t) => {
|
await knex.schema.createTable(TableName.Integration, (t) => {
|
||||||
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
t.boolean("isActive").notNullable();
|
t.boolean("isActive").notNullable();
|
||||||
t.string("url"); // self hosted
|
t.string("url"); // self-hosted
|
||||||
t.string("app"); // name of app in provider
|
t.string("app"); // name of app in provider
|
||||||
t.string("appId");
|
t.string("appId");
|
||||||
t.string("targetEnvironment");
|
t.string("targetEnvironment");
|
||||||
|
@ -64,23 +64,25 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (await knex.schema.hasTable(TableName.Certificate)) {
|
if (await knex.schema.hasTable(TableName.Certificate)) {
|
||||||
await knex.schema.alterTable(TableName.Certificate, (t) => {
|
const hasCaCertIdColumn = await knex.schema.hasColumn(TableName.Certificate, "caCertId");
|
||||||
t.uuid("caCertId").nullable();
|
if (!hasCaCertIdColumn) {
|
||||||
t.foreign("caCertId").references("id").inTable(TableName.CertificateAuthorityCert);
|
await knex.schema.alterTable(TableName.Certificate, (t) => {
|
||||||
});
|
t.uuid("caCertId").nullable();
|
||||||
|
t.foreign("caCertId").references("id").inTable(TableName.CertificateAuthorityCert);
|
||||||
|
});
|
||||||
|
|
||||||
await knex.raw(`
|
await knex.raw(`
|
||||||
UPDATE "${TableName.Certificate}" cert
|
UPDATE "${TableName.Certificate}" cert
|
||||||
SET "caCertId" = (
|
SET "caCertId" = (
|
||||||
SELECT caCert.id
|
SELECT caCert.id
|
||||||
FROM "${TableName.CertificateAuthorityCert}" caCert
|
FROM "${TableName.CertificateAuthorityCert}" caCert
|
||||||
WHERE caCert."caId" = cert."caId"
|
WHERE caCert."caId" = cert."caId"
|
||||||
)
|
)`);
|
||||||
`);
|
|
||||||
|
|
||||||
await knex.schema.alterTable(TableName.Certificate, (t) => {
|
await knex.schema.alterTable(TableName.Certificate, (t) => {
|
||||||
t.uuid("caCertId").notNullable().alter();
|
t.uuid("caCertId").notNullable().alter();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,27 +4,40 @@ import { TableName } from "../schemas";
|
|||||||
|
|
||||||
export async function up(knex: Knex): Promise<void> {
|
export async function up(knex: Knex): Promise<void> {
|
||||||
if (await knex.schema.hasTable(TableName.SecretSharing)) {
|
if (await knex.schema.hasTable(TableName.SecretSharing)) {
|
||||||
|
const hasEncryptedSecret = await knex.schema.hasColumn(TableName.SecretSharing, "encryptedSecret");
|
||||||
|
const hasIdentifier = await knex.schema.hasColumn(TableName.SecretSharing, "identifier");
|
||||||
|
|
||||||
await knex.schema.alterTable(TableName.SecretSharing, (t) => {
|
await knex.schema.alterTable(TableName.SecretSharing, (t) => {
|
||||||
t.string("iv").nullable().alter();
|
t.string("iv").nullable().alter();
|
||||||
t.string("tag").nullable().alter();
|
t.string("tag").nullable().alter();
|
||||||
t.string("encryptedValue").nullable().alter();
|
t.string("encryptedValue").nullable().alter();
|
||||||
|
|
||||||
t.binary("encryptedSecret").nullable();
|
if (!hasEncryptedSecret) {
|
||||||
|
t.binary("encryptedSecret").nullable();
|
||||||
|
}
|
||||||
t.string("hashedHex").nullable().alter();
|
t.string("hashedHex").nullable().alter();
|
||||||
|
|
||||||
t.string("identifier", 64).nullable();
|
if (!hasIdentifier) {
|
||||||
t.unique("identifier");
|
t.string("identifier", 64).nullable();
|
||||||
t.index("identifier");
|
t.unique("identifier");
|
||||||
|
t.index("identifier");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function down(knex: Knex): Promise<void> {
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasEncryptedSecret = await knex.schema.hasColumn(TableName.SecretSharing, "encryptedSecret");
|
||||||
|
const hasIdentifier = await knex.schema.hasColumn(TableName.SecretSharing, "identifier");
|
||||||
if (await knex.schema.hasTable(TableName.SecretSharing)) {
|
if (await knex.schema.hasTable(TableName.SecretSharing)) {
|
||||||
await knex.schema.alterTable(TableName.SecretSharing, (t) => {
|
await knex.schema.alterTable(TableName.SecretSharing, (t) => {
|
||||||
t.dropColumn("encryptedSecret");
|
if (hasEncryptedSecret) {
|
||||||
|
t.dropColumn("encryptedSecret");
|
||||||
|
}
|
||||||
|
|
||||||
t.dropColumn("identifier");
|
if (hasIdentifier) {
|
||||||
|
t.dropColumn("identifier");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,15 +7,18 @@ export async function up(knex: Knex): Promise<void> {
|
|||||||
if (await knex.schema.hasTable(TableName.KmsKey)) {
|
if (await knex.schema.hasTable(TableName.KmsKey)) {
|
||||||
const hasOrgId = await knex.schema.hasColumn(TableName.KmsKey, "orgId");
|
const hasOrgId = await knex.schema.hasColumn(TableName.KmsKey, "orgId");
|
||||||
const hasSlug = await knex.schema.hasColumn(TableName.KmsKey, "slug");
|
const hasSlug = await knex.schema.hasColumn(TableName.KmsKey, "slug");
|
||||||
|
const hasProjectId = await knex.schema.hasColumn(TableName.KmsKey, "projectId");
|
||||||
|
|
||||||
// drop constraint if exists (won't exist if rolled back, see below)
|
// drop constraint if exists (won't exist if rolled back, see below)
|
||||||
await dropConstraintIfExists(TableName.KmsKey, "kms_keys_orgid_slug_unique", knex);
|
await dropConstraintIfExists(TableName.KmsKey, "kms_keys_orgid_slug_unique", knex);
|
||||||
|
|
||||||
// projectId for CMEK functionality
|
// projectId for CMEK functionality
|
||||||
await knex.schema.alterTable(TableName.KmsKey, (table) => {
|
await knex.schema.alterTable(TableName.KmsKey, (table) => {
|
||||||
table.string("projectId").nullable().references("id").inTable(TableName.Project).onDelete("CASCADE");
|
if (!hasProjectId) {
|
||||||
|
table.string("projectId").nullable().references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||||
|
}
|
||||||
|
|
||||||
if (hasOrgId) {
|
if (hasOrgId && hasSlug) {
|
||||||
table.unique(["orgId", "projectId", "slug"]);
|
table.unique(["orgId", "projectId", "slug"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,6 +33,7 @@ export async function down(knex: Knex): Promise<void> {
|
|||||||
if (await knex.schema.hasTable(TableName.KmsKey)) {
|
if (await knex.schema.hasTable(TableName.KmsKey)) {
|
||||||
const hasOrgId = await knex.schema.hasColumn(TableName.KmsKey, "orgId");
|
const hasOrgId = await knex.schema.hasColumn(TableName.KmsKey, "orgId");
|
||||||
const hasName = await knex.schema.hasColumn(TableName.KmsKey, "name");
|
const hasName = await knex.schema.hasColumn(TableName.KmsKey, "name");
|
||||||
|
const hasProjectId = await knex.schema.hasColumn(TableName.KmsKey, "projectId");
|
||||||
|
|
||||||
// remove projectId for CMEK functionality
|
// remove projectId for CMEK functionality
|
||||||
await knex.schema.alterTable(TableName.KmsKey, (table) => {
|
await knex.schema.alterTable(TableName.KmsKey, (table) => {
|
||||||
@ -40,7 +44,9 @@ export async function down(knex: Knex): Promise<void> {
|
|||||||
if (hasOrgId) {
|
if (hasOrgId) {
|
||||||
table.dropUnique(["orgId", "projectId", "slug"]);
|
table.dropUnique(["orgId", "projectId", "slug"]);
|
||||||
}
|
}
|
||||||
table.dropColumn("projectId");
|
if (hasProjectId) {
|
||||||
|
table.dropColumn("projectId");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,101 @@
|
|||||||
|
/* eslint-disable no-await-in-loop */
|
||||||
|
import { packRules, unpackRules } from "@casl/ability/extra";
|
||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import {
|
||||||
|
backfillPermissionV1SchemaToV2Schema,
|
||||||
|
ProjectPermissionSub
|
||||||
|
} from "@app/ee/services/permission/project-permission";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
const CHUNK_SIZE = 1000;
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasVersion = await knex.schema.hasColumn(TableName.ProjectRoles, "version");
|
||||||
|
if (!hasVersion) {
|
||||||
|
await knex.schema.alterTable(TableName.ProjectRoles, (t) => {
|
||||||
|
t.integer("version").defaultTo(1).notNullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
const docs = await knex(TableName.ProjectRoles).select("*");
|
||||||
|
const updatedDocs = docs
|
||||||
|
.filter((i) => {
|
||||||
|
const permissionString = JSON.stringify(i.permissions || []);
|
||||||
|
return (
|
||||||
|
!permissionString.includes(ProjectPermissionSub.SecretImports) &&
|
||||||
|
!permissionString.includes(ProjectPermissionSub.DynamicSecrets)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.map((el) => ({
|
||||||
|
...el,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore-error this is valid ts
|
||||||
|
permissions: JSON.stringify(packRules(backfillPermissionV1SchemaToV2Schema(unpackRules(el.permissions), true)))
|
||||||
|
}));
|
||||||
|
if (updatedDocs.length) {
|
||||||
|
for (let i = 0; i < updatedDocs.length; i += CHUNK_SIZE) {
|
||||||
|
const chunk = updatedDocs.slice(i, i + CHUNK_SIZE);
|
||||||
|
await knex(TableName.ProjectRoles).insert(chunk).onConflict("id").merge();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// secret permission is split into multiple ones like secrets, folders, imports and dynamic-secrets
|
||||||
|
// so we just find all the privileges with respective mapping and map it as needed
|
||||||
|
const identityPrivileges = await knex(TableName.IdentityProjectAdditionalPrivilege).select("*");
|
||||||
|
const updatedIdentityPrivilegesDocs = identityPrivileges
|
||||||
|
.filter((i) => {
|
||||||
|
const permissionString = JSON.stringify(i.permissions || []);
|
||||||
|
return (
|
||||||
|
!permissionString.includes(ProjectPermissionSub.SecretImports) &&
|
||||||
|
!permissionString.includes(ProjectPermissionSub.DynamicSecrets) &&
|
||||||
|
!permissionString.includes(ProjectPermissionSub.SecretFolders)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.map((el) => ({
|
||||||
|
...el,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore-error this is valid ts
|
||||||
|
permissions: JSON.stringify(packRules(backfillPermissionV1SchemaToV2Schema(unpackRules(el.permissions))))
|
||||||
|
}));
|
||||||
|
if (updatedIdentityPrivilegesDocs.length) {
|
||||||
|
for (let i = 0; i < updatedIdentityPrivilegesDocs.length; i += CHUNK_SIZE) {
|
||||||
|
const chunk = updatedIdentityPrivilegesDocs.slice(i, i + CHUNK_SIZE);
|
||||||
|
await knex(TableName.IdentityProjectAdditionalPrivilege).insert(chunk).onConflict("id").merge();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const userPrivileges = await knex(TableName.ProjectUserAdditionalPrivilege).select("*");
|
||||||
|
const updatedUserPrivilegeDocs = userPrivileges
|
||||||
|
.filter((i) => {
|
||||||
|
const permissionString = JSON.stringify(i.permissions || []);
|
||||||
|
return (
|
||||||
|
!permissionString.includes(ProjectPermissionSub.SecretImports) &&
|
||||||
|
!permissionString.includes(ProjectPermissionSub.DynamicSecrets) &&
|
||||||
|
!permissionString.includes(ProjectPermissionSub.SecretFolders)
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.map((el) => ({
|
||||||
|
...el,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore-error this is valid ts
|
||||||
|
permissions: JSON.stringify(packRules(backfillPermissionV1SchemaToV2Schema(unpackRules(el.permissions))))
|
||||||
|
}));
|
||||||
|
if (docs.length) {
|
||||||
|
for (let i = 0; i < updatedUserPrivilegeDocs.length; i += CHUNK_SIZE) {
|
||||||
|
const chunk = updatedUserPrivilegeDocs.slice(i, i + CHUNK_SIZE);
|
||||||
|
await knex(TableName.ProjectUserAdditionalPrivilege).insert(chunk).onConflict("id").merge();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasVersion = await knex.schema.hasColumn(TableName.ProjectRoles, "version");
|
||||||
|
if (hasVersion) {
|
||||||
|
await knex.schema.alterTable(TableName.ProjectRoles, (t) => {
|
||||||
|
t.dropColumn("version");
|
||||||
|
});
|
||||||
|
|
||||||
|
// permission change can be ignored
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
const BATCH_SIZE = 10_000;
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasAuthMethodColumnAccessToken = await knex.schema.hasColumn(TableName.IdentityAccessToken, "authMethod");
|
||||||
|
|
||||||
|
if (!hasAuthMethodColumnAccessToken) {
|
||||||
|
await knex.schema.alterTable(TableName.IdentityAccessToken, (t) => {
|
||||||
|
t.string("authMethod").nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
// first we remove identities without auth method that is unused
|
||||||
|
// ! We delete all access tokens where the identity has no auth method set!
|
||||||
|
// ! Which means un-configured identities that for some reason have access tokens, will have their access tokens deleted.
|
||||||
|
await knex(TableName.IdentityAccessToken)
|
||||||
|
.leftJoin(TableName.Identity, `${TableName.Identity}.id`, `${TableName.IdentityAccessToken}.identityId`)
|
||||||
|
.whereNull(`${TableName.Identity}.authMethod`)
|
||||||
|
.delete();
|
||||||
|
|
||||||
|
let nullableAccessTokens = await knex(TableName.IdentityAccessToken)
|
||||||
|
.whereNull("authMethod")
|
||||||
|
.limit(BATCH_SIZE)
|
||||||
|
.select("id");
|
||||||
|
let totalUpdated = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
const batchIds = nullableAccessTokens.map((token) => token.id);
|
||||||
|
|
||||||
|
// ! Update the auth method column in batches for the current batch
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await knex(TableName.IdentityAccessToken)
|
||||||
|
.whereIn("id", batchIds)
|
||||||
|
.update({
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore because generate schema happens after this
|
||||||
|
authMethod: knex(TableName.Identity)
|
||||||
|
.select("authMethod")
|
||||||
|
.whereRaw(`${TableName.IdentityAccessToken}."identityId" = ${TableName.Identity}.id`)
|
||||||
|
.whereNotNull("authMethod")
|
||||||
|
.first()
|
||||||
|
});
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
nullableAccessTokens = await knex(TableName.IdentityAccessToken)
|
||||||
|
.whereNull("authMethod")
|
||||||
|
.limit(BATCH_SIZE)
|
||||||
|
.select("id");
|
||||||
|
|
||||||
|
totalUpdated += batchIds.length;
|
||||||
|
console.log(`Updated ${batchIds.length} access tokens in batch <> Total updated: ${totalUpdated}`);
|
||||||
|
} while (nullableAccessTokens.length > 0);
|
||||||
|
|
||||||
|
// Finally we set the authMethod to notNullable after populating the column.
|
||||||
|
// This will fail if the data is not populated correctly, so it's safe.
|
||||||
|
await knex.schema.alterTable(TableName.IdentityAccessToken, (t) => {
|
||||||
|
t.string("authMethod").notNullable().alter();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ! We aren't dropping the authMethod column from the Identity itself, because we wan't to be able to easily rollback for the time being.
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasAuthMethodColumnAccessToken = await knex.schema.hasColumn(TableName.IdentityAccessToken, "authMethod");
|
||||||
|
|
||||||
|
if (hasAuthMethodColumnAccessToken) {
|
||||||
|
await knex.schema.alterTable(TableName.IdentityAccessToken, (t) => {
|
||||||
|
t.dropColumn("authMethod");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = { transaction: false };
|
||||||
|
export { config };
|
@ -0,0 +1,19 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (!(await knex.schema.hasColumn(TableName.Organization, "enforceMfa"))) {
|
||||||
|
await knex.schema.alterTable(TableName.Organization, (tb) => {
|
||||||
|
tb.boolean("enforceMfa").defaultTo(false).notNullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasColumn(TableName.Organization, "enforceMfa")) {
|
||||||
|
await knex.schema.alterTable(TableName.Organization, (t) => {
|
||||||
|
t.dropColumn("enforceMfa");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasColumn(TableName.SamlConfig, "orgId")) {
|
||||||
|
await knex.schema.alterTable(TableName.SamlConfig, (t) => {
|
||||||
|
t.dropForeign("orgId");
|
||||||
|
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasColumn(TableName.SamlConfig, "orgId")) {
|
||||||
|
await knex.schema.alterTable(TableName.SamlConfig, (t) => {
|
||||||
|
t.dropForeign("orgId");
|
||||||
|
t.foreign("orgId").references("id").inTable(TableName.Organization);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "@app/db/schemas";
|
||||||
|
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "@app/db/utils";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (!(await knex.schema.hasTable(TableName.ProjectTemplates))) {
|
||||||
|
await knex.schema.createTable(TableName.ProjectTemplates, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.string("name", 32).notNullable();
|
||||||
|
t.string("description").nullable();
|
||||||
|
t.jsonb("roles").notNullable();
|
||||||
|
t.jsonb("environments").notNullable();
|
||||||
|
t.uuid("orgId").notNullable().references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
await createOnUpdateTrigger(knex, TableName.ProjectTemplates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasTable(TableName.ProjectTemplates)) {
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.ProjectTemplates);
|
||||||
|
|
||||||
|
await knex.schema.dropTable(TableName.ProjectTemplates);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasDisableBootstrapCertValidationCol = await knex.schema.hasColumn(
|
||||||
|
TableName.CertificateTemplateEstConfig,
|
||||||
|
"disableBootstrapCertValidation"
|
||||||
|
);
|
||||||
|
|
||||||
|
const hasCaChainCol = await knex.schema.hasColumn(TableName.CertificateTemplateEstConfig, "encryptedCaChain");
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.CertificateTemplateEstConfig, (t) => {
|
||||||
|
if (!hasDisableBootstrapCertValidationCol) {
|
||||||
|
t.boolean("disableBootstrapCertValidation").defaultTo(false).notNullable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasCaChainCol) {
|
||||||
|
t.binary("encryptedCaChain").nullable().alter();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasDisableBootstrapCertValidationCol = await knex.schema.hasColumn(
|
||||||
|
TableName.CertificateTemplateEstConfig,
|
||||||
|
"disableBootstrapCertValidation"
|
||||||
|
);
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.CertificateTemplateEstConfig, (t) => {
|
||||||
|
if (hasDisableBootstrapCertValidationCol) {
|
||||||
|
t.dropColumn("disableBootstrapCertValidation");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasColumn(TableName.OidcConfig, "orgId")) {
|
||||||
|
await knex.schema.alterTable(TableName.OidcConfig, (t) => {
|
||||||
|
t.dropForeign("orgId");
|
||||||
|
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasColumn(TableName.OidcConfig, "orgId")) {
|
||||||
|
await knex.schema.alterTable(TableName.OidcConfig, (t) => {
|
||||||
|
t.dropForeign("orgId");
|
||||||
|
t.foreign("orgId").references("id").inTable(TableName.Organization);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
23
backend/src/db/migrations/20241111175154_kms-root-cfg-hsm.ts
Normal file
23
backend/src/db/migrations/20241111175154_kms-root-cfg-hsm.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasEncryptionStrategy = await knex.schema.hasColumn(TableName.KmsServerRootConfig, "encryptionStrategy");
|
||||||
|
const hasTimestampsCol = await knex.schema.hasColumn(TableName.KmsServerRootConfig, "createdAt");
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.KmsServerRootConfig, (t) => {
|
||||||
|
if (!hasEncryptionStrategy) t.string("encryptionStrategy").defaultTo("SOFTWARE");
|
||||||
|
if (!hasTimestampsCol) t.timestamps(true, true, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasEncryptionStrategy = await knex.schema.hasColumn(TableName.KmsServerRootConfig, "encryptionStrategy");
|
||||||
|
const hasTimestampsCol = await knex.schema.hasColumn(TableName.KmsServerRootConfig, "createdAt");
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.KmsServerRootConfig, (t) => {
|
||||||
|
if (hasEncryptionStrategy) t.dropColumn("encryptionStrategy");
|
||||||
|
if (hasTimestampsCol) t.dropTimestamps(true);
|
||||||
|
});
|
||||||
|
}
|
54
backend/src/db/migrations/20241112082701_add-totp-support.ts
Normal file
54
backend/src/db/migrations/20241112082701_add-totp-support.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (!(await knex.schema.hasTable(TableName.TotpConfig))) {
|
||||||
|
await knex.schema.createTable(TableName.TotpConfig, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.uuid("userId").notNullable();
|
||||||
|
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||||
|
t.boolean("isVerified").defaultTo(false).notNullable();
|
||||||
|
t.binary("encryptedRecoveryCodes").notNullable();
|
||||||
|
t.binary("encryptedSecret").notNullable();
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
t.unique("userId");
|
||||||
|
});
|
||||||
|
|
||||||
|
await createOnUpdateTrigger(knex, TableName.TotpConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
const doesOrgMfaMethodColExist = await knex.schema.hasColumn(TableName.Organization, "selectedMfaMethod");
|
||||||
|
await knex.schema.alterTable(TableName.Organization, (t) => {
|
||||||
|
if (!doesOrgMfaMethodColExist) {
|
||||||
|
t.string("selectedMfaMethod");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const doesUserSelectedMfaMethodColExist = await knex.schema.hasColumn(TableName.Users, "selectedMfaMethod");
|
||||||
|
await knex.schema.alterTable(TableName.Users, (t) => {
|
||||||
|
if (!doesUserSelectedMfaMethodColExist) {
|
||||||
|
t.string("selectedMfaMethod");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.TotpConfig);
|
||||||
|
await knex.schema.dropTableIfExists(TableName.TotpConfig);
|
||||||
|
|
||||||
|
const doesOrgMfaMethodColExist = await knex.schema.hasColumn(TableName.Organization, "selectedMfaMethod");
|
||||||
|
await knex.schema.alterTable(TableName.Organization, (t) => {
|
||||||
|
if (doesOrgMfaMethodColExist) {
|
||||||
|
t.dropColumn("selectedMfaMethod");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const doesUserSelectedMfaMethodColExist = await knex.schema.hasColumn(TableName.Users, "selectedMfaMethod");
|
||||||
|
await knex.schema.alterTable(TableName.Users, (t) => {
|
||||||
|
if (doesUserSelectedMfaMethodColExist) {
|
||||||
|
t.dropColumn("selectedMfaMethod");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasProjectDescription = await knex.schema.hasColumn(TableName.Project, "description");
|
||||||
|
|
||||||
|
if (!hasProjectDescription) {
|
||||||
|
await knex.schema.alterTable(TableName.Project, (t) => {
|
||||||
|
t.string("description");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasProjectDescription = await knex.schema.hasColumn(TableName.Project, "description");
|
||||||
|
|
||||||
|
if (hasProjectDescription) {
|
||||||
|
await knex.schema.alterTable(TableName.Project, (t) => {
|
||||||
|
t.dropColumn("description");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasColumn(TableName.IdentityMetadata, "value")) {
|
||||||
|
await knex(TableName.IdentityMetadata).whereNull("value").delete();
|
||||||
|
await knex.schema.alterTable(TableName.IdentityMetadata, (t) => {
|
||||||
|
t.string("value", 1020).notNullable().alter();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasColumn(TableName.IdentityMetadata, "value")) {
|
||||||
|
await knex.schema.alterTable(TableName.IdentityMetadata, (t) => {
|
||||||
|
t.string("value", 1020).alter();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasAccessApprovalPolicyDeletedAtColumn = await knex.schema.hasColumn(
|
||||||
|
TableName.AccessApprovalPolicy,
|
||||||
|
"deletedAt"
|
||||||
|
);
|
||||||
|
const hasSecretApprovalPolicyDeletedAtColumn = await knex.schema.hasColumn(
|
||||||
|
TableName.SecretApprovalPolicy,
|
||||||
|
"deletedAt"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!hasAccessApprovalPolicyDeletedAtColumn) {
|
||||||
|
await knex.schema.alterTable(TableName.AccessApprovalPolicy, (t) => {
|
||||||
|
t.timestamp("deletedAt");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!hasSecretApprovalPolicyDeletedAtColumn) {
|
||||||
|
await knex.schema.alterTable(TableName.SecretApprovalPolicy, (t) => {
|
||||||
|
t.timestamp("deletedAt");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.AccessApprovalRequest, (t) => {
|
||||||
|
t.dropForeign(["privilegeId"]);
|
||||||
|
|
||||||
|
// Add the new foreign key constraint with ON DELETE SET NULL
|
||||||
|
t.foreign("privilegeId").references("id").inTable(TableName.ProjectUserAdditionalPrivilege).onDelete("SET NULL");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasAccessApprovalPolicyDeletedAtColumn = await knex.schema.hasColumn(
|
||||||
|
TableName.AccessApprovalPolicy,
|
||||||
|
"deletedAt"
|
||||||
|
);
|
||||||
|
const hasSecretApprovalPolicyDeletedAtColumn = await knex.schema.hasColumn(
|
||||||
|
TableName.SecretApprovalPolicy,
|
||||||
|
"deletedAt"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (hasAccessApprovalPolicyDeletedAtColumn) {
|
||||||
|
await knex.schema.alterTable(TableName.AccessApprovalPolicy, (t) => {
|
||||||
|
t.dropColumn("deletedAt");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (hasSecretApprovalPolicyDeletedAtColumn) {
|
||||||
|
await knex.schema.alterTable(TableName.SecretApprovalPolicy, (t) => {
|
||||||
|
t.dropColumn("deletedAt");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.AccessApprovalRequest, (t) => {
|
||||||
|
t.dropForeign(["privilegeId"]);
|
||||||
|
t.foreign("privilegeId").references("id").inTable(TableName.ProjectUserAdditionalPrivilege).onDelete("CASCADE");
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (!(await knex.schema.hasTable(TableName.IdentityJwtAuth))) {
|
||||||
|
await knex.schema.createTable(TableName.IdentityJwtAuth, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.bigInteger("accessTokenTTL").defaultTo(7200).notNullable();
|
||||||
|
t.bigInteger("accessTokenMaxTTL").defaultTo(7200).notNullable();
|
||||||
|
t.bigInteger("accessTokenNumUsesLimit").defaultTo(0).notNullable();
|
||||||
|
t.jsonb("accessTokenTrustedIps").notNullable();
|
||||||
|
t.uuid("identityId").notNullable().unique();
|
||||||
|
t.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
|
||||||
|
t.string("configurationType").notNullable();
|
||||||
|
t.string("jwksUrl").notNullable();
|
||||||
|
t.binary("encryptedJwksCaCert").notNullable();
|
||||||
|
t.binary("encryptedPublicKeys").notNullable();
|
||||||
|
t.string("boundIssuer").notNullable();
|
||||||
|
t.string("boundAudiences").notNullable();
|
||||||
|
t.jsonb("boundClaims").notNullable();
|
||||||
|
t.string("boundSubject").notNullable();
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
await createOnUpdateTrigger(knex, TableName.IdentityJwtAuth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.dropTableIfExists(TableName.IdentityJwtAuth);
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.IdentityJwtAuth);
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasColumn(TableName.SecretVersionV2, "folderId")) {
|
||||||
|
await knex.schema.alterTable(TableName.SecretVersionV2, (t) => {
|
||||||
|
t.index("folderId");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasColumn(TableName.SecretVersionV2, "folderId")) {
|
||||||
|
await knex.schema.alterTable(TableName.SecretVersionV2, (t) => {
|
||||||
|
t.dropIndex("folderId");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,297 @@
|
|||||||
|
import slugify from "@sindresorhus/slugify";
|
||||||
|
import { Knex } from "knex";
|
||||||
|
import { v4 as uuidV4 } from "uuid";
|
||||||
|
|
||||||
|
import { alphaNumericNanoId } from "@app/lib/nanoid";
|
||||||
|
|
||||||
|
import { ProjectType, TableName } from "../schemas";
|
||||||
|
|
||||||
|
/* eslint-disable no-await-in-loop,@typescript-eslint/ban-ts-comment */
|
||||||
|
const newProject = async (knex: Knex, projectId: string, projectType: ProjectType) => {
|
||||||
|
const newProjectId = uuidV4();
|
||||||
|
const project = await knex(TableName.Project).where("id", projectId).first();
|
||||||
|
await knex(TableName.Project).insert({
|
||||||
|
...project,
|
||||||
|
type: projectType,
|
||||||
|
// @ts-ignore id is required
|
||||||
|
id: newProjectId,
|
||||||
|
slug: slugify(`${project?.name}-${alphaNumericNanoId(4)}`)
|
||||||
|
});
|
||||||
|
|
||||||
|
const customRoleMapping: Record<string, string> = {};
|
||||||
|
const projectCustomRoles = await knex(TableName.ProjectRoles).where("projectId", projectId);
|
||||||
|
if (projectCustomRoles.length) {
|
||||||
|
await knex.batchInsert(
|
||||||
|
TableName.ProjectRoles,
|
||||||
|
projectCustomRoles.map((el) => {
|
||||||
|
const id = uuidV4();
|
||||||
|
customRoleMapping[el.id] = id;
|
||||||
|
return {
|
||||||
|
...el,
|
||||||
|
id,
|
||||||
|
projectId: newProjectId,
|
||||||
|
permissions: el.permissions ? JSON.stringify(el.permissions) : el.permissions
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const groupMembershipMapping: Record<string, string> = {};
|
||||||
|
const groupMemberships = await knex(TableName.GroupProjectMembership).where("projectId", projectId);
|
||||||
|
if (groupMemberships.length) {
|
||||||
|
await knex.batchInsert(
|
||||||
|
TableName.GroupProjectMembership,
|
||||||
|
groupMemberships.map((el) => {
|
||||||
|
const id = uuidV4();
|
||||||
|
groupMembershipMapping[el.id] = id;
|
||||||
|
return { ...el, id, projectId: newProjectId };
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupMembershipRoles = await knex(TableName.GroupProjectMembershipRole).whereIn(
|
||||||
|
"projectMembershipId",
|
||||||
|
groupMemberships.map((el) => el.id)
|
||||||
|
);
|
||||||
|
if (groupMembershipRoles.length) {
|
||||||
|
await knex.batchInsert(
|
||||||
|
TableName.GroupProjectMembershipRole,
|
||||||
|
groupMembershipRoles.map((el) => {
|
||||||
|
const id = uuidV4();
|
||||||
|
const projectMembershipId = groupMembershipMapping[el.projectMembershipId];
|
||||||
|
const customRoleId = el.customRoleId ? customRoleMapping[el.customRoleId] : el.customRoleId;
|
||||||
|
return { ...el, id, projectMembershipId, customRoleId };
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const identityProjectMembershipMapping: Record<string, string> = {};
|
||||||
|
const identities = await knex(TableName.IdentityProjectMembership).where("projectId", projectId);
|
||||||
|
if (identities.length) {
|
||||||
|
await knex.batchInsert(
|
||||||
|
TableName.IdentityProjectMembership,
|
||||||
|
identities.map((el) => {
|
||||||
|
const id = uuidV4();
|
||||||
|
identityProjectMembershipMapping[el.id] = id;
|
||||||
|
return { ...el, id, projectId: newProjectId };
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const identitiesRoles = await knex(TableName.IdentityProjectMembershipRole).whereIn(
|
||||||
|
"projectMembershipId",
|
||||||
|
identities.map((el) => el.id)
|
||||||
|
);
|
||||||
|
if (identitiesRoles.length) {
|
||||||
|
await knex.batchInsert(
|
||||||
|
TableName.IdentityProjectMembershipRole,
|
||||||
|
identitiesRoles.map((el) => {
|
||||||
|
const id = uuidV4();
|
||||||
|
const projectMembershipId = identityProjectMembershipMapping[el.projectMembershipId];
|
||||||
|
const customRoleId = el.customRoleId ? customRoleMapping[el.customRoleId] : el.customRoleId;
|
||||||
|
return { ...el, id, projectMembershipId, customRoleId };
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectMembershipMapping: Record<string, string> = {};
|
||||||
|
const projectUserMembers = await knex(TableName.ProjectMembership).where("projectId", projectId);
|
||||||
|
if (projectUserMembers.length) {
|
||||||
|
await knex.batchInsert(
|
||||||
|
TableName.ProjectMembership,
|
||||||
|
projectUserMembers.map((el) => {
|
||||||
|
const id = uuidV4();
|
||||||
|
projectMembershipMapping[el.id] = id;
|
||||||
|
return { ...el, id, projectId: newProjectId };
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const membershipRoles = await knex(TableName.ProjectUserMembershipRole).whereIn(
|
||||||
|
"projectMembershipId",
|
||||||
|
projectUserMembers.map((el) => el.id)
|
||||||
|
);
|
||||||
|
if (membershipRoles.length) {
|
||||||
|
await knex.batchInsert(
|
||||||
|
TableName.ProjectUserMembershipRole,
|
||||||
|
membershipRoles.map((el) => {
|
||||||
|
const id = uuidV4();
|
||||||
|
const projectMembershipId = projectMembershipMapping[el.projectMembershipId];
|
||||||
|
const customRoleId = el.customRoleId ? customRoleMapping[el.customRoleId] : el.customRoleId;
|
||||||
|
return { ...el, id, projectMembershipId, customRoleId };
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const kmsKeys = await knex(TableName.KmsKey).where("projectId", projectId).andWhere("isReserved", true);
|
||||||
|
if (kmsKeys.length) {
|
||||||
|
await knex.batchInsert(
|
||||||
|
TableName.KmsKey,
|
||||||
|
kmsKeys.map((el) => {
|
||||||
|
const id = uuidV4();
|
||||||
|
const slug = slugify(alphaNumericNanoId(8).toLowerCase());
|
||||||
|
return { ...el, id, slug, projectId: newProjectId };
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectBot = await knex(TableName.ProjectBot).where("projectId", projectId).first();
|
||||||
|
if (projectBot) {
|
||||||
|
const newProjectBot = { ...projectBot, id: uuidV4(), projectId: newProjectId };
|
||||||
|
await knex(TableName.ProjectBot).insert(newProjectBot);
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectKeys = await knex(TableName.ProjectKeys).where("projectId", projectId);
|
||||||
|
if (projectKeys.length) {
|
||||||
|
await knex.batchInsert(
|
||||||
|
TableName.ProjectKeys,
|
||||||
|
projectKeys.map((el) => {
|
||||||
|
const id = uuidV4();
|
||||||
|
return { ...el, id, projectId: newProjectId };
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newProjectId;
|
||||||
|
};
|
||||||
|
|
||||||
|
const BATCH_SIZE = 500;
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasSplitMappingTable = await knex.schema.hasTable(TableName.ProjectSplitBackfillIds);
|
||||||
|
if (!hasSplitMappingTable) {
|
||||||
|
await knex.schema.createTable(TableName.ProjectSplitBackfillIds, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.string("sourceProjectId", 36).notNullable();
|
||||||
|
t.foreign("sourceProjectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||||
|
t.string("destinationProjectType").notNullable();
|
||||||
|
t.string("destinationProjectId", 36).notNullable();
|
||||||
|
t.foreign("destinationProjectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasTypeColumn = await knex.schema.hasColumn(TableName.Project, "type");
|
||||||
|
if (!hasTypeColumn) {
|
||||||
|
await knex.schema.alterTable(TableName.Project, (t) => {
|
||||||
|
t.string("type");
|
||||||
|
});
|
||||||
|
|
||||||
|
let projectsToBeTyped;
|
||||||
|
do {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
projectsToBeTyped = await knex(TableName.Project).whereNull("type").limit(BATCH_SIZE).select("id");
|
||||||
|
if (projectsToBeTyped.length) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await knex(TableName.Project)
|
||||||
|
.whereIn(
|
||||||
|
"id",
|
||||||
|
projectsToBeTyped.map((el) => el.id)
|
||||||
|
)
|
||||||
|
.update({ type: ProjectType.SecretManager });
|
||||||
|
}
|
||||||
|
} while (projectsToBeTyped.length > 0);
|
||||||
|
|
||||||
|
const projectsWithCertificates = await knex(TableName.CertificateAuthority)
|
||||||
|
.distinct("projectId")
|
||||||
|
.select("projectId");
|
||||||
|
/* eslint-disable no-await-in-loop,no-param-reassign */
|
||||||
|
for (const { projectId } of projectsWithCertificates) {
|
||||||
|
const newProjectId = await newProject(knex, projectId, ProjectType.CertificateManager);
|
||||||
|
await knex(TableName.CertificateAuthority).where("projectId", projectId).update({ projectId: newProjectId });
|
||||||
|
await knex(TableName.PkiAlert).where("projectId", projectId).update({ projectId: newProjectId });
|
||||||
|
await knex(TableName.PkiCollection).where("projectId", projectId).update({ projectId: newProjectId });
|
||||||
|
await knex(TableName.ProjectSplitBackfillIds).insert({
|
||||||
|
sourceProjectId: projectId,
|
||||||
|
destinationProjectType: ProjectType.CertificateManager,
|
||||||
|
destinationProjectId: newProjectId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectsWithCmek = await knex(TableName.KmsKey)
|
||||||
|
.where("isReserved", false)
|
||||||
|
.whereNotNull("projectId")
|
||||||
|
.distinct("projectId")
|
||||||
|
.select("projectId");
|
||||||
|
for (const { projectId } of projectsWithCmek) {
|
||||||
|
if (projectId) {
|
||||||
|
const newProjectId = await newProject(knex, projectId, ProjectType.KMS);
|
||||||
|
await knex(TableName.KmsKey)
|
||||||
|
.where({
|
||||||
|
isReserved: false,
|
||||||
|
projectId
|
||||||
|
})
|
||||||
|
.update({ projectId: newProjectId });
|
||||||
|
await knex(TableName.ProjectSplitBackfillIds).insert({
|
||||||
|
sourceProjectId: projectId,
|
||||||
|
destinationProjectType: ProjectType.KMS,
|
||||||
|
destinationProjectId: newProjectId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-enable */
|
||||||
|
await knex.schema.alterTable(TableName.Project, (t) => {
|
||||||
|
t.string("type").notNullable().alter();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasTypeColumn = await knex.schema.hasColumn(TableName.Project, "type");
|
||||||
|
const hasSplitMappingTable = await knex.schema.hasTable(TableName.ProjectSplitBackfillIds);
|
||||||
|
|
||||||
|
if (hasTypeColumn && hasSplitMappingTable) {
|
||||||
|
const splitProjectMappings = await knex(TableName.ProjectSplitBackfillIds).where({});
|
||||||
|
const certMapping = splitProjectMappings.filter(
|
||||||
|
(el) => el.destinationProjectType === ProjectType.CertificateManager
|
||||||
|
);
|
||||||
|
/* eslint-disable no-await-in-loop */
|
||||||
|
for (const project of certMapping) {
|
||||||
|
await knex(TableName.CertificateAuthority)
|
||||||
|
.where("projectId", project.destinationProjectId)
|
||||||
|
.update({ projectId: project.sourceProjectId });
|
||||||
|
await knex(TableName.PkiAlert)
|
||||||
|
.where("projectId", project.destinationProjectId)
|
||||||
|
.update({ projectId: project.sourceProjectId });
|
||||||
|
await knex(TableName.PkiCollection)
|
||||||
|
.where("projectId", project.destinationProjectId)
|
||||||
|
.update({ projectId: project.sourceProjectId });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-enable */
|
||||||
|
const kmsMapping = splitProjectMappings.filter((el) => el.destinationProjectType === ProjectType.KMS);
|
||||||
|
/* eslint-disable no-await-in-loop */
|
||||||
|
for (const project of kmsMapping) {
|
||||||
|
await knex(TableName.KmsKey)
|
||||||
|
.where({
|
||||||
|
isReserved: false,
|
||||||
|
projectId: project.destinationProjectId
|
||||||
|
})
|
||||||
|
.update({ projectId: project.sourceProjectId });
|
||||||
|
}
|
||||||
|
/* eslint-enable */
|
||||||
|
await knex(TableName.ProjectMembership)
|
||||||
|
.whereIn(
|
||||||
|
"projectId",
|
||||||
|
splitProjectMappings.map((el) => el.destinationProjectId)
|
||||||
|
)
|
||||||
|
.delete();
|
||||||
|
await knex(TableName.ProjectRoles)
|
||||||
|
.whereIn(
|
||||||
|
"projectId",
|
||||||
|
splitProjectMappings.map((el) => el.destinationProjectId)
|
||||||
|
)
|
||||||
|
.delete();
|
||||||
|
await knex(TableName.Project)
|
||||||
|
.whereIn(
|
||||||
|
"id",
|
||||||
|
splitProjectMappings.map((el) => el.destinationProjectId)
|
||||||
|
)
|
||||||
|
.delete();
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.Project, (t) => {
|
||||||
|
t.dropColumn("type");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasSplitMappingTable) {
|
||||||
|
await knex.schema.dropTableIfExists(TableName.ProjectSplitBackfillIds);
|
||||||
|
}
|
||||||
|
}
|
99
backend/src/db/migrations/20241216013357_ssh-mgmt.ts
Normal file
99
backend/src/db/migrations/20241216013357_ssh-mgmt.ts
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (!(await knex.schema.hasTable(TableName.SshCertificateAuthority))) {
|
||||||
|
await knex.schema.createTable(TableName.SshCertificateAuthority, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
t.string("projectId").notNullable();
|
||||||
|
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||||
|
t.string("status").notNullable(); // active / disabled
|
||||||
|
t.string("friendlyName").notNullable();
|
||||||
|
t.string("keyAlgorithm").notNullable();
|
||||||
|
});
|
||||||
|
await createOnUpdateTrigger(knex, TableName.SshCertificateAuthority);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await knex.schema.hasTable(TableName.SshCertificateAuthoritySecret))) {
|
||||||
|
await knex.schema.createTable(TableName.SshCertificateAuthoritySecret, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
t.uuid("sshCaId").notNullable().unique();
|
||||||
|
t.foreign("sshCaId").references("id").inTable(TableName.SshCertificateAuthority).onDelete("CASCADE");
|
||||||
|
t.binary("encryptedPrivateKey").notNullable();
|
||||||
|
});
|
||||||
|
await createOnUpdateTrigger(knex, TableName.SshCertificateAuthoritySecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await knex.schema.hasTable(TableName.SshCertificateTemplate))) {
|
||||||
|
await knex.schema.createTable(TableName.SshCertificateTemplate, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
t.uuid("sshCaId").notNullable();
|
||||||
|
t.foreign("sshCaId").references("id").inTable(TableName.SshCertificateAuthority).onDelete("CASCADE");
|
||||||
|
t.string("status").notNullable(); // active / disabled
|
||||||
|
t.string("name").notNullable();
|
||||||
|
t.string("ttl").notNullable();
|
||||||
|
t.string("maxTTL").notNullable();
|
||||||
|
t.specificType("allowedUsers", "text[]").notNullable();
|
||||||
|
t.specificType("allowedHosts", "text[]").notNullable();
|
||||||
|
t.boolean("allowUserCertificates").notNullable();
|
||||||
|
t.boolean("allowHostCertificates").notNullable();
|
||||||
|
t.boolean("allowCustomKeyIds").notNullable();
|
||||||
|
});
|
||||||
|
await createOnUpdateTrigger(knex, TableName.SshCertificateTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await knex.schema.hasTable(TableName.SshCertificate))) {
|
||||||
|
await knex.schema.createTable(TableName.SshCertificate, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
t.uuid("sshCaId").notNullable();
|
||||||
|
t.foreign("sshCaId").references("id").inTable(TableName.SshCertificateAuthority).onDelete("SET NULL");
|
||||||
|
t.uuid("sshCertificateTemplateId");
|
||||||
|
t.foreign("sshCertificateTemplateId")
|
||||||
|
.references("id")
|
||||||
|
.inTable(TableName.SshCertificateTemplate)
|
||||||
|
.onDelete("SET NULL");
|
||||||
|
t.string("serialNumber").notNullable().unique();
|
||||||
|
t.string("certType").notNullable(); // user or host
|
||||||
|
t.specificType("principals", "text[]").notNullable();
|
||||||
|
t.string("keyId").notNullable();
|
||||||
|
t.datetime("notBefore").notNullable();
|
||||||
|
t.datetime("notAfter").notNullable();
|
||||||
|
});
|
||||||
|
await createOnUpdateTrigger(knex, TableName.SshCertificate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await knex.schema.hasTable(TableName.SshCertificateBody))) {
|
||||||
|
await knex.schema.createTable(TableName.SshCertificateBody, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
t.uuid("sshCertId").notNullable().unique();
|
||||||
|
t.foreign("sshCertId").references("id").inTable(TableName.SshCertificate).onDelete("CASCADE");
|
||||||
|
t.binary("encryptedCertificate").notNullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
await createOnUpdateTrigger(knex, TableName.SshCertificateBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.dropTableIfExists(TableName.SshCertificateBody);
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.SshCertificateBody);
|
||||||
|
|
||||||
|
await knex.schema.dropTableIfExists(TableName.SshCertificate);
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.SshCertificate);
|
||||||
|
|
||||||
|
await knex.schema.dropTableIfExists(TableName.SshCertificateTemplate);
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.SshCertificateTemplate);
|
||||||
|
|
||||||
|
await knex.schema.dropTableIfExists(TableName.SshCertificateAuthoritySecret);
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.SshCertificateAuthoritySecret);
|
||||||
|
|
||||||
|
await knex.schema.dropTableIfExists(TableName.SshCertificateAuthority);
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.SshCertificateAuthority);
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (!(await knex.schema.hasTable(TableName.ResourceMetadata))) {
|
||||||
|
await knex.schema.createTable(TableName.ResourceMetadata, (tb) => {
|
||||||
|
tb.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
tb.string("key").notNullable();
|
||||||
|
tb.string("value", 1020).notNullable();
|
||||||
|
tb.uuid("orgId").notNullable();
|
||||||
|
tb.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||||
|
tb.uuid("userId");
|
||||||
|
tb.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||||
|
tb.uuid("identityId");
|
||||||
|
tb.foreign("identityId").references("id").inTable(TableName.Identity).onDelete("CASCADE");
|
||||||
|
tb.uuid("secretId");
|
||||||
|
tb.foreign("secretId").references("id").inTable(TableName.SecretV2).onDelete("CASCADE");
|
||||||
|
tb.timestamps(true, true, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasSecretMetadataField = await knex.schema.hasColumn(TableName.SecretApprovalRequestSecretV2, "secretMetadata");
|
||||||
|
if (!hasSecretMetadataField) {
|
||||||
|
await knex.schema.alterTable(TableName.SecretApprovalRequestSecretV2, (t) => {
|
||||||
|
t.jsonb("secretMetadata");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.dropTableIfExists(TableName.ResourceMetadata);
|
||||||
|
|
||||||
|
const hasSecretMetadataField = await knex.schema.hasColumn(TableName.SecretApprovalRequestSecretV2, "secretMetadata");
|
||||||
|
if (hasSecretMetadataField) {
|
||||||
|
await knex.schema.alterTable(TableName.SecretApprovalRequestSecretV2, (t) => {
|
||||||
|
t.dropColumn("secretMetadata");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
28
backend/src/db/migrations/20241218181018_app-connection.ts
Normal file
28
backend/src/db/migrations/20241218181018_app-connection.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "@app/db/schemas";
|
||||||
|
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "@app/db/utils";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (!(await knex.schema.hasTable(TableName.AppConnection))) {
|
||||||
|
await knex.schema.createTable(TableName.AppConnection, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.string("name", 32).notNullable();
|
||||||
|
t.string("description");
|
||||||
|
t.string("app").notNullable();
|
||||||
|
t.string("method").notNullable();
|
||||||
|
t.binary("encryptedCredentials").notNullable();
|
||||||
|
t.integer("version").defaultTo(1).notNullable();
|
||||||
|
t.uuid("orgId").notNullable();
|
||||||
|
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
await createOnUpdateTrigger(knex, TableName.AppConnection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.dropTableIfExists(TableName.AppConnection);
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.AppConnection);
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
// find any duplicate group names within organizations
|
||||||
|
const duplicates = await knex(TableName.Groups)
|
||||||
|
.select("orgId", "name")
|
||||||
|
.count("* as count")
|
||||||
|
.groupBy("orgId", "name")
|
||||||
|
.having(knex.raw("count(*) > 1"));
|
||||||
|
|
||||||
|
// for each set of duplicates, update all but one with a numbered suffix
|
||||||
|
for await (const duplicate of duplicates) {
|
||||||
|
const groups = await knex(TableName.Groups)
|
||||||
|
.select("id", "name")
|
||||||
|
.where({
|
||||||
|
orgId: duplicate.orgId,
|
||||||
|
name: duplicate.name
|
||||||
|
})
|
||||||
|
.orderBy("createdAt", "asc"); // keep original name for oldest group
|
||||||
|
|
||||||
|
// skip the first (oldest) group, rename others with numbered suffix
|
||||||
|
for (let i = 1; i < groups.length; i += 1) {
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await knex(TableName.Groups)
|
||||||
|
.where("id", groups[i].id)
|
||||||
|
.update({
|
||||||
|
name: `${groups[i].name} (${i})`,
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore TS doesn't know about Knex's timestamp types
|
||||||
|
updatedAt: new Date()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the unique constraint
|
||||||
|
await knex.schema.alterTable(TableName.Groups, (t) => {
|
||||||
|
t.unique(["orgId", "name"]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
// Remove the unique constraint
|
||||||
|
await knex.schema.alterTable(TableName.Groups, (t) => {
|
||||||
|
t.dropUnique(["orgId", "name"]);
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasEnforceCapitalizationCol = await knex.schema.hasColumn(TableName.Project, "enforceCapitalization");
|
||||||
|
const hasAutoCapitalizationCol = await knex.schema.hasColumn(TableName.Project, "autoCapitalization");
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.Project, (t) => {
|
||||||
|
if (!hasEnforceCapitalizationCol) {
|
||||||
|
t.boolean("enforceCapitalization").defaultTo(false).notNullable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasAutoCapitalizationCol) {
|
||||||
|
t.boolean("autoCapitalization").defaultTo(false).alter();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasEnforceCapitalizationCol = await knex.schema.hasColumn(TableName.Project, "enforceCapitalization");
|
||||||
|
const hasAutoCapitalizationCol = await knex.schema.hasColumn(TableName.Project, "autoCapitalization");
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.Project, (t) => {
|
||||||
|
if (hasEnforceCapitalizationCol) {
|
||||||
|
t.dropColumn("enforceCapitalization");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasAutoCapitalizationCol) {
|
||||||
|
t.boolean("autoCapitalization").defaultTo(true).alter();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
50
backend/src/db/migrations/20250122055102_secret-sync.ts
Normal file
50
backend/src/db/migrations/20250122055102_secret-sync.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "@app/db/schemas";
|
||||||
|
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "@app/db/utils";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (!(await knex.schema.hasTable(TableName.SecretSync))) {
|
||||||
|
await knex.schema.createTable(TableName.SecretSync, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.string("name", 32).notNullable();
|
||||||
|
t.string("description");
|
||||||
|
t.string("destination").notNullable();
|
||||||
|
t.boolean("isAutoSyncEnabled").notNullable().defaultTo(true);
|
||||||
|
t.integer("version").defaultTo(1).notNullable();
|
||||||
|
t.jsonb("destinationConfig").notNullable();
|
||||||
|
t.jsonb("syncOptions").notNullable();
|
||||||
|
// we're including projectId in addition to folder ID because we allow folderId to be null (if the folder
|
||||||
|
// is deleted), to preserve sync configuration
|
||||||
|
t.string("projectId").notNullable();
|
||||||
|
t.foreign("projectId").references("id").inTable(TableName.Project).onDelete("CASCADE");
|
||||||
|
t.uuid("folderId");
|
||||||
|
t.foreign("folderId").references("id").inTable(TableName.SecretFolder).onDelete("SET NULL");
|
||||||
|
t.uuid("connectionId").notNullable();
|
||||||
|
t.foreign("connectionId").references("id").inTable(TableName.AppConnection);
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
// sync secrets to destination
|
||||||
|
t.string("syncStatus");
|
||||||
|
t.string("lastSyncJobId");
|
||||||
|
t.string("lastSyncMessage");
|
||||||
|
t.datetime("lastSyncedAt");
|
||||||
|
// import secrets from destination
|
||||||
|
t.string("importStatus");
|
||||||
|
t.string("lastImportJobId");
|
||||||
|
t.string("lastImportMessage");
|
||||||
|
t.datetime("lastImportedAt");
|
||||||
|
// remove secrets from destination
|
||||||
|
t.string("removeStatus");
|
||||||
|
t.string("lastRemoveJobId");
|
||||||
|
t.string("lastRemoveMessage");
|
||||||
|
t.datetime("lastRemovedAt");
|
||||||
|
});
|
||||||
|
|
||||||
|
await createOnUpdateTrigger(knex, TableName.SecretSync);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.dropTableIfExists(TableName.SecretSync);
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.SecretSync);
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasManageGroupMembershipsCol = await knex.schema.hasColumn(TableName.OidcConfig, "manageGroupMemberships");
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.OidcConfig, (tb) => {
|
||||||
|
if (!hasManageGroupMembershipsCol) {
|
||||||
|
tb.boolean("manageGroupMemberships").notNullable().defaultTo(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasManageGroupMembershipsCol = await knex.schema.hasColumn(TableName.OidcConfig, "manageGroupMemberships");
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.OidcConfig, (t) => {
|
||||||
|
if (hasManageGroupMembershipsCol) {
|
||||||
|
t.dropColumn("manageGroupMemberships");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "@app/db/schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.alterTable(TableName.AppConnection, (t) => {
|
||||||
|
t.unique(["orgId", "name"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.SecretSync, (t) => {
|
||||||
|
t.unique(["projectId", "name"]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.alterTable(TableName.AppConnection, (t) => {
|
||||||
|
t.dropUnique(["orgId", "name"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.SecretSync, (t) => {
|
||||||
|
t.dropUnique(["projectId", "name"]);
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasTable = await knex.schema.hasTable(TableName.IdentityGcpAuth);
|
||||||
|
const hasAllowedProjectsColumn = await knex.schema.hasColumn(TableName.IdentityGcpAuth, "allowedProjects");
|
||||||
|
const hasAllowedServiceAccountsColumn = await knex.schema.hasColumn(
|
||||||
|
TableName.IdentityGcpAuth,
|
||||||
|
"allowedServiceAccounts"
|
||||||
|
);
|
||||||
|
const hasAllowedZones = await knex.schema.hasColumn(TableName.IdentityGcpAuth, "allowedZones");
|
||||||
|
if (hasTable) {
|
||||||
|
await knex.schema.alterTable(TableName.IdentityGcpAuth, (t) => {
|
||||||
|
if (hasAllowedProjectsColumn) t.string("allowedProjects", 2500).alter();
|
||||||
|
if (hasAllowedServiceAccountsColumn) t.string("allowedServiceAccounts", 5000).alter();
|
||||||
|
if (hasAllowedZones) t.string("allowedZones", 2500).alter();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasTable = await knex.schema.hasTable(TableName.IdentityGcpAuth);
|
||||||
|
const hasAllowedProjectsColumn = await knex.schema.hasColumn(TableName.IdentityGcpAuth, "allowedProjects");
|
||||||
|
const hasAllowedServiceAccountsColumn = await knex.schema.hasColumn(
|
||||||
|
TableName.IdentityGcpAuth,
|
||||||
|
"allowedServiceAccounts"
|
||||||
|
);
|
||||||
|
const hasAllowedZones = await knex.schema.hasColumn(TableName.IdentityGcpAuth, "allowedZones");
|
||||||
|
if (hasTable) {
|
||||||
|
await knex.schema.alterTable(TableName.IdentityGcpAuth, (t) => {
|
||||||
|
if (hasAllowedProjectsColumn) t.string("allowedProjects").alter();
|
||||||
|
if (hasAllowedServiceAccountsColumn) t.string("allowedServiceAccounts").alter();
|
||||||
|
if (hasAllowedZones) t.string("allowedZones").alter();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,8 @@ export const AccessApprovalPoliciesSchema = z.object({
|
|||||||
envId: z.string().uuid(),
|
envId: z.string().uuid(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date(),
|
updatedAt: z.date(),
|
||||||
enforcementLevel: z.string().default("hard")
|
enforcementLevel: z.string().default("hard"),
|
||||||
|
deletedAt: z.date().nullable().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TAccessApprovalPolicies = z.infer<typeof AccessApprovalPoliciesSchema>;
|
export type TAccessApprovalPolicies = z.infer<typeof AccessApprovalPoliciesSchema>;
|
||||||
|
27
backend/src/db/schemas/app-connections.ts
Normal file
27
backend/src/db/schemas/app-connections.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// 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 AppConnectionsSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
name: z.string(),
|
||||||
|
description: z.string().nullable().optional(),
|
||||||
|
app: z.string(),
|
||||||
|
method: z.string(),
|
||||||
|
encryptedCredentials: zodBuffer,
|
||||||
|
version: z.number().default(1),
|
||||||
|
orgId: z.string().uuid(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TAppConnections = z.infer<typeof AppConnectionsSchema>;
|
||||||
|
export type TAppConnectionsInsert = Omit<z.input<typeof AppConnectionsSchema>, TImmutableDBKeys>;
|
||||||
|
export type TAppConnectionsUpdate = Partial<Omit<z.input<typeof AppConnectionsSchema>, TImmutableDBKeys>>;
|
@ -12,11 +12,12 @@ import { TImmutableDBKeys } from "./models";
|
|||||||
export const CertificateTemplateEstConfigsSchema = z.object({
|
export const CertificateTemplateEstConfigsSchema = z.object({
|
||||||
id: z.string().uuid(),
|
id: z.string().uuid(),
|
||||||
certificateTemplateId: z.string().uuid(),
|
certificateTemplateId: z.string().uuid(),
|
||||||
encryptedCaChain: zodBuffer,
|
encryptedCaChain: zodBuffer.nullable().optional(),
|
||||||
hashedPassphrase: z.string(),
|
hashedPassphrase: z.string(),
|
||||||
isEnabled: z.boolean(),
|
isEnabled: z.boolean(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date()
|
updatedAt: z.date(),
|
||||||
|
disableBootstrapCertValidation: z.boolean().default(false)
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TCertificateTemplateEstConfigs = z.infer<typeof CertificateTemplateEstConfigsSchema>;
|
export type TCertificateTemplateEstConfigs = z.infer<typeof CertificateTemplateEstConfigsSchema>;
|
||||||
|
@ -20,7 +20,8 @@ export const IdentityAccessTokensSchema = z.object({
|
|||||||
identityId: z.string().uuid(),
|
identityId: z.string().uuid(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date(),
|
updatedAt: z.date(),
|
||||||
name: z.string().nullable().optional()
|
name: z.string().nullable().optional(),
|
||||||
|
authMethod: z.string()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TIdentityAccessTokens = z.infer<typeof IdentityAccessTokensSchema>;
|
export type TIdentityAccessTokens = z.infer<typeof IdentityAccessTokensSchema>;
|
||||||
|
@ -17,9 +17,9 @@ export const IdentityGcpAuthsSchema = z.object({
|
|||||||
updatedAt: z.date(),
|
updatedAt: z.date(),
|
||||||
identityId: z.string().uuid(),
|
identityId: z.string().uuid(),
|
||||||
type: z.string(),
|
type: z.string(),
|
||||||
allowedServiceAccounts: z.string(),
|
allowedServiceAccounts: z.string().nullable().optional(),
|
||||||
allowedProjects: z.string(),
|
allowedProjects: z.string().nullable().optional(),
|
||||||
allowedZones: z.string()
|
allowedZones: z.string().nullable().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TIdentityGcpAuths = z.infer<typeof IdentityGcpAuthsSchema>;
|
export type TIdentityGcpAuths = z.infer<typeof IdentityGcpAuthsSchema>;
|
||||||
|
33
backend/src/db/schemas/identity-jwt-auths.ts
Normal file
33
backend/src/db/schemas/identity-jwt-auths.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// 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 IdentityJwtAuthsSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
accessTokenTTL: z.coerce.number().default(7200),
|
||||||
|
accessTokenMaxTTL: z.coerce.number().default(7200),
|
||||||
|
accessTokenNumUsesLimit: z.coerce.number().default(0),
|
||||||
|
accessTokenTrustedIps: z.unknown(),
|
||||||
|
identityId: z.string().uuid(),
|
||||||
|
configurationType: z.string(),
|
||||||
|
jwksUrl: z.string(),
|
||||||
|
encryptedJwksCaCert: zodBuffer,
|
||||||
|
encryptedPublicKeys: zodBuffer,
|
||||||
|
boundIssuer: z.string(),
|
||||||
|
boundAudiences: z.string(),
|
||||||
|
boundClaims: z.unknown(),
|
||||||
|
boundSubject: z.string(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TIdentityJwtAuths = z.infer<typeof IdentityJwtAuthsSchema>;
|
||||||
|
export type TIdentityJwtAuthsInsert = Omit<z.input<typeof IdentityJwtAuthsSchema>, TImmutableDBKeys>;
|
||||||
|
export type TIdentityJwtAuthsUpdate = Partial<Omit<z.input<typeof IdentityJwtAuthsSchema>, TImmutableDBKeys>>;
|
@ -30,6 +30,7 @@ export * from "./identity-access-tokens";
|
|||||||
export * from "./identity-aws-auths";
|
export * from "./identity-aws-auths";
|
||||||
export * from "./identity-azure-auths";
|
export * from "./identity-azure-auths";
|
||||||
export * from "./identity-gcp-auths";
|
export * from "./identity-gcp-auths";
|
||||||
|
export * from "./identity-jwt-auths";
|
||||||
export * from "./identity-kubernetes-auths";
|
export * from "./identity-kubernetes-auths";
|
||||||
export * from "./identity-metadata";
|
export * from "./identity-metadata";
|
||||||
export * from "./identity-oidc-auths";
|
export * from "./identity-oidc-auths";
|
||||||
@ -64,10 +65,13 @@ export * from "./project-keys";
|
|||||||
export * from "./project-memberships";
|
export * from "./project-memberships";
|
||||||
export * from "./project-roles";
|
export * from "./project-roles";
|
||||||
export * from "./project-slack-configs";
|
export * from "./project-slack-configs";
|
||||||
|
export * from "./project-split-backfill-ids";
|
||||||
|
export * from "./project-templates";
|
||||||
export * from "./project-user-additional-privilege";
|
export * from "./project-user-additional-privilege";
|
||||||
export * from "./project-user-membership-roles";
|
export * from "./project-user-membership-roles";
|
||||||
export * from "./projects";
|
export * from "./projects";
|
||||||
export * from "./rate-limit";
|
export * from "./rate-limit";
|
||||||
|
export * from "./resource-metadata";
|
||||||
export * from "./saml-configs";
|
export * from "./saml-configs";
|
||||||
export * from "./scim-tokens";
|
export * from "./scim-tokens";
|
||||||
export * from "./secret-approval-policies";
|
export * from "./secret-approval-policies";
|
||||||
@ -104,7 +108,13 @@ export * from "./secrets";
|
|||||||
export * from "./secrets-v2";
|
export * from "./secrets-v2";
|
||||||
export * from "./service-tokens";
|
export * from "./service-tokens";
|
||||||
export * from "./slack-integrations";
|
export * from "./slack-integrations";
|
||||||
|
export * from "./ssh-certificate-authorities";
|
||||||
|
export * from "./ssh-certificate-authority-secrets";
|
||||||
|
export * from "./ssh-certificate-bodies";
|
||||||
|
export * from "./ssh-certificate-templates";
|
||||||
|
export * from "./ssh-certificates";
|
||||||
export * from "./super-admin";
|
export * from "./super-admin";
|
||||||
|
export * from "./totp-configs";
|
||||||
export * from "./trusted-ips";
|
export * from "./trusted-ips";
|
||||||
export * from "./user-actions";
|
export * from "./user-actions";
|
||||||
export * from "./user-aliases";
|
export * from "./user-aliases";
|
||||||
|
@ -11,7 +11,10 @@ import { TImmutableDBKeys } from "./models";
|
|||||||
|
|
||||||
export const KmsRootConfigSchema = z.object({
|
export const KmsRootConfigSchema = z.object({
|
||||||
id: z.string().uuid(),
|
id: z.string().uuid(),
|
||||||
encryptedRootKey: zodBuffer
|
encryptedRootKey: zodBuffer,
|
||||||
|
encryptionStrategy: z.string().default("SOFTWARE").nullable().optional(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TKmsRootConfig = z.infer<typeof KmsRootConfigSchema>;
|
export type TKmsRootConfig = z.infer<typeof KmsRootConfigSchema>;
|
||||||
|
@ -2,6 +2,11 @@ import { z } from "zod";
|
|||||||
|
|
||||||
export enum TableName {
|
export enum TableName {
|
||||||
Users = "users",
|
Users = "users",
|
||||||
|
SshCertificateAuthority = "ssh_certificate_authorities",
|
||||||
|
SshCertificateAuthoritySecret = "ssh_certificate_authority_secrets",
|
||||||
|
SshCertificateTemplate = "ssh_certificate_templates",
|
||||||
|
SshCertificate = "ssh_certificates",
|
||||||
|
SshCertificateBody = "ssh_certificate_bodies",
|
||||||
CertificateAuthority = "certificate_authorities",
|
CertificateAuthority = "certificate_authorities",
|
||||||
CertificateTemplateEstConfig = "certificate_template_est_configs",
|
CertificateTemplateEstConfig = "certificate_template_est_configs",
|
||||||
CertificateAuthorityCert = "certificate_authority_certs",
|
CertificateAuthorityCert = "certificate_authority_certs",
|
||||||
@ -41,6 +46,7 @@ export enum TableName {
|
|||||||
ProjectUserAdditionalPrivilege = "project_user_additional_privilege",
|
ProjectUserAdditionalPrivilege = "project_user_additional_privilege",
|
||||||
ProjectUserMembershipRole = "project_user_membership_roles",
|
ProjectUserMembershipRole = "project_user_membership_roles",
|
||||||
ProjectKeys = "project_keys",
|
ProjectKeys = "project_keys",
|
||||||
|
ProjectTemplates = "project_templates",
|
||||||
Secret = "secrets",
|
Secret = "secrets",
|
||||||
SecretReference = "secret_references",
|
SecretReference = "secret_references",
|
||||||
SecretSharing = "secret_sharing",
|
SecretSharing = "secret_sharing",
|
||||||
@ -67,12 +73,14 @@ export enum TableName {
|
|||||||
IdentityUaClientSecret = "identity_ua_client_secrets",
|
IdentityUaClientSecret = "identity_ua_client_secrets",
|
||||||
IdentityAwsAuth = "identity_aws_auths",
|
IdentityAwsAuth = "identity_aws_auths",
|
||||||
IdentityOidcAuth = "identity_oidc_auths",
|
IdentityOidcAuth = "identity_oidc_auths",
|
||||||
|
IdentityJwtAuth = "identity_jwt_auths",
|
||||||
IdentityOrgMembership = "identity_org_memberships",
|
IdentityOrgMembership = "identity_org_memberships",
|
||||||
IdentityProjectMembership = "identity_project_memberships",
|
IdentityProjectMembership = "identity_project_memberships",
|
||||||
IdentityProjectMembershipRole = "identity_project_membership_role",
|
IdentityProjectMembershipRole = "identity_project_membership_role",
|
||||||
IdentityProjectAdditionalPrivilege = "identity_project_additional_privilege",
|
IdentityProjectAdditionalPrivilege = "identity_project_additional_privilege",
|
||||||
// used by both identity and users
|
// used by both identity and users
|
||||||
IdentityMetadata = "identity_metadata",
|
IdentityMetadata = "identity_metadata",
|
||||||
|
ResourceMetadata = "resource_metadata",
|
||||||
ScimToken = "scim_tokens",
|
ScimToken = "scim_tokens",
|
||||||
AccessApprovalPolicy = "access_approval_policies",
|
AccessApprovalPolicy = "access_approval_policies",
|
||||||
AccessApprovalPolicyApprover = "access_approval_policies_approvers",
|
AccessApprovalPolicyApprover = "access_approval_policies_approvers",
|
||||||
@ -104,6 +112,7 @@ export enum TableName {
|
|||||||
SecretApprovalRequestSecretV2 = "secret_approval_requests_secrets_v2",
|
SecretApprovalRequestSecretV2 = "secret_approval_requests_secrets_v2",
|
||||||
SecretApprovalRequestSecretTagV2 = "secret_approval_request_secret_tags_v2",
|
SecretApprovalRequestSecretTagV2 = "secret_approval_request_secret_tags_v2",
|
||||||
SnapshotSecretV2 = "secret_snapshot_secrets_v2",
|
SnapshotSecretV2 = "secret_snapshot_secrets_v2",
|
||||||
|
ProjectSplitBackfillIds = "project_split_backfill_ids",
|
||||||
// junction tables with tags
|
// junction tables with tags
|
||||||
SecretV2JnTag = "secret_v2_tag_junction",
|
SecretV2JnTag = "secret_v2_tag_junction",
|
||||||
JnSecretTag = "secret_tag_junction",
|
JnSecretTag = "secret_tag_junction",
|
||||||
@ -116,11 +125,14 @@ export enum TableName {
|
|||||||
ExternalKms = "external_kms",
|
ExternalKms = "external_kms",
|
||||||
InternalKms = "internal_kms",
|
InternalKms = "internal_kms",
|
||||||
InternalKmsKeyVersion = "internal_kms_key_version",
|
InternalKmsKeyVersion = "internal_kms_key_version",
|
||||||
|
TotpConfig = "totp_configs",
|
||||||
// @depreciated
|
// @depreciated
|
||||||
KmsKeyVersion = "kms_key_versions",
|
KmsKeyVersion = "kms_key_versions",
|
||||||
WorkflowIntegrations = "workflow_integrations",
|
WorkflowIntegrations = "workflow_integrations",
|
||||||
SlackIntegrations = "slack_integrations",
|
SlackIntegrations = "slack_integrations",
|
||||||
ProjectSlackConfigs = "project_slack_configs"
|
ProjectSlackConfigs = "project_slack_configs",
|
||||||
|
AppConnection = "app_connections",
|
||||||
|
SecretSync = "secret_syncs"
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TImmutableDBKeys = "id" | "createdAt" | "updatedAt";
|
export type TImmutableDBKeys = "id" | "createdAt" | "updatedAt";
|
||||||
@ -189,10 +201,27 @@ export enum ProjectUpgradeStatus {
|
|||||||
|
|
||||||
export enum IdentityAuthMethod {
|
export enum IdentityAuthMethod {
|
||||||
TOKEN_AUTH = "token-auth",
|
TOKEN_AUTH = "token-auth",
|
||||||
Univeral = "universal-auth",
|
UNIVERSAL_AUTH = "universal-auth",
|
||||||
KUBERNETES_AUTH = "kubernetes-auth",
|
KUBERNETES_AUTH = "kubernetes-auth",
|
||||||
GCP_AUTH = "gcp-auth",
|
GCP_AUTH = "gcp-auth",
|
||||||
AWS_AUTH = "aws-auth",
|
AWS_AUTH = "aws-auth",
|
||||||
AZURE_AUTH = "azure-auth",
|
AZURE_AUTH = "azure-auth",
|
||||||
OIDC_AUTH = "oidc-auth"
|
OIDC_AUTH = "oidc-auth",
|
||||||
|
JWT_AUTH = "jwt-auth"
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ProjectType {
|
||||||
|
SecretManager = "secret-manager",
|
||||||
|
CertificateManager = "cert-manager",
|
||||||
|
KMS = "kms",
|
||||||
|
SSH = "ssh"
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ActionProjectType {
|
||||||
|
SecretManager = ProjectType.SecretManager,
|
||||||
|
CertificateManager = ProjectType.CertificateManager,
|
||||||
|
KMS = ProjectType.KMS,
|
||||||
|
SSH = ProjectType.SSH,
|
||||||
|
// project operations that happen on all types
|
||||||
|
Any = "any"
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,8 @@ export const OidcConfigsSchema = z.object({
|
|||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
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)
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TOidcConfigs = z.infer<typeof OidcConfigsSchema>;
|
export type TOidcConfigs = z.infer<typeof OidcConfigsSchema>;
|
||||||
|
@ -20,7 +20,9 @@ export const OrganizationsSchema = z.object({
|
|||||||
scimEnabled: z.boolean().default(false).nullable().optional(),
|
scimEnabled: z.boolean().default(false).nullable().optional(),
|
||||||
kmsDefaultKeyId: z.string().uuid().nullable().optional(),
|
kmsDefaultKeyId: z.string().uuid().nullable().optional(),
|
||||||
kmsEncryptedDataKey: zodBuffer.nullable().optional(),
|
kmsEncryptedDataKey: zodBuffer.nullable().optional(),
|
||||||
defaultMembershipRole: z.string().default("member")
|
defaultMembershipRole: z.string().default("member"),
|
||||||
|
enforceMfa: z.boolean().default(false),
|
||||||
|
selectedMfaMethod: z.string().nullable().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TOrganizations = z.infer<typeof OrganizationsSchema>;
|
export type TOrganizations = z.infer<typeof OrganizationsSchema>;
|
||||||
|
@ -15,7 +15,8 @@ export const ProjectRolesSchema = z.object({
|
|||||||
permissions: z.unknown(),
|
permissions: z.unknown(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date(),
|
updatedAt: z.date(),
|
||||||
projectId: z.string()
|
projectId: z.string(),
|
||||||
|
version: z.number().default(1)
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TProjectRoles = z.infer<typeof ProjectRolesSchema>;
|
export type TProjectRoles = z.infer<typeof ProjectRolesSchema>;
|
||||||
|
21
backend/src/db/schemas/project-split-backfill-ids.ts
Normal file
21
backend/src/db/schemas/project-split-backfill-ids.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// 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 ProjectSplitBackfillIdsSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
sourceProjectId: z.string(),
|
||||||
|
destinationProjectType: z.string(),
|
||||||
|
destinationProjectId: z.string()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TProjectSplitBackfillIds = z.infer<typeof ProjectSplitBackfillIdsSchema>;
|
||||||
|
export type TProjectSplitBackfillIdsInsert = Omit<z.input<typeof ProjectSplitBackfillIdsSchema>, TImmutableDBKeys>;
|
||||||
|
export type TProjectSplitBackfillIdsUpdate = Partial<
|
||||||
|
Omit<z.input<typeof ProjectSplitBackfillIdsSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
23
backend/src/db/schemas/project-templates.ts
Normal file
23
backend/src/db/schemas/project-templates.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 ProjectTemplatesSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
name: z.string(),
|
||||||
|
description: z.string().nullable().optional(),
|
||||||
|
roles: z.unknown(),
|
||||||
|
environments: z.unknown(),
|
||||||
|
orgId: z.string().uuid(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TProjectTemplates = z.infer<typeof ProjectTemplatesSchema>;
|
||||||
|
export type TProjectTemplatesInsert = Omit<z.input<typeof ProjectTemplatesSchema>, TImmutableDBKeys>;
|
||||||
|
export type TProjectTemplatesUpdate = Partial<Omit<z.input<typeof ProjectTemplatesSchema>, TImmutableDBKeys>>;
|
@ -13,7 +13,7 @@ export const ProjectsSchema = z.object({
|
|||||||
id: z.string(),
|
id: z.string(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
slug: z.string(),
|
slug: z.string(),
|
||||||
autoCapitalization: z.boolean().default(true).nullable().optional(),
|
autoCapitalization: z.boolean().default(false).nullable().optional(),
|
||||||
orgId: z.string().uuid(),
|
orgId: z.string().uuid(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date(),
|
updatedAt: z.date(),
|
||||||
@ -23,7 +23,10 @@ export const ProjectsSchema = z.object({
|
|||||||
kmsCertificateKeyId: z.string().uuid().nullable().optional(),
|
kmsCertificateKeyId: z.string().uuid().nullable().optional(),
|
||||||
auditLogsRetentionDays: z.number().nullable().optional(),
|
auditLogsRetentionDays: z.number().nullable().optional(),
|
||||||
kmsSecretManagerKeyId: z.string().uuid().nullable().optional(),
|
kmsSecretManagerKeyId: z.string().uuid().nullable().optional(),
|
||||||
kmsSecretManagerEncryptedDataKey: zodBuffer.nullable().optional()
|
kmsSecretManagerEncryptedDataKey: zodBuffer.nullable().optional(),
|
||||||
|
description: z.string().nullable().optional(),
|
||||||
|
type: z.string(),
|
||||||
|
enforceCapitalization: z.boolean().default(false)
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TProjects = z.infer<typeof ProjectsSchema>;
|
export type TProjects = z.infer<typeof ProjectsSchema>;
|
||||||
|
24
backend/src/db/schemas/resource-metadata.ts
Normal file
24
backend/src/db/schemas/resource-metadata.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 { TImmutableDBKeys } from "./models";
|
||||||
|
|
||||||
|
export const ResourceMetadataSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
key: z.string(),
|
||||||
|
value: z.string(),
|
||||||
|
orgId: z.string().uuid(),
|
||||||
|
userId: z.string().uuid().nullable().optional(),
|
||||||
|
identityId: z.string().uuid().nullable().optional(),
|
||||||
|
secretId: z.string().uuid().nullable().optional(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TResourceMetadata = z.infer<typeof ResourceMetadataSchema>;
|
||||||
|
export type TResourceMetadataInsert = Omit<z.input<typeof ResourceMetadataSchema>, TImmutableDBKeys>;
|
||||||
|
export type TResourceMetadataUpdate = Partial<Omit<z.input<typeof ResourceMetadataSchema>, TImmutableDBKeys>>;
|
@ -15,7 +15,8 @@ export const SecretApprovalPoliciesSchema = z.object({
|
|||||||
envId: z.string().uuid(),
|
envId: z.string().uuid(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date(),
|
updatedAt: z.date(),
|
||||||
enforcementLevel: z.string().default("hard")
|
enforcementLevel: z.string().default("hard"),
|
||||||
|
deletedAt: z.date().nullable().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretApprovalPolicies = z.infer<typeof SecretApprovalPoliciesSchema>;
|
export type TSecretApprovalPolicies = z.infer<typeof SecretApprovalPoliciesSchema>;
|
||||||
|
@ -24,7 +24,8 @@ export const SecretApprovalRequestsSecretsV2Schema = z.object({
|
|||||||
requestId: z.string().uuid(),
|
requestId: z.string().uuid(),
|
||||||
op: z.string(),
|
op: z.string(),
|
||||||
secretId: z.string().uuid().nullable().optional(),
|
secretId: z.string().uuid().nullable().optional(),
|
||||||
secretVersion: z.string().uuid().nullable().optional()
|
secretVersion: z.string().uuid().nullable().optional(),
|
||||||
|
secretMetadata: z.unknown().nullable().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretApprovalRequestsSecretsV2 = z.infer<typeof SecretApprovalRequestsSecretsV2Schema>;
|
export type TSecretApprovalRequestsSecretsV2 = z.infer<typeof SecretApprovalRequestsSecretsV2Schema>;
|
||||||
|
40
backend/src/db/schemas/secret-syncs.ts
Normal file
40
backend/src/db/schemas/secret-syncs.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// 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 SecretSyncsSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
name: z.string(),
|
||||||
|
description: z.string().nullable().optional(),
|
||||||
|
destination: z.string(),
|
||||||
|
isAutoSyncEnabled: z.boolean().default(true),
|
||||||
|
version: z.number().default(1),
|
||||||
|
destinationConfig: z.unknown(),
|
||||||
|
syncOptions: z.unknown(),
|
||||||
|
projectId: z.string(),
|
||||||
|
folderId: z.string().uuid().nullable().optional(),
|
||||||
|
connectionId: z.string().uuid(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date(),
|
||||||
|
syncStatus: z.string().nullable().optional(),
|
||||||
|
lastSyncJobId: z.string().nullable().optional(),
|
||||||
|
lastSyncMessage: z.string().nullable().optional(),
|
||||||
|
lastSyncedAt: z.date().nullable().optional(),
|
||||||
|
importStatus: z.string().nullable().optional(),
|
||||||
|
lastImportJobId: z.string().nullable().optional(),
|
||||||
|
lastImportMessage: z.string().nullable().optional(),
|
||||||
|
lastImportedAt: z.date().nullable().optional(),
|
||||||
|
removeStatus: z.string().nullable().optional(),
|
||||||
|
lastRemoveJobId: z.string().nullable().optional(),
|
||||||
|
lastRemoveMessage: z.string().nullable().optional(),
|
||||||
|
lastRemovedAt: z.date().nullable().optional()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TSecretSyncs = z.infer<typeof SecretSyncsSchema>;
|
||||||
|
export type TSecretSyncsInsert = Omit<z.input<typeof SecretSyncsSchema>, TImmutableDBKeys>;
|
||||||
|
export type TSecretSyncsUpdate = Partial<Omit<z.input<typeof SecretSyncsSchema>, TImmutableDBKeys>>;
|
24
backend/src/db/schemas/ssh-certificate-authorities.ts
Normal file
24
backend/src/db/schemas/ssh-certificate-authorities.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 { TImmutableDBKeys } from "./models";
|
||||||
|
|
||||||
|
export const SshCertificateAuthoritiesSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date(),
|
||||||
|
projectId: z.string(),
|
||||||
|
status: z.string(),
|
||||||
|
friendlyName: z.string(),
|
||||||
|
keyAlgorithm: z.string()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TSshCertificateAuthorities = z.infer<typeof SshCertificateAuthoritiesSchema>;
|
||||||
|
export type TSshCertificateAuthoritiesInsert = Omit<z.input<typeof SshCertificateAuthoritiesSchema>, TImmutableDBKeys>;
|
||||||
|
export type TSshCertificateAuthoritiesUpdate = Partial<
|
||||||
|
Omit<z.input<typeof SshCertificateAuthoritiesSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
27
backend/src/db/schemas/ssh-certificate-authority-secrets.ts
Normal file
27
backend/src/db/schemas/ssh-certificate-authority-secrets.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// 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 SshCertificateAuthoritySecretsSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date(),
|
||||||
|
sshCaId: z.string().uuid(),
|
||||||
|
encryptedPrivateKey: zodBuffer
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TSshCertificateAuthoritySecrets = z.infer<typeof SshCertificateAuthoritySecretsSchema>;
|
||||||
|
export type TSshCertificateAuthoritySecretsInsert = Omit<
|
||||||
|
z.input<typeof SshCertificateAuthoritySecretsSchema>,
|
||||||
|
TImmutableDBKeys
|
||||||
|
>;
|
||||||
|
export type TSshCertificateAuthoritySecretsUpdate = Partial<
|
||||||
|
Omit<z.input<typeof SshCertificateAuthoritySecretsSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
22
backend/src/db/schemas/ssh-certificate-bodies.ts
Normal file
22
backend/src/db/schemas/ssh-certificate-bodies.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// 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 SshCertificateBodiesSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date(),
|
||||||
|
sshCertId: z.string().uuid(),
|
||||||
|
encryptedCertificate: zodBuffer
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TSshCertificateBodies = z.infer<typeof SshCertificateBodiesSchema>;
|
||||||
|
export type TSshCertificateBodiesInsert = Omit<z.input<typeof SshCertificateBodiesSchema>, TImmutableDBKeys>;
|
||||||
|
export type TSshCertificateBodiesUpdate = Partial<Omit<z.input<typeof SshCertificateBodiesSchema>, TImmutableDBKeys>>;
|
30
backend/src/db/schemas/ssh-certificate-templates.ts
Normal file
30
backend/src/db/schemas/ssh-certificate-templates.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// 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 SshCertificateTemplatesSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date(),
|
||||||
|
sshCaId: z.string().uuid(),
|
||||||
|
status: z.string(),
|
||||||
|
name: z.string(),
|
||||||
|
ttl: z.string(),
|
||||||
|
maxTTL: z.string(),
|
||||||
|
allowedUsers: z.string().array(),
|
||||||
|
allowedHosts: z.string().array(),
|
||||||
|
allowUserCertificates: z.boolean(),
|
||||||
|
allowHostCertificates: z.boolean(),
|
||||||
|
allowCustomKeyIds: z.boolean()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TSshCertificateTemplates = z.infer<typeof SshCertificateTemplatesSchema>;
|
||||||
|
export type TSshCertificateTemplatesInsert = Omit<z.input<typeof SshCertificateTemplatesSchema>, TImmutableDBKeys>;
|
||||||
|
export type TSshCertificateTemplatesUpdate = Partial<
|
||||||
|
Omit<z.input<typeof SshCertificateTemplatesSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
26
backend/src/db/schemas/ssh-certificates.ts
Normal file
26
backend/src/db/schemas/ssh-certificates.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// 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 SshCertificatesSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date(),
|
||||||
|
sshCaId: z.string().uuid(),
|
||||||
|
sshCertificateTemplateId: z.string().uuid().nullable().optional(),
|
||||||
|
serialNumber: z.string(),
|
||||||
|
certType: z.string(),
|
||||||
|
principals: z.string().array(),
|
||||||
|
keyId: z.string(),
|
||||||
|
notBefore: z.date(),
|
||||||
|
notAfter: z.date()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TSshCertificates = z.infer<typeof SshCertificatesSchema>;
|
||||||
|
export type TSshCertificatesInsert = Omit<z.input<typeof SshCertificatesSchema>, TImmutableDBKeys>;
|
||||||
|
export type TSshCertificatesUpdate = Partial<Omit<z.input<typeof SshCertificatesSchema>, TImmutableDBKeys>>;
|
24
backend/src/db/schemas/totp-configs.ts
Normal file
24
backend/src/db/schemas/totp-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 TotpConfigsSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
userId: z.string().uuid(),
|
||||||
|
isVerified: z.boolean().default(false),
|
||||||
|
encryptedRecoveryCodes: zodBuffer,
|
||||||
|
encryptedSecret: zodBuffer,
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TTotpConfigs = z.infer<typeof TotpConfigsSchema>;
|
||||||
|
export type TTotpConfigsInsert = Omit<z.input<typeof TotpConfigsSchema>, TImmutableDBKeys>;
|
||||||
|
export type TTotpConfigsUpdate = Partial<Omit<z.input<typeof TotpConfigsSchema>, TImmutableDBKeys>>;
|
@ -26,7 +26,8 @@ export const UsersSchema = z.object({
|
|||||||
consecutiveFailedMfaAttempts: z.number().default(0).nullable().optional(),
|
consecutiveFailedMfaAttempts: z.number().default(0).nullable().optional(),
|
||||||
isLocked: z.boolean().default(false).nullable().optional(),
|
isLocked: z.boolean().default(false).nullable().optional(),
|
||||||
temporaryLockDateEnd: z.date().nullable().optional(),
|
temporaryLockDateEnd: z.date().nullable().optional(),
|
||||||
consecutiveFailedPasswordAttempts: z.number().default(0).nullable().optional()
|
consecutiveFailedPasswordAttempts: z.number().default(0).nullable().optional(),
|
||||||
|
selectedMfaMethod: z.string().nullable().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TUsers = z.infer<typeof UsersSchema>;
|
export type TUsers = z.infer<typeof UsersSchema>;
|
||||||
|
@ -4,7 +4,7 @@ import { Knex } from "knex";
|
|||||||
|
|
||||||
import { encryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
|
import { encryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
|
||||||
|
|
||||||
import { ProjectMembershipRole, SecretEncryptionAlgo, SecretKeyEncoding, TableName } from "../schemas";
|
import { ProjectMembershipRole, ProjectType, SecretEncryptionAlgo, SecretKeyEncoding, TableName } from "../schemas";
|
||||||
import { buildUserProjectKey, getUserPrivateKey, seedData1 } from "../seed-data";
|
import { buildUserProjectKey, getUserPrivateKey, seedData1 } from "../seed-data";
|
||||||
|
|
||||||
export const DEFAULT_PROJECT_ENVS = [
|
export const DEFAULT_PROJECT_ENVS = [
|
||||||
@ -24,6 +24,7 @@ export async function seed(knex: Knex): Promise<void> {
|
|||||||
name: seedData1.project.name,
|
name: seedData1.project.name,
|
||||||
orgId: seedData1.organization.id,
|
orgId: seedData1.organization.id,
|
||||||
slug: "first-project",
|
slug: "first-project",
|
||||||
|
type: ProjectType.SecretManager,
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
id: seedData1.project.id
|
id: seedData1.project.id
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Knex } from "knex";
|
import { Knex } from "knex";
|
||||||
|
|
||||||
import { ProjectMembershipRole, ProjectVersion, TableName } from "../schemas";
|
import { ProjectMembershipRole, ProjectType, ProjectVersion, TableName } from "../schemas";
|
||||||
import { seedData1 } from "../seed-data";
|
import { seedData1 } from "../seed-data";
|
||||||
|
|
||||||
export const DEFAULT_PROJECT_ENVS = [
|
export const DEFAULT_PROJECT_ENVS = [
|
||||||
@ -16,6 +16,7 @@ export async function seed(knex: Knex): Promise<void> {
|
|||||||
orgId: seedData1.organization.id,
|
orgId: seedData1.organization.id,
|
||||||
slug: seedData1.projectV3.slug,
|
slug: seedData1.projectV3.slug,
|
||||||
version: ProjectVersion.V3,
|
version: ProjectVersion.V3,
|
||||||
|
type: ProjectType.SecretManager,
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
id: seedData1.projectV3.id
|
id: seedData1.projectV3.id
|
||||||
|
@ -16,7 +16,7 @@ export async function seed(knex: Knex): Promise<void> {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
id: seedData1.machineIdentity.id,
|
id: seedData1.machineIdentity.id,
|
||||||
name: seedData1.machineIdentity.name,
|
name: seedData1.machineIdentity.name,
|
||||||
authMethod: IdentityAuthMethod.Univeral
|
authMethod: IdentityAuthMethod.UNIVERSAL_AUTH
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
const identityUa = await knex(TableName.IdentityUniversalAuth)
|
const identityUa = await knex(TableName.IdentityUniversalAuth)
|
||||||
|
@ -2,6 +2,9 @@ import { Knex } from "knex";
|
|||||||
|
|
||||||
import { TableName } from "./schemas";
|
import { TableName } from "./schemas";
|
||||||
|
|
||||||
|
interface PgTriggerResult {
|
||||||
|
rows: Array<{ exists: boolean }>;
|
||||||
|
}
|
||||||
export const createJunctionTable = (knex: Knex, tableName: TableName, table1Name: TableName, table2Name: TableName) =>
|
export const createJunctionTable = (knex: Knex, tableName: TableName, table1Name: TableName, table2Name: TableName) =>
|
||||||
knex.schema.createTable(tableName, (table) => {
|
knex.schema.createTable(tableName, (table) => {
|
||||||
table.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
table.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
@ -28,13 +31,26 @@ DROP FUNCTION IF EXISTS on_update_timestamp() CASCADE;
|
|||||||
|
|
||||||
// we would be using this to apply updatedAt where ever we wanta
|
// we would be using this to apply updatedAt where ever we wanta
|
||||||
// remember to set `timestamps(true,true,true)` before this on schema
|
// remember to set `timestamps(true,true,true)` before this on schema
|
||||||
export const createOnUpdateTrigger = (knex: Knex, tableName: string) =>
|
export const createOnUpdateTrigger = async (knex: Knex, tableName: string) => {
|
||||||
knex.raw(`
|
const triggerExists = await knex.raw<PgTriggerResult>(`
|
||||||
CREATE TRIGGER "${tableName}_updatedAt"
|
SELECT EXISTS (
|
||||||
BEFORE UPDATE ON ${tableName}
|
SELECT 1
|
||||||
FOR EACH ROW
|
FROM pg_trigger
|
||||||
EXECUTE PROCEDURE on_update_timestamp();
|
WHERE tgname = '${tableName}_updatedAt'
|
||||||
`);
|
);
|
||||||
|
`);
|
||||||
|
|
||||||
|
if (!triggerExists?.rows?.[0]?.exists) {
|
||||||
|
return knex.raw(`
|
||||||
|
CREATE TRIGGER "${tableName}_updatedAt"
|
||||||
|
BEFORE UPDATE ON ${tableName}
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE PROCEDURE on_update_timestamp();
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
export const dropOnUpdateTrigger = (knex: Knex, tableName: string) =>
|
export const dropOnUpdateTrigger = (knex: Knex, tableName: string) =>
|
||||||
knex.raw(`DROP TRIGGER IF EXISTS "${tableName}_updatedAt" ON ${tableName}`);
|
knex.raw(`DROP TRIGGER IF EXISTS "${tableName}_updatedAt" ON ${tableName}`);
|
||||||
|
@ -109,7 +109,8 @@ export const registerAccessApprovalRequestRouter = async (server: FastifyZodProv
|
|||||||
approvers: z.string().array(),
|
approvers: z.string().array(),
|
||||||
secretPath: z.string().nullish(),
|
secretPath: z.string().nullish(),
|
||||||
envId: z.string(),
|
envId: z.string(),
|
||||||
enforcementLevel: z.string()
|
enforcementLevel: z.string(),
|
||||||
|
deletedAt: z.date().nullish()
|
||||||
}),
|
}),
|
||||||
reviewers: z
|
reviewers: z
|
||||||
.object({
|
.object({
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import ms from "ms";
|
import ms from "ms";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
@ -8,6 +7,7 @@ import { 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 { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
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 { SanitizedDynamicSecretSchema } from "@app/server/routes/sanitizedSchemas";
|
import { SanitizedDynamicSecretSchema } from "@app/server/routes/sanitizedSchemas";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
@ -48,15 +48,7 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
|||||||
.nullable(),
|
.nullable(),
|
||||||
path: z.string().describe(DYNAMIC_SECRETS.CREATE.path).trim().default("/").transform(removeTrailingSlash),
|
path: z.string().describe(DYNAMIC_SECRETS.CREATE.path).trim().default("/").transform(removeTrailingSlash),
|
||||||
environmentSlug: z.string().describe(DYNAMIC_SECRETS.CREATE.environmentSlug).min(1),
|
environmentSlug: z.string().describe(DYNAMIC_SECRETS.CREATE.environmentSlug).min(1),
|
||||||
name: z
|
name: slugSchema({ min: 1, max: 64, field: "Name" }).describe(DYNAMIC_SECRETS.CREATE.name)
|
||||||
.string()
|
|
||||||
.describe(DYNAMIC_SECRETS.CREATE.name)
|
|
||||||
.min(1)
|
|
||||||
.toLowerCase()
|
|
||||||
.max(64)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid"
|
|
||||||
})
|
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
|
@ -4,9 +4,15 @@ import { ExternalKmsSchema, 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 {
|
import {
|
||||||
ExternalKmsAwsSchema,
|
ExternalKmsAwsSchema,
|
||||||
|
ExternalKmsGcpCredentialSchema,
|
||||||
|
ExternalKmsGcpSchema,
|
||||||
ExternalKmsInputSchema,
|
ExternalKmsInputSchema,
|
||||||
ExternalKmsInputUpdateSchema
|
ExternalKmsInputUpdateSchema,
|
||||||
|
KmsGcpKeyFetchAuthType,
|
||||||
|
KmsProviders,
|
||||||
|
TExternalKmsGcpCredentialSchema
|
||||||
} from "@app/ee/services/external-kms/providers/model";
|
} from "@app/ee/services/external-kms/providers/model";
|
||||||
|
import { NotFoundError } from "@app/lib/errors";
|
||||||
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";
|
||||||
@ -44,7 +50,8 @@ const sanitizedExternalSchemaForGetById = KmsKeysSchema.extend({
|
|||||||
statusDetails: true,
|
statusDetails: true,
|
||||||
provider: true
|
provider: true
|
||||||
}).extend({
|
}).extend({
|
||||||
providerInput: ExternalKmsAwsSchema
|
// for GCP, we don't return the credential object as it is sensitive data that should not be exposed
|
||||||
|
providerInput: z.union([ExternalKmsAwsSchema, ExternalKmsGcpSchema.pick({ gcpRegion: true, keyName: true })])
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -286,4 +293,67 @@ export const registerExternalKmsRouter = async (server: FastifyZodProvider) => {
|
|||||||
return { externalKms };
|
return { externalKms };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: "POST",
|
||||||
|
url: "/gcp/keys",
|
||||||
|
config: {
|
||||||
|
rateLimit: writeLimit
|
||||||
|
},
|
||||||
|
schema: {
|
||||||
|
body: z.discriminatedUnion("authMethod", [
|
||||||
|
z.object({
|
||||||
|
authMethod: z.literal(KmsGcpKeyFetchAuthType.Credential),
|
||||||
|
region: z.string().trim().min(1),
|
||||||
|
credential: ExternalKmsGcpCredentialSchema
|
||||||
|
}),
|
||||||
|
z.object({
|
||||||
|
authMethod: z.literal(KmsGcpKeyFetchAuthType.Kms),
|
||||||
|
region: z.string().trim().min(1),
|
||||||
|
kmsId: z.string().trim().min(1)
|
||||||
|
})
|
||||||
|
]),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
keys: z.string().array()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const { region, authMethod } = req.body;
|
||||||
|
let credentialJson: TExternalKmsGcpCredentialSchema | undefined;
|
||||||
|
|
||||||
|
if (authMethod === KmsGcpKeyFetchAuthType.Credential) {
|
||||||
|
credentialJson = req.body.credential;
|
||||||
|
} else if (authMethod === KmsGcpKeyFetchAuthType.Kms) {
|
||||||
|
const externalKms = await server.services.externalKms.findById({
|
||||||
|
actor: req.permission.type,
|
||||||
|
actorId: req.permission.id,
|
||||||
|
actorAuthMethod: req.permission.authMethod,
|
||||||
|
actorOrgId: req.permission.orgId,
|
||||||
|
id: req.body.kmsId
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!externalKms || externalKms.external.provider !== KmsProviders.Gcp) {
|
||||||
|
throw new NotFoundError({ message: "KMS not found or not of type GCP" });
|
||||||
|
}
|
||||||
|
|
||||||
|
credentialJson = externalKms.external.providerInput.credential as TExternalKmsGcpCredentialSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!credentialJson) {
|
||||||
|
throw new NotFoundError({
|
||||||
|
message: "Something went wrong while fetching the GCP credential, please check inputs and try again"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const results = await server.services.externalKms.fetchGcpKeys({
|
||||||
|
credential: credentialJson,
|
||||||
|
gcpRegion: region
|
||||||
|
});
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
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 { GROUPS } from "@app/lib/api-docs";
|
import { GROUPS } from "@app/lib/api-docs";
|
||||||
|
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";
|
||||||
|
|
||||||
@ -14,15 +15,7 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
schema: {
|
schema: {
|
||||||
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: z
|
slug: slugSchema({ min: 5, max: 36 }).optional().describe(GROUPS.CREATE.slug),
|
||||||
.string()
|
|
||||||
.min(5)
|
|
||||||
.max(36)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
.describe(GROUPS.CREATE.slug),
|
|
||||||
role: z.string().trim().min(1).default(OrgMembershipRole.NoAccess).describe(GROUPS.CREATE.role)
|
role: z.string().trim().min(1).default(OrgMembershipRole.NoAccess).describe(GROUPS.CREATE.role)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
@ -100,14 +93,7 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
body: z
|
body: z
|
||||||
.object({
|
.object({
|
||||||
name: z.string().trim().min(1).describe(GROUPS.UPDATE.name),
|
name: z.string().trim().min(1).describe(GROUPS.UPDATE.name),
|
||||||
slug: z
|
slug: slugSchema({ min: 5, max: 36 }).describe(GROUPS.UPDATE.slug),
|
||||||
.string()
|
|
||||||
.min(5)
|
|
||||||
.max(36)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.describe(GROUPS.UPDATE.slug),
|
|
||||||
role: z.string().trim().min(1).describe(GROUPS.UPDATE.role)
|
role: z.string().trim().min(1).describe(GROUPS.UPDATE.role)
|
||||||
})
|
})
|
||||||
.partial(),
|
.partial(),
|
||||||
@ -165,7 +151,9 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
querystring: z.object({
|
querystring: z.object({
|
||||||
offset: z.coerce.number().min(0).max(100).default(0).describe(GROUPS.LIST_USERS.offset),
|
offset: z.coerce.number().min(0).max(100).default(0).describe(GROUPS.LIST_USERS.offset),
|
||||||
limit: z.coerce.number().min(1).max(100).default(10).describe(GROUPS.LIST_USERS.limit),
|
limit: z.coerce.number().min(1).max(100).default(10).describe(GROUPS.LIST_USERS.limit),
|
||||||
username: z.string().optional().describe(GROUPS.LIST_USERS.username)
|
username: z.string().trim().optional().describe(GROUPS.LIST_USERS.username),
|
||||||
|
search: z.string().trim().optional().describe(GROUPS.LIST_USERS.search),
|
||||||
|
filter: z.nativeEnum(EFilterReturnedUsers).optional().describe(GROUPS.LIST_USERS.filterUsers)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
@ -178,7 +166,8 @@ export const registerGroupRouter = async (server: FastifyZodProvider) => {
|
|||||||
})
|
})
|
||||||
.merge(
|
.merge(
|
||||||
z.object({
|
z.object({
|
||||||
isPartOfGroup: z.boolean()
|
isPartOfGroup: z.boolean(),
|
||||||
|
joinedGroupAt: z.date().nullable()
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.array(),
|
.array(),
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import { packRules } from "@casl/ability/extra";
|
|
||||||
import slugify from "@sindresorhus/slugify";
|
import slugify from "@sindresorhus/slugify";
|
||||||
import ms from "ms";
|
import ms from "ms";
|
||||||
import { z } from "zod";
|
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 { IDENTITY_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
|
import { IDENTITY_ADDITIONAL_PRIVILEGE } from "@app/lib/api-docs";
|
||||||
import { UnauthorizedError } from "@app/lib/errors";
|
import { UnauthorizedError } from "@app/lib/errors";
|
||||||
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";
|
||||||
|
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 {
|
import {
|
||||||
ProjectPermissionSchema,
|
ProjectPermissionSchema,
|
||||||
@ -33,17 +34,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
body: z.object({
|
body: z.object({
|
||||||
identityId: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.identityId),
|
identityId: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.identityId),
|
||||||
projectSlug: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.projectSlug),
|
projectSlug: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.projectSlug),
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 60 }).optional().describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.slug),
|
||||||
.string()
|
|
||||||
.min(1)
|
|
||||||
.max(60)
|
|
||||||
.trim()
|
|
||||||
.refine((val) => val.toLowerCase() === val, "Must be lowercase")
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.slug),
|
|
||||||
permissions: ProjectPermissionSchema.array()
|
permissions: ProjectPermissionSchema.array()
|
||||||
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.permissions)
|
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.permissions)
|
||||||
.optional(),
|
.optional(),
|
||||||
@ -77,9 +68,11 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
...req.body,
|
...req.body,
|
||||||
slug: req.body.slug ? slugify(req.body.slug) : slugify(alphaNumericNanoId(12)),
|
slug: req.body.slug ?? slugify(alphaNumericNanoId(12)),
|
||||||
isTemporary: false,
|
isTemporary: false,
|
||||||
permissions: JSON.stringify(packRules(permission))
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore-error this is valid ts
|
||||||
|
permissions: backfillPermissionV1SchemaToV2Schema(permission)
|
||||||
});
|
});
|
||||||
return { privilege };
|
return { privilege };
|
||||||
}
|
}
|
||||||
@ -101,17 +94,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
body: z.object({
|
body: z.object({
|
||||||
identityId: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.identityId),
|
identityId: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.identityId),
|
||||||
projectSlug: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.projectSlug),
|
projectSlug: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.projectSlug),
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 60 }).optional().describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.slug),
|
||||||
.string()
|
|
||||||
.min(1)
|
|
||||||
.max(60)
|
|
||||||
.trim()
|
|
||||||
.refine((val) => val.toLowerCase() === val, "Must be lowercase")
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.slug),
|
|
||||||
permissions: ProjectPermissionSchema.array()
|
permissions: ProjectPermissionSchema.array()
|
||||||
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.permissions)
|
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.CREATE.permissions)
|
||||||
.optional(),
|
.optional(),
|
||||||
@ -157,9 +140,11 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actorAuthMethod: req.permission.authMethod,
|
actorAuthMethod: req.permission.authMethod,
|
||||||
...req.body,
|
...req.body,
|
||||||
slug: req.body.slug ? slugify(req.body.slug) : slugify(alphaNumericNanoId(12)),
|
slug: req.body.slug ?? slugify(alphaNumericNanoId(12)),
|
||||||
isTemporary: true,
|
isTemporary: true,
|
||||||
permissions: JSON.stringify(packRules(permission))
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore-error this is valid ts
|
||||||
|
permissions: backfillPermissionV1SchemaToV2Schema(permission)
|
||||||
});
|
});
|
||||||
return { privilege };
|
return { privilege };
|
||||||
}
|
}
|
||||||
@ -185,16 +170,7 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
projectSlug: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.projectSlug),
|
projectSlug: z.string().min(1).describe(IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.projectSlug),
|
||||||
privilegeDetails: z
|
privilegeDetails: z
|
||||||
.object({
|
.object({
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 60 }).describe(IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.newSlug),
|
||||||
.string()
|
|
||||||
.min(1)
|
|
||||||
.max(60)
|
|
||||||
.trim()
|
|
||||||
.refine((val) => val.toLowerCase() === val, "Must be lowercase")
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid slug"
|
|
||||||
})
|
|
||||||
.describe(IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.newSlug),
|
|
||||||
permissions: ProjectPermissionSchema.array().describe(IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.permissions),
|
permissions: ProjectPermissionSchema.array().describe(IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.permissions),
|
||||||
privilegePermission: ProjectSpecificPrivilegePermissionSchema.describe(
|
privilegePermission: ProjectSpecificPrivilegePermissionSchema.describe(
|
||||||
IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.privilegePermission
|
IDENTITY_ADDITIONAL_PRIVILEGE.UPDATE.privilegePermission
|
||||||
@ -244,7 +220,13 @@ export const registerIdentityProjectAdditionalPrivilegeRouter = async (server: F
|
|||||||
projectSlug: req.body.projectSlug,
|
projectSlug: req.body.projectSlug,
|
||||||
data: {
|
data: {
|
||||||
...updatedInfo,
|
...updatedInfo,
|
||||||
permissions: permission ? JSON.stringify(packRules(permission)) : undefined
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore-error this is valid ts
|
||||||
|
permissions: permission
|
||||||
|
? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore-error this is valid ts
|
||||||
|
backfillPermissionV1SchemaToV2Schema(permission)
|
||||||
|
: undefined
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return { privilege };
|
return { privilege };
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { registerProjectTemplateRouter } from "@app/ee/routes/v1/project-template-router";
|
||||||
|
|
||||||
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 { registerAuditLogStreamRouter } from "./audit-log-stream-router";
|
import { registerAuditLogStreamRouter } from "./audit-log-stream-router";
|
||||||
@ -20,9 +22,13 @@ import { registerSecretApprovalPolicyRouter } from "./secret-approval-policy-rou
|
|||||||
import { registerSecretApprovalRequestRouter } from "./secret-approval-request-router";
|
import { registerSecretApprovalRequestRouter } from "./secret-approval-request-router";
|
||||||
import { registerSecretRotationProviderRouter } from "./secret-rotation-provider-router";
|
import { registerSecretRotationProviderRouter } from "./secret-rotation-provider-router";
|
||||||
import { registerSecretRotationRouter } from "./secret-rotation-router";
|
import { registerSecretRotationRouter } from "./secret-rotation-router";
|
||||||
|
import { registerSecretRouter } from "./secret-router";
|
||||||
import { registerSecretScanningRouter } from "./secret-scanning-router";
|
import { registerSecretScanningRouter } from "./secret-scanning-router";
|
||||||
import { registerSecretVersionRouter } from "./secret-version-router";
|
import { registerSecretVersionRouter } from "./secret-version-router";
|
||||||
import { registerSnapshotRouter } from "./snapshot-router";
|
import { registerSnapshotRouter } from "./snapshot-router";
|
||||||
|
import { registerSshCaRouter } from "./ssh-certificate-authority-router";
|
||||||
|
import { registerSshCertRouter } from "./ssh-certificate-router";
|
||||||
|
import { registerSshCertificateTemplateRouter } from "./ssh-certificate-template-router";
|
||||||
import { registerTrustedIpRouter } from "./trusted-ip-router";
|
import { registerTrustedIpRouter } from "./trusted-ip-router";
|
||||||
import { registerUserAdditionalPrivilegeRouter } from "./user-additional-privilege-router";
|
import { registerUserAdditionalPrivilegeRouter } from "./user-additional-privilege-router";
|
||||||
|
|
||||||
@ -66,6 +72,15 @@ export const registerV1EERoutes = async (server: FastifyZodProvider) => {
|
|||||||
{ prefix: "/pki" }
|
{ prefix: "/pki" }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
await server.register(
|
||||||
|
async (sshRouter) => {
|
||||||
|
await sshRouter.register(registerSshCaRouter, { prefix: "/ca" });
|
||||||
|
await sshRouter.register(registerSshCertRouter, { prefix: "/certificates" });
|
||||||
|
await sshRouter.register(registerSshCertificateTemplateRouter, { prefix: "/certificate-templates" });
|
||||||
|
},
|
||||||
|
{ prefix: "/ssh" }
|
||||||
|
);
|
||||||
|
|
||||||
await server.register(
|
await server.register(
|
||||||
async (ssoRouter) => {
|
async (ssoRouter) => {
|
||||||
await ssoRouter.register(registerSamlRouter);
|
await ssoRouter.register(registerSamlRouter);
|
||||||
@ -78,12 +93,13 @@ export const registerV1EERoutes = async (server: FastifyZodProvider) => {
|
|||||||
await server.register(registerLdapRouter, { prefix: "/ldap" });
|
await server.register(registerLdapRouter, { prefix: "/ldap" });
|
||||||
await server.register(registerSecretScanningRouter, { prefix: "/secret-scanning" });
|
await server.register(registerSecretScanningRouter, { prefix: "/secret-scanning" });
|
||||||
await server.register(registerSecretRotationRouter, { prefix: "/secret-rotations" });
|
await server.register(registerSecretRotationRouter, { prefix: "/secret-rotations" });
|
||||||
|
await server.register(registerSecretRouter, { prefix: "/secrets" });
|
||||||
await server.register(registerSecretVersionRouter, { prefix: "/secret" });
|
await server.register(registerSecretVersionRouter, { prefix: "/secret" });
|
||||||
await server.register(registerGroupRouter, { prefix: "/groups" });
|
await server.register(registerGroupRouter, { prefix: "/groups" });
|
||||||
await server.register(registerAuditLogStreamRouter, { prefix: "/audit-log-streams" });
|
await server.register(registerAuditLogStreamRouter, { prefix: "/audit-log-streams" });
|
||||||
|
await server.register(registerUserAdditionalPrivilegeRouter, { prefix: "/user-project-additional-privilege" });
|
||||||
await server.register(
|
await server.register(
|
||||||
async (privilegeRouter) => {
|
async (privilegeRouter) => {
|
||||||
await privilegeRouter.register(registerUserAdditionalPrivilegeRouter, { prefix: "/users" });
|
|
||||||
await privilegeRouter.register(registerIdentityProjectAdditionalPrivilegeRouter, { prefix: "/identity" });
|
await privilegeRouter.register(registerIdentityProjectAdditionalPrivilegeRouter, { prefix: "/identity" });
|
||||||
},
|
},
|
||||||
{ prefix: "/additional-privilege" }
|
{ prefix: "/additional-privilege" }
|
||||||
@ -92,4 +108,6 @@ export const registerV1EERoutes = async (server: FastifyZodProvider) => {
|
|||||||
await server.register(registerExternalKmsRouter, {
|
await server.register(registerExternalKmsRouter, {
|
||||||
prefix: "/external-kms"
|
prefix: "/external-kms"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await server.register(registerProjectTemplateRouter, { prefix: "/project-templates" });
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
import { Authenticator, Strategy } from "@fastify/passport";
|
import { Authenticator, Strategy } from "@fastify/passport";
|
||||||
import fastifySession from "@fastify/session";
|
import fastifySession from "@fastify/session";
|
||||||
import RedisStore from "connect-redis";
|
import RedisStore from "connect-redis";
|
||||||
import { Redis } from "ioredis";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { OidcConfigsSchema } from "@app/db/schemas/oidc-configs";
|
import { OidcConfigsSchema } from "@app/db/schemas/oidc-configs";
|
||||||
@ -21,7 +20,6 @@ import { AuthMode } from "@app/services/auth/auth-type";
|
|||||||
|
|
||||||
export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
||||||
const appCfg = getConfig();
|
const appCfg = getConfig();
|
||||||
const redis = new Redis(appCfg.REDIS_URL);
|
|
||||||
const passport = new Authenticator({ key: "oidc", userProperty: "passportUser" });
|
const passport = new Authenticator({ key: "oidc", userProperty: "passportUser" });
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -30,7 +28,7 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
|||||||
- Fastify session <> Redis structure is based on the ff: https://github.com/fastify/session/blob/master/examples/redis.js
|
- Fastify session <> Redis structure is based on the ff: https://github.com/fastify/session/blob/master/examples/redis.js
|
||||||
*/
|
*/
|
||||||
const redisStore = new RedisStore({
|
const redisStore = new RedisStore({
|
||||||
client: redis,
|
client: server.redis,
|
||||||
prefix: "oidc-session:",
|
prefix: "oidc-session:",
|
||||||
ttl: 600 // 10 minutes
|
ttl: 600 // 10 minutes
|
||||||
});
|
});
|
||||||
@ -155,7 +153,8 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
|||||||
discoveryURL: true,
|
discoveryURL: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
orgId: true,
|
orgId: true,
|
||||||
allowedEmailDomains: true
|
allowedEmailDomains: true,
|
||||||
|
manageGroupMemberships: true
|
||||||
}).extend({
|
}).extend({
|
||||||
clientId: z.string(),
|
clientId: z.string(),
|
||||||
clientSecret: z.string()
|
clientSecret: z.string()
|
||||||
@ -209,7 +208,8 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
|||||||
userinfoEndpoint: z.string().trim(),
|
userinfoEndpoint: z.string().trim(),
|
||||||
clientId: z.string().trim(),
|
clientId: z.string().trim(),
|
||||||
clientSecret: z.string().trim(),
|
clientSecret: z.string().trim(),
|
||||||
isActive: z.boolean()
|
isActive: z.boolean(),
|
||||||
|
manageGroupMemberships: z.boolean().optional()
|
||||||
})
|
})
|
||||||
.partial()
|
.partial()
|
||||||
.merge(z.object({ orgSlug: z.string() })),
|
.merge(z.object({ orgSlug: z.string() })),
|
||||||
@ -225,7 +225,8 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
|||||||
userinfoEndpoint: true,
|
userinfoEndpoint: true,
|
||||||
orgId: true,
|
orgId: true,
|
||||||
allowedEmailDomains: true,
|
allowedEmailDomains: true,
|
||||||
isActive: true
|
isActive: true,
|
||||||
|
manageGroupMemberships: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -274,7 +275,8 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
|||||||
clientId: z.string().trim(),
|
clientId: z.string().trim(),
|
||||||
clientSecret: z.string().trim(),
|
clientSecret: z.string().trim(),
|
||||||
isActive: z.boolean(),
|
isActive: z.boolean(),
|
||||||
orgSlug: z.string().trim()
|
orgSlug: z.string().trim(),
|
||||||
|
manageGroupMemberships: z.boolean().optional().default(false)
|
||||||
})
|
})
|
||||||
.superRefine((data, ctx) => {
|
.superRefine((data, ctx) => {
|
||||||
if (data.configurationType === OIDCConfigurationType.CUSTOM) {
|
if (data.configurationType === OIDCConfigurationType.CUSTOM) {
|
||||||
@ -336,7 +338,8 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
|||||||
userinfoEndpoint: true,
|
userinfoEndpoint: true,
|
||||||
orgId: true,
|
orgId: true,
|
||||||
isActive: true,
|
isActive: true,
|
||||||
allowedEmailDomains: true
|
allowedEmailDomains: true,
|
||||||
|
manageGroupMemberships: true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -352,4 +355,25 @@ export const registerOidcRouter = async (server: FastifyZodProvider) => {
|
|||||||
return oidc;
|
return oidc;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.route({
|
||||||
|
method: "GET",
|
||||||
|
url: "/manage-group-memberships",
|
||||||
|
schema: {
|
||||||
|
querystring: z.object({
|
||||||
|
orgId: z.string().trim().min(1, "Org ID is required")
|
||||||
|
}),
|
||||||
|
response: {
|
||||||
|
200: z.object({
|
||||||
|
isEnabled: z.boolean()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRequest: verifyAuth([AuthMode.JWT]),
|
||||||
|
handler: async (req) => {
|
||||||
|
const isEnabled = await server.services.oidc.isOidcManageGroupMembershipsEnabled(req.query.orgId, req.permission);
|
||||||
|
|
||||||
|
return { isEnabled };
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { OrgMembershipRole, OrgMembershipsSchema, OrgRolesSchema } from "@app/db/schemas";
|
import { OrgMembershipRole, OrgMembershipsSchema, OrgRolesSchema } from "@app/db/schemas";
|
||||||
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
import { readLimit, writeLimit } from "@app/server/config/rateLimiter";
|
||||||
|
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";
|
||||||
|
|
||||||
@ -18,19 +18,13 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
organizationId: z.string().trim()
|
organizationId: z.string().trim()
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
slug: slugSchema({ min: 1, max: 64 }).refine(
|
||||||
.string()
|
(val) => !Object.values(OrgMembershipRole).includes(val as OrgMembershipRole),
|
||||||
.min(1)
|
"Please choose a different slug, the slug you have entered is reserved"
|
||||||
.trim()
|
),
|
||||||
.refine(
|
|
||||||
(val) => !Object.values(OrgMembershipRole).includes(val as OrgMembershipRole),
|
|
||||||
"Please choose a different slug, the slug you have entered is reserved"
|
|
||||||
)
|
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid"
|
|
||||||
}),
|
|
||||||
name: z.string().trim(),
|
name: z.string().trim(),
|
||||||
description: z.string().trim().optional(),
|
description: z.string().trim().nullish(),
|
||||||
|
// TODO(scott): once UI refactored permissions: OrgPermissionSchema.array()
|
||||||
permissions: z.any().array()
|
permissions: z.any().array()
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
@ -94,19 +88,16 @@ export const registerOrgRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
roleId: z.string().trim()
|
roleId: z.string().trim()
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
// TODO: Switch to slugSchema after verifying correct methods with Akhil - Omar 11/24
|
||||||
.string()
|
slug: slugSchema({ min: 1, max: 64 })
|
||||||
.trim()
|
|
||||||
.optional()
|
|
||||||
.refine(
|
.refine(
|
||||||
(val) => typeof val !== "undefined" && !Object.keys(OrgMembershipRole).includes(val),
|
(val) => !Object.keys(OrgMembershipRole).includes(val),
|
||||||
"Please choose a different slug, the slug you have entered is reserved."
|
"Please choose a different slug, the slug you have entered is reserved."
|
||||||
)
|
)
|
||||||
.refine((val) => typeof val === "undefined" || slugify(val) === val, {
|
.optional(),
|
||||||
message: "Slug must be a valid"
|
|
||||||
}),
|
|
||||||
name: z.string().trim().optional(),
|
name: z.string().trim().optional(),
|
||||||
description: z.string().trim().optional(),
|
description: z.string().trim().nullish(),
|
||||||
|
// TODO(scott): once UI refactored permissions: OrgPermissionSchema.array().optional()
|
||||||
permissions: z.any().array().optional()
|
permissions: z.any().array().optional()
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
import { packRules } from "@casl/ability/extra";
|
import { packRules } from "@casl/ability/extra";
|
||||||
import slugify from "@sindresorhus/slugify";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
|
||||||
import { ProjectMembershipRole, ProjectMembershipsSchema, ProjectRolesSchema } from "@app/db/schemas";
|
import { ProjectMembershipRole, ProjectMembershipsSchema, ProjectRolesSchema } from "@app/db/schemas";
|
||||||
import { ProjectPermissionSchema } from "@app/ee/services/permission/project-permission";
|
import {
|
||||||
|
backfillPermissionV1SchemaToV2Schema,
|
||||||
|
ProjectPermissionV1Schema
|
||||||
|
} from "@app/ee/services/permission/project-permission";
|
||||||
import { PROJECT_ROLE } from "@app/lib/api-docs";
|
import { 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 { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||||
import { SanitizedRoleSchema } from "@app/server/routes/sanitizedSchemas";
|
import { SanitizedRoleSchemaV1 } from "@app/server/routes/sanitizedSchemas";
|
||||||
import { AuthMode } from "@app/services/auth/auth-type";
|
import { AuthMode } from "@app/services/auth/auth-type";
|
||||||
|
import { ProjectRoleServiceIdentifierType } from "@app/services/project-role/project-role-types";
|
||||||
|
|
||||||
export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
||||||
server.route({
|
server.route({
|
||||||
@ -28,26 +32,19 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
projectSlug: z.string().trim().describe(PROJECT_ROLE.CREATE.projectSlug)
|
projectSlug: z.string().trim().describe(PROJECT_ROLE.CREATE.projectSlug)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
slug: slugSchema({ max: 64 })
|
||||||
.string()
|
|
||||||
.toLowerCase()
|
|
||||||
.trim()
|
|
||||||
.min(1)
|
|
||||||
.refine(
|
.refine(
|
||||||
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
||||||
"Please choose a different slug, the slug you have entered is reserved"
|
"Please choose a different slug, the slug you have entered is reserved"
|
||||||
)
|
)
|
||||||
.refine((v) => slugify(v) === v, {
|
|
||||||
message: "Slug must be a valid"
|
|
||||||
})
|
|
||||||
.describe(PROJECT_ROLE.CREATE.slug),
|
.describe(PROJECT_ROLE.CREATE.slug),
|
||||||
name: z.string().min(1).trim().describe(PROJECT_ROLE.CREATE.name),
|
name: z.string().min(1).trim().describe(PROJECT_ROLE.CREATE.name),
|
||||||
description: z.string().trim().optional().describe(PROJECT_ROLE.CREATE.description),
|
description: z.string().trim().nullish().describe(PROJECT_ROLE.CREATE.description),
|
||||||
permissions: ProjectPermissionSchema.array().describe(PROJECT_ROLE.CREATE.permissions)
|
permissions: ProjectPermissionV1Schema.array().describe(PROJECT_ROLE.CREATE.permissions)
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
role: SanitizedRoleSchema
|
role: SanitizedRoleSchemaV1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -58,12 +55,16 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
projectSlug: req.params.projectSlug,
|
filter: {
|
||||||
|
type: ProjectRoleServiceIdentifierType.SLUG,
|
||||||
|
projectSlug: req.params.projectSlug
|
||||||
|
},
|
||||||
data: {
|
data: {
|
||||||
...req.body,
|
...req.body,
|
||||||
permissions: JSON.stringify(packRules(req.body.permissions))
|
permissions: JSON.stringify(packRules(backfillPermissionV1SchemaToV2Schema(req.body.permissions, true)))
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return { role };
|
return { role };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -86,28 +87,20 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
roleId: z.string().trim().describe(PROJECT_ROLE.UPDATE.roleId)
|
roleId: z.string().trim().describe(PROJECT_ROLE.UPDATE.roleId)
|
||||||
}),
|
}),
|
||||||
body: z.object({
|
body: z.object({
|
||||||
slug: z
|
slug: slugSchema({ max: 64 })
|
||||||
.string()
|
|
||||||
.toLowerCase()
|
|
||||||
.trim()
|
|
||||||
.optional()
|
|
||||||
.describe(PROJECT_ROLE.UPDATE.slug)
|
|
||||||
.refine(
|
.refine(
|
||||||
(val) =>
|
(val) => !Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
||||||
typeof val === "undefined" ||
|
|
||||||
!Object.values(ProjectMembershipRole).includes(val as ProjectMembershipRole),
|
|
||||||
"Please choose a different slug, the slug you have entered is reserved"
|
"Please choose a different slug, the slug you have entered is reserved"
|
||||||
)
|
)
|
||||||
.refine((val) => typeof val === "undefined" || slugify(val) === val, {
|
.describe(PROJECT_ROLE.UPDATE.slug)
|
||||||
message: "Slug must be a valid"
|
.optional(),
|
||||||
}),
|
|
||||||
name: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.name),
|
name: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.name),
|
||||||
description: z.string().trim().optional().describe(PROJECT_ROLE.UPDATE.description),
|
description: z.string().trim().nullish().describe(PROJECT_ROLE.UPDATE.description),
|
||||||
permissions: ProjectPermissionSchema.array().describe(PROJECT_ROLE.UPDATE.permissions).optional()
|
permissions: ProjectPermissionV1Schema.array().describe(PROJECT_ROLE.UPDATE.permissions).optional()
|
||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
role: SanitizedRoleSchema
|
role: SanitizedRoleSchemaV1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -118,11 +111,12 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
projectSlug: req.params.projectSlug,
|
|
||||||
roleId: req.params.roleId,
|
roleId: req.params.roleId,
|
||||||
data: {
|
data: {
|
||||||
...req.body,
|
...req.body,
|
||||||
permissions: req.body.permissions ? JSON.stringify(packRules(req.body.permissions)) : undefined
|
permissions: req.body.permissions
|
||||||
|
? JSON.stringify(packRules(backfillPermissionV1SchemaToV2Schema(req.body.permissions, true)))
|
||||||
|
: undefined
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return { role };
|
return { role };
|
||||||
@ -148,7 +142,7 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
role: SanitizedRoleSchema
|
role: SanitizedRoleSchemaV1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -159,7 +153,6 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
projectSlug: req.params.projectSlug,
|
|
||||||
roleId: req.params.roleId
|
roleId: req.params.roleId
|
||||||
});
|
});
|
||||||
return { role };
|
return { role };
|
||||||
@ -184,7 +177,7 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
roles: ProjectRolesSchema.omit({ permissions: true }).array()
|
roles: ProjectRolesSchema.omit({ permissions: true, version: true }).array()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -195,7 +188,10 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
projectSlug: req.params.projectSlug
|
filter: {
|
||||||
|
type: ProjectRoleServiceIdentifierType.SLUG,
|
||||||
|
projectSlug: req.params.projectSlug
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return { roles };
|
return { roles };
|
||||||
}
|
}
|
||||||
@ -214,7 +210,7 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
}),
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
role: SanitizedRoleSchema
|
role: SanitizedRoleSchemaV1.omit({ version: true })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -225,9 +221,13 @@ export const registerProjectRoleRouter = async (server: FastifyZodProvider) => {
|
|||||||
actorId: req.permission.id,
|
actorId: req.permission.id,
|
||||||
actorOrgId: req.permission.orgId,
|
actorOrgId: req.permission.orgId,
|
||||||
actor: req.permission.type,
|
actor: req.permission.type,
|
||||||
projectSlug: req.params.projectSlug,
|
filter: {
|
||||||
|
type: ProjectRoleServiceIdentifierType.SLUG,
|
||||||
|
projectSlug: req.params.projectSlug
|
||||||
|
},
|
||||||
roleSlug: req.params.slug
|
roleSlug: req.params.slug
|
||||||
});
|
});
|
||||||
|
|
||||||
return { role };
|
return { role };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user