diff --git a/backend/package-lock.json b/backend/package-lock.json index 0bc3aadd1..59698d5b3 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -90,6 +90,7 @@ "mysql2": "^3.9.8", "nanoid": "^3.3.8", "nodemailer": "^6.9.9", + "oci-sdk": "^2.108.0", "odbc": "^2.4.9", "openid-client": "^5.6.5", "ora": "^7.0.1", @@ -10656,6 +10657,12 @@ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" }, + "node_modules/@types/isomorphic-fetch": { + "version": "0.0.35", + "resolved": "https://registry.npmjs.org/@types/isomorphic-fetch/-/isomorphic-fetch-0.0.35.tgz", + "integrity": "sha512-DaZNUvLDCAnCTjgwxgiL1eQdxIKEpNLOlTNtAgnZc50bG2copGhRrFN9/PxPBuJe+tZVLCbQ7ls0xveXVRPkvw==", + "license": "MIT" + }, "node_modules/@types/jmespath": { "version": "0.15.2", "resolved": "https://registry.npmjs.org/@types/jmespath/-/jmespath-0.15.2.tgz", @@ -10689,6 +10696,12 @@ "integrity": "sha512-2h3tFvkbHksiNcDiUdcJ08gXWG10fnahp30GJ2Tbt4vd4pfsbfkoKTaTbYykFoppaJ6DL3914nQ3PU1vVIlBRQ==", "dev": true }, + "node_modules/@types/jssha": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/jssha/-/jssha-2.0.0.tgz", + "integrity": "sha512-oBnY3csYnXfqZXDRBJwP1nDDJCW/+VMJ88UHT4DCy0deSXpJIQvMCwYlnmdW4M+u7PiSfQc44LmiFcUbJ8hLEw==", + "license": "MIT" + }, "node_modules/@types/ldapjs": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/@types/ldapjs/-/ldapjs-2.2.5.tgz", @@ -10780,6 +10793,15 @@ "@types/node": "*" } }, + "node_modules/@types/opossum": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@types/opossum/-/opossum-4.1.1.tgz", + "integrity": "sha512-9TMnd8AWRVtnZMqBbbzceQoJdafErgUViogFaQ3eetsbeLtiFFZ695mepNaLtlfJi4uRP3GmHfe3CJ2DZKaxYA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/passport": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.16.tgz", @@ -11027,6 +11049,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/sshpk": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/@types/sshpk/-/sshpk-1.10.3.tgz", + "integrity": "sha512-cru1waDhHZnZuB18E6Dgf2UXf8U93mdOEDcKYe5jTri+fpucidSs7DLmGICpLxN+95aYkwtgeyny9fBFzQVdmA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/tough-cookie": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", @@ -12359,6 +12390,12 @@ "fastq": "^1.17.1" } }, + "node_modules/await-semaphore": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/await-semaphore/-/await-semaphore-0.1.3.tgz", + "integrity": "sha512-d1W2aNSYcz/sxYO4pMGX9vq65qOTu0P800epMud+6cYYX0QcT7zyqcxec3VWzpgvdXo57UWmVbZpLMjX2m1I7Q==", + "license": "MIT" + }, "node_modules/aws-sdk": { "version": "2.1553.0", "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1553.0.tgz", @@ -12589,6 +12626,21 @@ "node": ">= 10.0.0" } }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "license": "Unlicense" + }, "node_modules/bcryptjs": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", @@ -13833,6 +13885,18 @@ "dev": true, "license": "MIT" }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/data-urls": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", @@ -14369,6 +14433,22 @@ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "license": "MIT", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ecc-jsbn/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "license": "MIT" + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -14666,6 +14746,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es6-promise": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.6.tgz", + "integrity": "sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==", + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", @@ -16407,6 +16493,15 @@ "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", "integrity": "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==" }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, "node_modules/github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", @@ -17036,6 +17131,20 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/http-signature": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.1.tgz", + "integrity": "sha512-Y29YKEc8MQsjch/VzkUVJ+2MXd9WcR42fK5u36CZf4G8bXw2DXMTWuESiB0R6m59JAWxlPPw5/Fri/t/AyyueA==", + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.14.1" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -17741,6 +17850,16 @@ "node": ">=18" } }, + "node_modules/isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", @@ -17967,6 +18086,12 @@ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, "node_modules/json-schema-ref-resolver": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-1.0.1.tgz", @@ -18073,6 +18198,44 @@ "npm": ">=6" } }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "license": "MIT", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jsprim/node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, + "node_modules/jsprim/node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "node_modules/jsrp": { "version": "0.2.4", "resolved": "https://registry.npmjs.org/jsrp/-/jsrp-0.2.4.tgz", @@ -18083,6 +18246,16 @@ "randombytes": "^2.0.0" } }, + "node_modules/jssha": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/jssha/-/jssha-2.4.1.tgz", + "integrity": "sha512-77DN1YurYgh+7FPCTJ2CQ6hVDHgIWiHxm4Y5/mAdnpETKYagX22pVWMz4xfKF5fcpNfMaztgVj+/B1bt2k23Eg==", + "deprecated": "jsSHA versions < 3.0.0 will no longer receive feature updates", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, "node_modules/jwa": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", @@ -19955,6 +20128,1722 @@ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true }, + "node_modules/oci-accessgovernancecp": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-accessgovernancecp/-/oci-accessgovernancecp-2.108.0.tgz", + "integrity": "sha512-lohjenh/9XOWSt34clBbCMIa460TC1Lxrj+myry0JrFR8P5zzehqjmLDEUpDjpXx0oACP5t+3bhwuDn/GDzj7w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-adm": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-adm/-/oci-adm-2.108.0.tgz", + "integrity": "sha512-V8faYUwFeQFYFcl6bqnxlF9CzILH6VAb/kzXH9sHX8R2OYF8vXW7rTH72VlW5vxqEDzX0zYhHu46sJo/C5vkBw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-aianomalydetection": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-aianomalydetection/-/oci-aianomalydetection-2.108.0.tgz", + "integrity": "sha512-tJvJ/Mh0owQAIKVsTZyiPXymmUKP1b99yZDYg4rWy3mojrUZ6wHAT5OGgMOa9cSdfTvlkTnyZ194yt54ymG38g==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-aidocument": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-aidocument/-/oci-aidocument-2.108.0.tgz", + "integrity": "sha512-fLGR1rnbhPOgKZ2NReWiYR83XyNY3wW5jV91Q0twSnFuFbkWGE0b/P/89ire06DMkRvkb/nESuYActhDUFhcGg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-ailanguage": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-ailanguage/-/oci-ailanguage-2.108.0.tgz", + "integrity": "sha512-DhwnTXbSs3Z43B4+sK3l7NU+hbOcfk/ZBWfcy32jOA0DsOaH2WUiaUss801IvoE8iaWuAFbNX1odpphgFFHfwg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-aispeech": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-aispeech/-/oci-aispeech-2.108.0.tgz", + "integrity": "sha512-WZUUugibvl5qaX8IgiUj/1hIC3PAZIm9uPQnLMGXeFYmO/Zu5YunVJ85T/qTI3U7UY8O3kdGiXsUKFKCTnZc1A==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-aivision": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-aivision/-/oci-aivision-2.108.0.tgz", + "integrity": "sha512-cgoQ73OfY2+6AELGzXqv4nf9EIUXFx8ENYgRgg6P4DnyFY04NgeUufiZGM2nB4XByxJ862DzBw2YydKlTXPi7A==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-analytics": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-analytics/-/oci-analytics-2.108.0.tgz", + "integrity": "sha512-p09Hk1fFz85nhvkWaFDEEUNwUJFBQFXQpj4OZzGA8orERJhi1dzd6X1Px1dCHpXTaPG8S8NWk2tRV/uloVd7AQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-announcementsservice": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-announcementsservice/-/oci-announcementsservice-2.108.0.tgz", + "integrity": "sha512-rYBcCHP+jZ4CGkJ0mUd6jdFU149AQjxqagoXH/LMUYvSS3ATUf91LlbiWQW22w5k0Otl5SSdMmEiIV7h7NUYyg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-apigateway": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-apigateway/-/oci-apigateway-2.108.0.tgz", + "integrity": "sha512-h6fIWU0kDPTxeqOsNJL35nPrDL8yr4YEKyuhJ4SQsA3wY2BqGs//eX+we4tTXHkEFBtbVJdRWYrt7BU8adsG9w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-apmconfig": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-apmconfig/-/oci-apmconfig-2.108.0.tgz", + "integrity": "sha512-a7YYSKFjdrH9nrngT1OwQ/40yTnPo1SzVas9ImeFLkUFm/5lC/D8t6Rmv7dlR/WO7U5o7e5dN5zLEDVf9LZqBg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-apmcontrolplane": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-apmcontrolplane/-/oci-apmcontrolplane-2.108.0.tgz", + "integrity": "sha512-jIeCJVr+Ci+3Ogifcwe5OYyeQg6otmoT+UiGoMHcUn+gNTgPcG5tSsqQ7C/2KL/qg1P+XEBoDtMen5wBXionPg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-apmsynthetics": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-apmsynthetics/-/oci-apmsynthetics-2.108.0.tgz", + "integrity": "sha512-h13UuPx0UUHV+IyoJtsov4KvNwB0l4QJABW8K49xsOkllUd4IO4VomJw1yhrau9OVXe8QE0P2GyCAHdH1rJPfw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-apmtraces": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-apmtraces/-/oci-apmtraces-2.108.0.tgz", + "integrity": "sha512-ufH4/WYXd2N6AveLCKDynaCx/T9UgzQ/LOatIbtZ1Q86ywd5aS4vdnzKxWUMdDNI//10z92nWeCZCqGov0HgkA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-appmgmtcontrol": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-appmgmtcontrol/-/oci-appmgmtcontrol-2.108.0.tgz", + "integrity": "sha512-JgFGFoJZW0gTtc010K19uIXGOevqpOT575ndRGxpQO04U+41GRDb+IOUe2NYe4ehw1rfYRA4/uUM0xdcbzPPRg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-artifacts": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-artifacts/-/oci-artifacts-2.108.0.tgz", + "integrity": "sha512-ZljcFpyjVuQZiu4V/gKTEjxu1pMiQVH9o5k+Ys++cMtQWBvGyMlnxrDwpFRi16vHoXuPxKw2ygvjqM2wNN8M/g==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-audit": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-audit/-/oci-audit-2.108.0.tgz", + "integrity": "sha512-i7iH6sMzqGi0zl3SwNatnnzqb5CkKXr1sIW8uiamBghhyjIE8sehrW/eQl+hrzKNk/piSvi/5f5ftZ0MIQjxww==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-autoscaling": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-autoscaling/-/oci-autoscaling-2.108.0.tgz", + "integrity": "sha512-HCIU06FXuDa3suv/t0q+dchZAPFr6tRswccRIytvVm4eBJHiB6vblEqrJ6jgPzBd6F+y+hPZ4ZlJ1L2MLE6WYA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-bastion": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-bastion/-/oci-bastion-2.108.0.tgz", + "integrity": "sha512-6Ys6CAO6K+ylKkjQcyBr7oglRQZWd4RZPJdhFqybIQmeysKzzaY44zoWMah7tcYryu3sKaypsmrypIOTXHIwdA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-bds": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-bds/-/oci-bds-2.108.0.tgz", + "integrity": "sha512-eaWmH312PSJd1WiS6eV9KoKUGDzq94UwlaaqslS6Yo8cOLBWhNhrd4yoIcL/rGWpURLAuNfFkqqaIPEUWSzw1A==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-blockchain": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-blockchain/-/oci-blockchain-2.108.0.tgz", + "integrity": "sha512-KTVP/Nlki8Z5ZekU39N/IMEr7LhXbRtz+8u7e8VnGmiHbrJGEA377KQv0cUDczQ8vyC+7IbWLIGvXUgXYVd93A==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-budget": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-budget/-/oci-budget-2.108.0.tgz", + "integrity": "sha512-fy6DKzWD+HgDXjx0HzjgKz5nIRrDeZhn8EIiAMaCqUsPFA982iNw8BRwgw5k0tU6BZf/kwDeLUDc3O1NvlhUDQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-capacitymanagement": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-capacitymanagement/-/oci-capacitymanagement-2.108.0.tgz", + "integrity": "sha512-CEIoKbD49h7naGRFgyqfDnyEtQZfAl4b9IJsx+jJXvJ2sTmhYJagbWoBA/MkoHoYvRfUE3o2VVM1SkBMKLjE/Q==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-certificates": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-certificates/-/oci-certificates-2.108.0.tgz", + "integrity": "sha512-OmeY3hj3VX5r0IkyZg/IMv14CmVnhIUA04aAhtA9F94TlxGKgg6muQ5OppPhnmKrrvuBZhV+8w/3p0BUB0gt1g==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-certificatesmanagement": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-certificatesmanagement/-/oci-certificatesmanagement-2.108.0.tgz", + "integrity": "sha512-yDkpv49vDkGun6Byju19Uxm5+aR38zA1vEexW33hDWyOghLvZP1Jasu41G6xljytoIIy24wykBTZ3IAnB6I00g==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-cims": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-cims/-/oci-cims-2.108.0.tgz", + "integrity": "sha512-3lny4DzRAwtBGGs35K7LsVf388V3AQAyuiIhWDGBB71HtgBw9VGrL3sBB3jyO5WCjwE/akKEXJLKPvpjBgZBGw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-cloudbridge": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-cloudbridge/-/oci-cloudbridge-2.108.0.tgz", + "integrity": "sha512-R6diQhWNusQ7jJU/z45IyrquJz5iZd1NHovNP9TwtkQw2yPrdIbMjLZYhoWSsVDNOnffn1q1VreYNYkid/4qoA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-cloudguard": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-cloudguard/-/oci-cloudguard-2.108.0.tgz", + "integrity": "sha512-0qrH8OM1f1pIHc8tqOpeZfh+DRPlP88FikVf8woCeM8ekD4ysV04+zATAf+w8VVeASkHbYQnrTQB+UgtXMOB7A==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-cloudmigrations": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-cloudmigrations/-/oci-cloudmigrations-2.108.0.tgz", + "integrity": "sha512-ZITVnShAItKIoB2ONp4+XONUVUjKyh5dMg0Mh2Ik1OL2JpKr6tu5KWWUie15azaDj4TqQ022mSbHfdsV51DEIw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-clusterplacementgroups": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-clusterplacementgroups/-/oci-clusterplacementgroups-2.108.0.tgz", + "integrity": "sha512-3TpH2710n4yJFI/oeMyEND719KbgiuP/OD9jjZMiGIDDi9XjGwZnsKNYP6K0kgRriwEDtUNZdFBDtJa69XyB7Q==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-common": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-common/-/oci-common-2.108.0.tgz", + "integrity": "sha512-H7kaU/A57ksvmXlLLFnTo91CeG6m3M5nbqYbWgniHl84vEmaM0vHhe5C9jQOpPUuhMdRRB2GareJYBjP79cqBg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "@types/isomorphic-fetch": "0.0.35", + "@types/jsonwebtoken": "9.0.0", + "@types/jssha": "2.0.0", + "@types/opossum": "4.1.1", + "@types/sshpk": "1.10.3", + "es6-promise": "4.2.6", + "http-signature": "1.3.1", + "isomorphic-fetch": "3.0.0", + "jsonwebtoken": "9.0.0", + "jssha": "2.4.1", + "opossum": "5.0.1", + "sshpk": "1.16.1", + "uuid": "3.3.3" + } + }, + "node_modules/oci-common/node_modules/@types/jsonwebtoken": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", + "integrity": "sha512-mM4TkDpA9oixqg1Fv2vVpOFyIVLJjm5x4k0V+K/rEsizfjD7Tk7LKk3GTtbB7KCfP0FEHQtsZqFxYA0+sijNVg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/oci-common/node_modules/jsonwebtoken": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", + "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/oci-common/node_modules/uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/oci-computecloudatcustomer": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-computecloudatcustomer/-/oci-computecloudatcustomer-2.108.0.tgz", + "integrity": "sha512-UU7GHrvMm6cJ1LeRbJfazq0/FrKEphePulLhvGn3IMiDxYRuAfON8RNydaJGZ+Q8s1Qv4BdID0//zPO7QkiD2Q==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-computeinstanceagent": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-computeinstanceagent/-/oci-computeinstanceagent-2.108.0.tgz", + "integrity": "sha512-1vn2zjyyCOOAtTKiyOG9pm9OxD0VPXZH7HPQP3CRcTalahfFY3WTy0Ti51/Ozk0rOLKUBpyJzcfsknaO87p4LQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-containerengine": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-containerengine/-/oci-containerengine-2.108.0.tgz", + "integrity": "sha512-OcQUtL/3rthwVx3rOTC1vJDTc6FL/kr0gQpqbjRtU5HBGnZE7Y7+R+CLWi+WejX6qP4IgU+Wv2T2Jig4tROZEQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-containerinstances": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-containerinstances/-/oci-containerinstances-2.108.0.tgz", + "integrity": "sha512-0JFULah06CupSJxrHZeOvdSYn6OkYw+/KY3eCb49K6Ht9/dtumHKTLVvGrr/b9JlAtl8ZPdFOd8hNb9WA/dAGQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-core": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-core/-/oci-core-2.108.0.tgz", + "integrity": "sha512-Nuowt0mFE+f1LDT+VFwQt9JRNzTsHkdRd8CPMBgS+czyyI89UsIkAYj9eVzgbyV98Btzv8aX/BF7EGh1BhYJKQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-dashboardservice": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-dashboardservice/-/oci-dashboardservice-2.108.0.tgz", + "integrity": "sha512-zmg7hgVjqXJ0zgf/53bxBnpiZ2nbb8InccjElbiApvUhICMw65BsDCh0JDxyZUbfFBORZSVJcWbr3J5PzudE1w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-database": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-database/-/oci-database-2.108.0.tgz", + "integrity": "sha512-q4Jb9ZosdVbCFtqqDBy1RY0zqk4hSljtvGu+z5A3DyZ6DfL7ALUah8GweZeVWsX6vvfwrc7H1ca15ksxGwl9Lw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-databasemanagement": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-databasemanagement/-/oci-databasemanagement-2.108.0.tgz", + "integrity": "sha512-JQ0ysKWcG21jDGSCiOw1T/uqY+ChGG1SOKa/kMa4stLON86t/DAcjPE343uUtld4fts6GMBDXkGnx8hWW9BaQg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-databasemigration": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-databasemigration/-/oci-databasemigration-2.108.0.tgz", + "integrity": "sha512-OIEx0CNTi9m+ydeFCKCOslcWOWoX+xJkWMbiGGESQdjmSSczkMXoAK4Kn+XmUcRxap2DczBCICS+8dafl7Z76w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-databasetools": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-databasetools/-/oci-databasetools-2.108.0.tgz", + "integrity": "sha512-CYTfqYOdL/INiTTAfRB+DJS06PUclNL6q1AWMYFgDi++R4jcIueyJDXqqnSzwkt/iBzA8IW72er5N8pvVxgYRw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-datacatalog": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-datacatalog/-/oci-datacatalog-2.108.0.tgz", + "integrity": "sha512-T4J175I1229EUpc68HaRMlIhIpQgRf2ajCCNriniwaaz7EWtej4LKRvzaw/eWe3DwHFI4kEb+9WXlpzHj0C7Hw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-dataflow": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-dataflow/-/oci-dataflow-2.108.0.tgz", + "integrity": "sha512-GHPiHHdEC0onqBA4GCHFQ8RdijYmro3hLYXztgrI+uMoIEb/ms9ayBptKliEHwlHmEF85or7/sn5JB2xqXGxPQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-dataintegration": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-dataintegration/-/oci-dataintegration-2.108.0.tgz", + "integrity": "sha512-/BoQhwoBsrK2wGaO9uV6idnIooPb9GTOuE30p+c02Bm7yuFmXTGgA/mQxIEk6TcBvcJGss+3pWiyDrq03gEyqw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-datalabelingservice": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-datalabelingservice/-/oci-datalabelingservice-2.108.0.tgz", + "integrity": "sha512-JE43+obBvanuiJepAGtCrz80giIMB2o8v5sP1Qe0xs7zuB1HtZ1k+tRuof2ipznbnLScCyUZGdROMReE5IiEmQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-datalabelingservicedataplane": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-datalabelingservicedataplane/-/oci-datalabelingservicedataplane-2.108.0.tgz", + "integrity": "sha512-m22njdO3pogqpbeOgJM+ArCwJJvWhHB2Nz13/Kj6YXPuQqFv0TUzGHEL2LuhqpNFdM4CvF5Dtb472q4Kav5+/A==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-datasafe": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-datasafe/-/oci-datasafe-2.108.0.tgz", + "integrity": "sha512-uZ18rhS9FmP//IrRunBQvdwbjdqQiLyKlIdaL0M8BiI+MDrE3ZXL5veZUS8GmD+xeBZyCHV8cqJAvQfcgsi2oA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-datascience": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-datascience/-/oci-datascience-2.108.0.tgz", + "integrity": "sha512-nh/LpXBVYvBrS3Rp8K7J/l8JurDm1geFEgu9oNXxJ+fheofpAZ6HHXeRIVadXHARXbgLuu7ta+pmB1IBft6OEg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-dblm": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-dblm/-/oci-dblm-2.108.0.tgz", + "integrity": "sha512-RJGrKUtzhWeXono6lUvNrRD/xrR4jVrmVNEgpSFTIkDM0rRlKP2lSqWdfZdB+qTt3QaNjKsRWm9TRxYyrroW+w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-delegateaccesscontrol": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-delegateaccesscontrol/-/oci-delegateaccesscontrol-2.108.0.tgz", + "integrity": "sha512-Imri3k0tESbq4xNxlHwqfcRZgvVPxx2Lt29TMuC34mrj2zhNlcKIsg0xgvpmfB3NrEjKz9M/X4MSpIfjzVUJ+w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-demandsignal": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-demandsignal/-/oci-demandsignal-2.108.0.tgz", + "integrity": "sha512-ZvpAJf5QnpeQ5rkMGuQIa04Dv0Q4gS+nmyWLXyIipMV5mrbkyWAdWo4crauZxiwBt6yyJe5r3zBkrNTtXWQubg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-desktops": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-desktops/-/oci-desktops-2.108.0.tgz", + "integrity": "sha512-sEBs1QzvOj1z6NQjZHln65bXyIqOla34lJLsN260GL2AjcV5V/j/8668FP7InxfRFvrb+2+jcefeI54tZbx+NQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-devops": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-devops/-/oci-devops-2.108.0.tgz", + "integrity": "sha512-HgLwTv4+TA/sXIRPGFflyiHQWL9OjQXvej2V+nwiujeiMYsJ66bvTTE3FIm3ku+6apHlD6zQQ8s8VBAJ/IR/bA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-disasterrecovery": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-disasterrecovery/-/oci-disasterrecovery-2.108.0.tgz", + "integrity": "sha512-GULI5fQg+8qWzw9Nk2U4p+COOiXBq5+6+XHRjfriEg1EkIwF+TUt71cwyOUaE+jKZQdI/gHz1ViQdy972S318w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-dns": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-dns/-/oci-dns-2.108.0.tgz", + "integrity": "sha512-93hiGQU6tNwL++Qq6MNbw9RD6CFLl+6pUPaybnosR+/sjYnh0IinwFSaLChizzevSCWWILTr2h/BETafnDXXXA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-dts": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-dts/-/oci-dts-2.108.0.tgz", + "integrity": "sha512-62/xBcPGA6IlAgez0Vrakz7OLav4DTA8SEGpUJPDWdMAAMoJFeSSCVpPh/tVRY3jzjM+3rTTQzmXiI9yix0EaQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-email": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-email/-/oci-email-2.108.0.tgz", + "integrity": "sha512-xIZDTjxuOuK3gcMYUPXUf39NOVQB8frrSJvGTa8Lp4aQNDGgkbwpONCbmyJj7pb0tvOag1likbRuQi9M8Cmjwg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-emaildataplane": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-emaildataplane/-/oci-emaildataplane-2.108.0.tgz", + "integrity": "sha512-eSKh1yTNTwEF/YfuR2AaTmhyipG3jOBPA7kICx0Syrba4pPqvkNqgJBq1pQcJHH0wBxTZZTag7MlMPs4ibIz5g==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-emwarehouse": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-emwarehouse/-/oci-emwarehouse-2.108.0.tgz", + "integrity": "sha512-3vqgsNxz5jTXrrlZQT4Vl9zgGMABqD/OViv4oI/8zNS6eHC5zuUDVbGqe9sZNHlO1VtNOzDlRxbJHCzxj1mnwQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-events": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-events/-/oci-events-2.108.0.tgz", + "integrity": "sha512-4JoHrafbesO+cIXH9BADXZrZM2gCeUeNMTwZc38FP6rhOTK45CrYYP8Izbe+hzoKXCDsbp4rvLsxOdu9gJg1jQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-filestorage": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-filestorage/-/oci-filestorage-2.108.0.tgz", + "integrity": "sha512-XOce/0fDnnsgyRG3vKuHNXpbxAmQ/Erd2KwX9GGPlf6ig4uQHO4X6i2ylVD90OfaPxYbzwdV96j7cTwwlVHfXw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-fleetappsmanagement": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-fleetappsmanagement/-/oci-fleetappsmanagement-2.108.0.tgz", + "integrity": "sha512-OHq1Ctm3EJM6jasYvtHO5HaypR14tw8F6BJPOemCd3sRzoUiqIiZ1qxi1USYq5Salpng+FfvL18Qt4XEZhW+9Q==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-fleetsoftwareupdate": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-fleetsoftwareupdate/-/oci-fleetsoftwareupdate-2.108.0.tgz", + "integrity": "sha512-M5UEi4Kl1vNGUtnf4eoc74nFzZ8k0engo5L8ufJ/lszPtcMJ0pTMFuHB6A9lOSgaXnaIXRIOEj7aW4Wo9lj+6w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-functions": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-functions/-/oci-functions-2.108.0.tgz", + "integrity": "sha512-nD5rVZ3Pve7oTq+Dvpj1uPymRArq45U8Lm7J/EZCwwI9sFTu5ZQyL0nbXNHJRda24W+QdnWeHGQSIB4hcA806A==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-fusionapps": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-fusionapps/-/oci-fusionapps-2.108.0.tgz", + "integrity": "sha512-B8sNAB6er9LBd0C/l3qYRPLqGzf0s0lgyYWDEZsPT5q+1wS9fSmBAvyAfU9bUrL8GgsCaNC4W96ROfEjQ/ZKwA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-generativeai": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-generativeai/-/oci-generativeai-2.108.0.tgz", + "integrity": "sha512-g2EGfBMDzVvo44IEPqLBBHf3pei0DvIOQUT23BgYO08nwfsNmHacuEx8yl6jZvb00/58qN+LjKBQ0807eoHGow==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-generativeaiagent": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-generativeaiagent/-/oci-generativeaiagent-2.108.0.tgz", + "integrity": "sha512-LbzrMlJsORYF67rcJl4gMmNXzzKk09HbnyoqxRT96tHYbSC72w7xMCMnc9xN2746K52mxT4ZsyOI+kPcD/XTww==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-generativeaiagentruntime": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-generativeaiagentruntime/-/oci-generativeaiagentruntime-2.108.0.tgz", + "integrity": "sha512-+TvJklyLWOlq70arKPnkfiCx8WTEDvb2sZgZiq7arxBJYUL3burg/bLO3Di+XlGaHMyoaBbKLW5tJM77rdFNKg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-generativeaiinference": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-generativeaiinference/-/oci-generativeaiinference-2.108.0.tgz", + "integrity": "sha512-OBKKowDh7duUiMRS2LWmLWDGpDz6th7Ef0NznAYGniXAzxf3x1VcGkGYHi/8NEB5GvTzCxbPXYBunA/C0oUL8w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-genericartifactscontent": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-genericartifactscontent/-/oci-genericartifactscontent-2.108.0.tgz", + "integrity": "sha512-6hpnmK4TQG5rUtlib89BQjMte4ho6xhkCH+nyWqbUwUTDMn3L5/On8Nk/O3Rchm6/lgObHZ4v+1LNt1vxE96JQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-globallydistributeddatabase": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-globallydistributeddatabase/-/oci-globallydistributeddatabase-2.108.0.tgz", + "integrity": "sha512-db79VO9Z/dCyhVCIcvg5suqFoUwo7UhH9zT14T8rPTvSuLm3ISZsEYU6XEshXefsIIV5huzElus/SvCEI/JC8g==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-goldengate": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-goldengate/-/oci-goldengate-2.108.0.tgz", + "integrity": "sha512-6pn1HAIXsvfcFaiSdXQtTViRXqQtubyktQyY4hXQ0HyDU+Iv9ZaIXrJ8Z/aAWSRVvH3Rw0W7L5Le4Q1ar+FJ9g==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-governancerulescontrolplane": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-governancerulescontrolplane/-/oci-governancerulescontrolplane-2.108.0.tgz", + "integrity": "sha512-EdtoyGwHAoug/1hHkx3fa/7cOQ55TzAC9lvHJg23uUgM4zHbEjvRuMJjEoyMo6NBWoLk5jM67ESAeczkOCsGaQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-healthchecks": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-healthchecks/-/oci-healthchecks-2.108.0.tgz", + "integrity": "sha512-/98NvgW1uKMxyC+6pvLGaVapMkxsh1qhKjBTXJShIkmGKUycXIksCkknMRCeik98FWmvoSWfu9I0dnTewjTq/w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-identity": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-identity/-/oci-identity-2.108.0.tgz", + "integrity": "sha512-yetR36jJYFEIthzBe7qBSiZQczKIcYT6SQAejxlAXTwAW5uSsRaR6tmv1H24hB/csjVfhZeHFjeDYP99oxsonQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-identitydataplane": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-identitydataplane/-/oci-identitydataplane-2.108.0.tgz", + "integrity": "sha512-WZdy59Lwy85swqYJb6U3pUBUfDNPVPn4mUd/LseezvoDTHwiNTw66DtEQK87XBNMa8O57t4GMdtRV798WqM1fg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-identitydomains": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-identitydomains/-/oci-identitydomains-2.108.0.tgz", + "integrity": "sha512-XQtHk2IA51gKvFAkXcKh/w7NhpoAUXMgy7/4ni8OKhR3Ru7bpGI0cea87iV/eNo0n/p3PxtAqy6AQF+/5VHdyA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-integration": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-integration/-/oci-integration-2.108.0.tgz", + "integrity": "sha512-wmNN4T536iyf5UJaibyHpaGPrA5jNG0r7CwdN0cxQXOw1BhWV8vLXQfEaE/TRDJEmFahbOvdHdEIBH+IExKMrA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-jms": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-jms/-/oci-jms-2.108.0.tgz", + "integrity": "sha512-R7NCobTxuMx8NWx6Vbov5cjBpLct9EW7cFmqurKTWdlWOC98spIujtMOkHnIcB4G5a6PaOWgViXhrjsVSarJaw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-jmsjavadownloads": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-jmsjavadownloads/-/oci-jmsjavadownloads-2.108.0.tgz", + "integrity": "sha512-JeVPC3nvB6MxvL9P3fYm8MkCKSWJDWUrn0i6S0iEAVMJwjfoXkamt1UL1P2r9jCxnkJK9nxJh0YnUUXsSUWrYw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-keymanagement": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-keymanagement/-/oci-keymanagement-2.108.0.tgz", + "integrity": "sha512-4hbzgIZI6C5TpUhPzt2jJASfke342aoOqH0oYKN1kb2cK+3BfyNFqh0loDgUtWkoKlk94joPAbHaf4ebmYmeHw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-licensemanager": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-licensemanager/-/oci-licensemanager-2.108.0.tgz", + "integrity": "sha512-OKjENCbpN6LOHSJLEbomhh9+cMxOMRmkKaJultzGvyMJ0GnULgFC5+6n/de+2/+rchQyai62JhZlU7fiXAUcFw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-limits": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-limits/-/oci-limits-2.108.0.tgz", + "integrity": "sha512-q8r56EfgjmFmUP6Jj7Bl668Jv3M+4AQM2kwWDMCWWJVIiyWLEmHURmiLkstnxlT9qfrjsHpyOp6Uy8fdm/idVg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-loadbalancer": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-loadbalancer/-/oci-loadbalancer-2.108.0.tgz", + "integrity": "sha512-N+PyjBLP2ng2HFNlL+iuSHvJHGJQmHYIYW8wuZ4sYvA9rz4um/PQMPD6OgRz+kO3dsxF/8dPkwnQ33RwHwxMfQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-lockbox": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-lockbox/-/oci-lockbox-2.108.0.tgz", + "integrity": "sha512-CrVmzyvjBpy7yVfOso2x0M16h+p0zNzn75/7QVx9ifwFxBhSJpiztjH0YTADHd1l0KMNXa1ZDsxKq0mOQlYp0Q==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-loganalytics": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-loganalytics/-/oci-loganalytics-2.108.0.tgz", + "integrity": "sha512-5uFYU/1uHJYg8evPECvXC6oTZhYwXUk3CKkEcklXQAHptDEMYzVu24S/nBkqgdjHAXWtIHElh8V0lrgboseodA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-logging": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-logging/-/oci-logging-2.108.0.tgz", + "integrity": "sha512-A7Gu+hoJGOI2tBrCkLdMHEabQmmUEAPZEUVEq9MrAsTqJYjZi89V7KNiaLx15ARCUaj9ivUYN9eamLfPSQQaJw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-loggingingestion": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-loggingingestion/-/oci-loggingingestion-2.108.0.tgz", + "integrity": "sha512-otlfcKBUpAvg81fbyIHMUMNuTuErmrNq/yK2SynwqJUTcZ9EjbaysqCwed67tRDyETqru1/qX2tmI2XCQkATCQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-loggingsearch": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-loggingsearch/-/oci-loggingsearch-2.108.0.tgz", + "integrity": "sha512-Pj629/S9LYPH+wkDdi1gazYzv8V7PvvW6OgKsg5zH6XKBhZrD4k3yHmW1nNoEVmR3JHFui4DcK8YBj3Jv2oLCA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-lustrefilestorage": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-lustrefilestorage/-/oci-lustrefilestorage-2.108.0.tgz", + "integrity": "sha512-WtQxJp2gQP/K411FHlh2bg8UW8Wx76b+ZA1ApySQR7IiXicDs0kSsfNluKat5DytFnAMt97Qh5pq2KnjwKg88w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-managementagent": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-managementagent/-/oci-managementagent-2.108.0.tgz", + "integrity": "sha512-VCmMUoet6AsZXmKneykIxddRr6Wo01Aj1ByCnlg9PaqmWbNNv5PkmdzCDrpV8GNhpn2IyfAp61lr/lwI3imD+Q==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-managementdashboard": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-managementdashboard/-/oci-managementdashboard-2.108.0.tgz", + "integrity": "sha512-tVuAB2xRUiSYLjuUBiqtkqvszpmTQrVJLCZB92H+SzaNFeqa2OjoH/qK0jU6LOQuLfMr7SG3atATGYNqFLVMBw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-marketplace": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-marketplace/-/oci-marketplace-2.108.0.tgz", + "integrity": "sha512-zMsftpZM6VThpicbhciK/b1irkrJPbqX45aHvj2iS1q+I7h7dG1WD+LMK/K6oS53idzFclHOvBCN0DMg1OYEjw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-marketplaceprivateoffer": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-marketplaceprivateoffer/-/oci-marketplaceprivateoffer-2.108.0.tgz", + "integrity": "sha512-JMdMPLpRwiARCgjiEVbyVweYZjmIt2KntqG7o6SEDoIoE2j74poqHjP75M4794pNynFHT4AZJzb/Ryv1hwuWhQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-marketplacepublisher": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-marketplacepublisher/-/oci-marketplacepublisher-2.108.0.tgz", + "integrity": "sha512-EjjACVK6JDn3/m1kXadeJa+s7zUsPR9uVq+e6QFwyeB9ro1HnzG+qyYJikoDc/huF3ZYwQFlWcTFR3Q/x4acJg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-mediaservices": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-mediaservices/-/oci-mediaservices-2.108.0.tgz", + "integrity": "sha512-AB1dRo+g12Qq6ep/BrtEHjEG49NpePqgDt6/WZSre1BpEcfyONTCMQDaI7HpeUH2OuEsn/duXLEHVLE1w0zQzg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-mngdmac": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-mngdmac/-/oci-mngdmac-2.108.0.tgz", + "integrity": "sha512-kZg+mDSIeMQqBhQz0JmcSQKKdMizR975xxkLbLdUXdhtAoCcFMagYm4NqsdHGMbchMJ2JfKpB3ylPexoRyY89g==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-monitoring": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-monitoring/-/oci-monitoring-2.108.0.tgz", + "integrity": "sha512-nWRALVeyuIzFi7wRSb+hsYl8S7le7jlZKa47eCLlSHziHTJrDUT7PLAeSTdAVkPRzircHAFeD+H1SB8tVsyrzQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-mysql": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-mysql/-/oci-mysql-2.108.0.tgz", + "integrity": "sha512-Zr9B8hgwQy1Z+BTStUdrVnjj+2ZkeR3+NFlhxPGt2LvU+vm92XOUD33h6MbogswpJ/cb7RlazKxKQKJtPHfJPw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-networkfirewall": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-networkfirewall/-/oci-networkfirewall-2.108.0.tgz", + "integrity": "sha512-TvGwagr0Qyt/BFnxyrVmPnsFryRn9snLXwJPwQU2MMcGlnJHUDcsidhKxV/tJzSHYNINmYy9IXOy4D+E8a+wUA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-networkloadbalancer": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-networkloadbalancer/-/oci-networkloadbalancer-2.108.0.tgz", + "integrity": "sha512-XnuIvO4GRyKjRxigAMBl1zjKhxnGMyuo9fkx53nbPaWdmMM0mEbL6csKxTsozQxc29gUtUcZJI/tqvC/yBNQ+g==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-nosql": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-nosql/-/oci-nosql-2.108.0.tgz", + "integrity": "sha512-OJtPwgNmMPslXj/QIaT7NQQxPUrY1zCAPSZdCBfhlQH/D7x62w5A8BVP+HtkTA4LyN/GgGqnk/L01uni7lng8w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-objectstorage": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-objectstorage/-/oci-objectstorage-2.108.0.tgz", + "integrity": "sha512-TjG6tf8RpnCz00loEy8Nhe/FD0P+TOkzyBaVoGODDr6rR1F7PmWL4k3u8rQA7tvTtJsIO//XaSaObcnW7ytM3g==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "await-semaphore": "^0.1.3", + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-oce": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-oce/-/oci-oce-2.108.0.tgz", + "integrity": "sha512-h+WUIkNpLTCjLLPM3xsMwR7r3K+NzId2Sxh4yIHbzOewRJIk1o/qpZzSyMevnUIL86S9IYPkVvjIVJnU2Dueyw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-ocicontrolcenter": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-ocicontrolcenter/-/oci-ocicontrolcenter-2.108.0.tgz", + "integrity": "sha512-I6MfZbsYHkNojoqvzKdkz8vlQu/ZcYm80mZf9XpK9HY00SyY/SfPtwjutyGi46L8dIBVoXHhUNP3hQcVD5T0rQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-ocvp": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-ocvp/-/oci-ocvp-2.108.0.tgz", + "integrity": "sha512-JCriglSsxC1YXfUd/3xVxMojZT+b/+Go3hRIxom4gkOJ3Ceo0x7VXfJKeYGnjqERP5YIA2KWztgHQwAgAG0xFA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-oda": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-oda/-/oci-oda-2.108.0.tgz", + "integrity": "sha512-QNkLczqrgaVVmnyYTRaiEF3cfohzgIYLyKpBT7Bg4Bu2kP0ljAQV0/BxD1XXpkUpC5atK5wjEq5urUWdybKqZg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-onesubscription": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-onesubscription/-/oci-onesubscription-2.108.0.tgz", + "integrity": "sha512-Er6TBhzziC5uHURHLl1AjHjPp2r8wvYH7p59aJ0uyuXucZ0rGVJ9IkmU8T+TNznSx59iEhcmsYvaZyYUPI3RkQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-ons": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-ons/-/oci-ons-2.108.0.tgz", + "integrity": "sha512-C1Z/OBjPFeL3wa1M8AHArCbeNqul3GoO9QbEwZQ5qsNyKlF9Ol06UcdXA9vhSl25q+sH905JetuGaa9knIKA1A==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-opa": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-opa/-/oci-opa-2.108.0.tgz", + "integrity": "sha512-8jB/IqlevkwXlq9DSzTJ+2re+Y6vLCKFyVhQX323Sc/BamrEP2YnCU5HInSy+9GzQWbkBJ872CPvuQxLpUgHCA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-opensearch": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-opensearch/-/oci-opensearch-2.108.0.tgz", + "integrity": "sha512-/Mofttk4YRa+/unJEFwis8gFgjQGCh55My5dzeKASBBlRGuSJTHWwJDBkZAsY/Boizen7nb2nvvgzQpB7Q42Zg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-operatoraccesscontrol": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-operatoraccesscontrol/-/oci-operatoraccesscontrol-2.108.0.tgz", + "integrity": "sha512-Ln9tyjySUvWA7kHx7EQ6z0+wWuHoYQ7e9AvsxIVCuL6WzVy+CEONknNhqXqfMmSQHexgpXPaVJtTd8HRoISGUA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-opsi": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-opsi/-/oci-opsi-2.108.0.tgz", + "integrity": "sha512-AhO4cME5h4dMsZSXlWKU4fAjf+G6KOSDC/q1/MKzsuFOVIw8YaNWEldOai1k+z5VRC1EWmuneFvgnK4EVnaeMA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-optimizer": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-optimizer/-/oci-optimizer-2.108.0.tgz", + "integrity": "sha512-FsmroTYeawQAiEraHHt3EG0WiMwjfjYCpSbhl0Rh4kBMEG27BbW6SBzE4J/Aam2ArJLM8NSdakDwAt3y8oJZdA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-osmanagement": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-osmanagement/-/oci-osmanagement-2.108.0.tgz", + "integrity": "sha512-FJsODD7muZCnpgGAL3t6rBvbg+cJRvcrjtVkPx147tED2wI1Hxrc/bXAhanC375rn4k8vFvrFjNSKCfF1VCG7A==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-osmanagementhub": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-osmanagementhub/-/oci-osmanagementhub-2.108.0.tgz", + "integrity": "sha512-u4yPdLxYGoSGMrI3jE5N0ruhH719Sm/Ga6uhONhufGew3g/fszaTQfjvDML9kSo+BtReiaua6gfAidi24dTfVQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-ospgateway": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-ospgateway/-/oci-ospgateway-2.108.0.tgz", + "integrity": "sha512-2DGQ903/wtQRvNEwScYTpr+pjcVmumAQw+ihWBV3WQ5bFCZNaFEfSyEu7wvFYxRMI4WvfwjivUmVUmSbTIVMzg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-osubbillingschedule": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-osubbillingschedule/-/oci-osubbillingschedule-2.108.0.tgz", + "integrity": "sha512-2iN2hoYUyR9yg/RUR7VnKVmW+N0HHBuO8cVXmgjdoybzS9rDLvAmy/JsoHS0tMt/a4ExAIi9iC228Fwk4x3Sgg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-osuborganizationsubscription": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-osuborganizationsubscription/-/oci-osuborganizationsubscription-2.108.0.tgz", + "integrity": "sha512-58WtIRE8+jK6V1Lzt9cToiv2wr4XIX41P3M6ab/vljusW5bJ+trNRrJXugcq6BE3+s9ysebdVY9mLe3O14qNLQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-osubsubscription": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-osubsubscription/-/oci-osubsubscription-2.108.0.tgz", + "integrity": "sha512-cCSjWrJVsOTkt2IhokdUkrx95VxLh4HuK51EAfo7ITLuOnMkScoDSFgTB48+Ktx3qjEMG9fNrM9lRxtktTpe3A==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-osubusage": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-osubusage/-/oci-osubusage-2.108.0.tgz", + "integrity": "sha512-bICbOu3MbKRnhV8iFLOHVhs31bQlmZS8cO8qWCFQgci7dt401mrxj+MFO0Yzq/Hk5unpbuFonLjlHsiD456ZDg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-psql": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-psql/-/oci-psql-2.108.0.tgz", + "integrity": "sha512-w3ruZcKn++JnnYiPu6gmnSCjD/NQ1SGCJUIGDcc+O2qI01tfVXa3BI/c2AY7Y5Z+DbRD/efO0hSZt/9mtkS5IQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-queue": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-queue/-/oci-queue-2.108.0.tgz", + "integrity": "sha512-G3VUM2a9X1Gu0KnhYsCQlbH/3kHvbMsOH1IbA/XAJPAmpWp4JcXhFzWzW03/aymkoqoA1Vt3p77u9ltmrhgG7g==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-recovery": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-recovery/-/oci-recovery-2.108.0.tgz", + "integrity": "sha512-6OSclD5wagdrJGZtRvJbE1FJq8wl9igGevDMrd1o5rPJoGd/pCmZBn9bvfLPL1Mw9h0YGSAKZhAeMd3pDCNaIQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-redis": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-redis/-/oci-redis-2.108.0.tgz", + "integrity": "sha512-MzCORmjESnRs9BkOc3gnrbNaNOwWgZI+tgK2xTVY65PIy4PyYq5qvwgO3wmnLc4sULI4nIoWpoMSDxYyly7Zgg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-resourcemanager": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-resourcemanager/-/oci-resourcemanager-2.108.0.tgz", + "integrity": "sha512-IBfQL1K7YaDyvO1UUM2277aH7gejRv6bcAD6G2kv7D/0PamavlDf1PJ1oGv8kQrPCjoALiBNNohelTEltywNOA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-resourcescheduler": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-resourcescheduler/-/oci-resourcescheduler-2.108.0.tgz", + "integrity": "sha512-DI2w49VFfzo1y3y4uaqa5sFqqlpZlyQm6qpuhIaCjjDyrvZpbLLAC8Q9dFKq15PpzA7vlKQPPnBFeoW6YAX4pQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-resourcesearch": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-resourcesearch/-/oci-resourcesearch-2.108.0.tgz", + "integrity": "sha512-9HCm5fVmZf9ANW02YL3UYn1xGy5b2WMkABmVjosAs2rsMbRPieoOuu0zKK+d2YG2cXXHc1cGfFALQV9rfRSI2w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-rover": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-rover/-/oci-rover-2.108.0.tgz", + "integrity": "sha512-uy3oNTMQDaLLy7EUoOljcXsnSKshQof9ESajQOKq4+EXNiFQ9fa5PNTTVl6g10+GS5Mak4KVLTIU7UnMYqwX9A==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-sch": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-sch/-/oci-sch-2.108.0.tgz", + "integrity": "sha512-4W+LA2lXN/rKoj8ZRu5HMzFq0De/VLTtUTVY37srgYBs0mp7z+crX4VenA9sIiytYzrY3cijxsDZOe6EBxnMqQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-sdk": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-sdk/-/oci-sdk-2.108.0.tgz", + "integrity": "sha512-wc5FXeAGUxBzTbRohdn7zD9328akY6CZ9qZoMzdXNe7dn65flxn1iO/clsw0zc3StRgy+0NGia1ZvsHIgkWzcg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-accessgovernancecp": "2.108.0", + "oci-adm": "2.108.0", + "oci-aianomalydetection": "2.108.0", + "oci-aidocument": "2.108.0", + "oci-ailanguage": "2.108.0", + "oci-aispeech": "2.108.0", + "oci-aivision": "2.108.0", + "oci-analytics": "2.108.0", + "oci-announcementsservice": "2.108.0", + "oci-apigateway": "2.108.0", + "oci-apmconfig": "2.108.0", + "oci-apmcontrolplane": "2.108.0", + "oci-apmsynthetics": "2.108.0", + "oci-apmtraces": "2.108.0", + "oci-appmgmtcontrol": "2.108.0", + "oci-artifacts": "2.108.0", + "oci-audit": "2.108.0", + "oci-autoscaling": "2.108.0", + "oci-bastion": "2.108.0", + "oci-bds": "2.108.0", + "oci-blockchain": "2.108.0", + "oci-budget": "2.108.0", + "oci-capacitymanagement": "2.108.0", + "oci-certificates": "2.108.0", + "oci-certificatesmanagement": "2.108.0", + "oci-cims": "2.108.0", + "oci-cloudbridge": "2.108.0", + "oci-cloudguard": "2.108.0", + "oci-cloudmigrations": "2.108.0", + "oci-clusterplacementgroups": "2.108.0", + "oci-common": "2.108.0", + "oci-computecloudatcustomer": "2.108.0", + "oci-computeinstanceagent": "2.108.0", + "oci-containerengine": "2.108.0", + "oci-containerinstances": "2.108.0", + "oci-core": "2.108.0", + "oci-dashboardservice": "2.108.0", + "oci-database": "2.108.0", + "oci-databasemanagement": "2.108.0", + "oci-databasemigration": "2.108.0", + "oci-databasetools": "2.108.0", + "oci-datacatalog": "2.108.0", + "oci-dataflow": "2.108.0", + "oci-dataintegration": "2.108.0", + "oci-datalabelingservice": "2.108.0", + "oci-datalabelingservicedataplane": "2.108.0", + "oci-datasafe": "2.108.0", + "oci-datascience": "2.108.0", + "oci-dblm": "2.108.0", + "oci-delegateaccesscontrol": "2.108.0", + "oci-demandsignal": "2.108.0", + "oci-desktops": "2.108.0", + "oci-devops": "2.108.0", + "oci-disasterrecovery": "2.108.0", + "oci-dns": "2.108.0", + "oci-dts": "2.108.0", + "oci-email": "2.108.0", + "oci-emaildataplane": "2.108.0", + "oci-emwarehouse": "2.108.0", + "oci-events": "2.108.0", + "oci-filestorage": "2.108.0", + "oci-fleetappsmanagement": "2.108.0", + "oci-fleetsoftwareupdate": "2.108.0", + "oci-functions": "2.108.0", + "oci-fusionapps": "2.108.0", + "oci-generativeai": "2.108.0", + "oci-generativeaiagent": "2.108.0", + "oci-generativeaiagentruntime": "2.108.0", + "oci-generativeaiinference": "2.108.0", + "oci-genericartifactscontent": "2.108.0", + "oci-globallydistributeddatabase": "2.108.0", + "oci-goldengate": "2.108.0", + "oci-governancerulescontrolplane": "2.108.0", + "oci-healthchecks": "2.108.0", + "oci-identity": "2.108.0", + "oci-identitydataplane": "2.108.0", + "oci-identitydomains": "2.108.0", + "oci-integration": "2.108.0", + "oci-jms": "2.108.0", + "oci-jmsjavadownloads": "2.108.0", + "oci-keymanagement": "2.108.0", + "oci-licensemanager": "2.108.0", + "oci-limits": "2.108.0", + "oci-loadbalancer": "2.108.0", + "oci-lockbox": "2.108.0", + "oci-loganalytics": "2.108.0", + "oci-logging": "2.108.0", + "oci-loggingingestion": "2.108.0", + "oci-loggingsearch": "2.108.0", + "oci-lustrefilestorage": "2.108.0", + "oci-managementagent": "2.108.0", + "oci-managementdashboard": "2.108.0", + "oci-marketplace": "2.108.0", + "oci-marketplaceprivateoffer": "2.108.0", + "oci-marketplacepublisher": "2.108.0", + "oci-mediaservices": "2.108.0", + "oci-mngdmac": "2.108.0", + "oci-monitoring": "2.108.0", + "oci-mysql": "2.108.0", + "oci-networkfirewall": "2.108.0", + "oci-networkloadbalancer": "2.108.0", + "oci-nosql": "2.108.0", + "oci-objectstorage": "2.108.0", + "oci-oce": "2.108.0", + "oci-ocicontrolcenter": "2.108.0", + "oci-ocvp": "2.108.0", + "oci-oda": "2.108.0", + "oci-onesubscription": "2.108.0", + "oci-ons": "2.108.0", + "oci-opa": "2.108.0", + "oci-opensearch": "2.108.0", + "oci-operatoraccesscontrol": "2.108.0", + "oci-opsi": "2.108.0", + "oci-optimizer": "2.108.0", + "oci-osmanagement": "2.108.0", + "oci-osmanagementhub": "2.108.0", + "oci-ospgateway": "2.108.0", + "oci-osubbillingschedule": "2.108.0", + "oci-osuborganizationsubscription": "2.108.0", + "oci-osubsubscription": "2.108.0", + "oci-osubusage": "2.108.0", + "oci-psql": "2.108.0", + "oci-queue": "2.108.0", + "oci-recovery": "2.108.0", + "oci-redis": "2.108.0", + "oci-resourcemanager": "2.108.0", + "oci-resourcescheduler": "2.108.0", + "oci-resourcesearch": "2.108.0", + "oci-rover": "2.108.0", + "oci-sch": "2.108.0", + "oci-secrets": "2.108.0", + "oci-securityattribute": "2.108.0", + "oci-servicecatalog": "2.108.0", + "oci-servicemanagerproxy": "2.108.0", + "oci-servicemesh": "2.108.0", + "oci-stackmonitoring": "2.108.0", + "oci-streaming": "2.108.0", + "oci-tenantmanagercontrolplane": "2.108.0", + "oci-threatintelligence": "2.108.0", + "oci-usage": "2.108.0", + "oci-usageapi": "2.108.0", + "oci-vault": "2.108.0", + "oci-vbsinst": "2.108.0", + "oci-visualbuilder": "2.108.0", + "oci-vnmonitoring": "2.108.0", + "oci-vulnerabilityscanning": "2.108.0", + "oci-waa": "2.108.0", + "oci-waas": "2.108.0", + "oci-waf": "2.108.0", + "oci-workrequests": "2.108.0", + "oci-zpr": "2.108.0" + } + }, + "node_modules/oci-secrets": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-secrets/-/oci-secrets-2.108.0.tgz", + "integrity": "sha512-GFFCuaKnS8pX7mE4mvZn/3m+rlksbheRNBg0e3dADAE9/G8hcRDabfUcp8ee0I2IOGlfmPx1MqqVxGdOB5qePA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-securityattribute": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-securityattribute/-/oci-securityattribute-2.108.0.tgz", + "integrity": "sha512-5q7X2iTIFONcQZLMMyuSPEGwv+/H1zp6+A8pizNEKnt/Ky1Y6J7mVt8rIfjkmW2adjCMbJvjOd/FEx1qpPMSdA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-servicecatalog": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-servicecatalog/-/oci-servicecatalog-2.108.0.tgz", + "integrity": "sha512-wawMy6pyaaLGb//qDSRZY3RDlBAdcgiH5rT8HWIvjpty5/LUfAFEoc6GT+hXESJJnTgKPv3jVRsauKGaYY0ThQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-servicemanagerproxy": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-servicemanagerproxy/-/oci-servicemanagerproxy-2.108.0.tgz", + "integrity": "sha512-ze38V56A7Lj2bmu0zrJJP/p0zJXawdUZO4vzVNKTRCMuCHA/bpNgxhsqrZftrlh/hJHIvzTUorNqKG6db4rvpw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-servicemesh": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-servicemesh/-/oci-servicemesh-2.108.0.tgz", + "integrity": "sha512-PKCePlf3UBtmXXqkCLQb3ckhYcMPwUjigKQHJXLomqRsN/WWS4cjaXFfwPms1LHYiljFaUBBpYPEXXuNBIAxrw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-stackmonitoring": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-stackmonitoring/-/oci-stackmonitoring-2.108.0.tgz", + "integrity": "sha512-MnWwot6txJhUFjmToZLg/MqxOy9oUcuosOv1ndRt1KJzgHlVqNDKhlYSzsY3M1I/luLKl56MmGUXEmPByTVNsA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-streaming": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-streaming/-/oci-streaming-2.108.0.tgz", + "integrity": "sha512-EJflloCRvhKpmbMWLtDKgYQDiinZgIyyAArl0YChUuLXYs7ntXNdK7vkiz/xYtez1j06JSGVDlhoJGnWHnLLOA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-tenantmanagercontrolplane": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-tenantmanagercontrolplane/-/oci-tenantmanagercontrolplane-2.108.0.tgz", + "integrity": "sha512-qOrkZhRI54+dncswCWrzgYNUhC1v/RVrBm/3M34RrZP3XIUYk42FbWEGmAUIf8CsKqAnMihHGZhYmKLF+CnQEQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-threatintelligence": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-threatintelligence/-/oci-threatintelligence-2.108.0.tgz", + "integrity": "sha512-xU9XRZRfTrXN4+UzsPwQbZXmwyU9IY5CpXvsAO/PjdIZJGwl69CGlxSbbLk0ye9qC+0zdADN8fspHp7u++jJ3w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-usage": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-usage/-/oci-usage-2.108.0.tgz", + "integrity": "sha512-qjP75B0BchoIHc2VCQF8Yehx69/2F/M0UT74GcGjiNewkjxlJwiDCegj+IeVHZ91OCmb1Dqva3u2zUfwxbaqIw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-usageapi": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-usageapi/-/oci-usageapi-2.108.0.tgz", + "integrity": "sha512-hKcssMA1aHia+EM1rD+tGt/njsUn3nYmHJKMzywLHKYnmsbtVVVli8bKlELBFkLVjkIyKPY7XJQfCRr5TPQBHw==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-vault": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-vault/-/oci-vault-2.108.0.tgz", + "integrity": "sha512-wDq/hibUkif9rYJOhkY6/D9RXhSCsMuaKQeR0WaO6MdYhe7zbo0uXlADn8nPHWJ257CUBoDcpPMWP+mlWyVq9g==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-vbsinst": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-vbsinst/-/oci-vbsinst-2.108.0.tgz", + "integrity": "sha512-ZH6igsrlPrkC6DS9g6c7F6nSAb6/s7NuT11ENc/i2zG2DtsZBOTkr5l8+/mG5AvzMocKRd7NrcHjR4IMxrnhMQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-visualbuilder": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-visualbuilder/-/oci-visualbuilder-2.108.0.tgz", + "integrity": "sha512-G2oISBuIwvzl6sJV4KwbZX5G5GwkDmKG4JX2jxp/WNTtawsUz/OfpbpPyx+y5raWCUh3Uji5vWMlDVXfhzzzhg==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-vnmonitoring": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-vnmonitoring/-/oci-vnmonitoring-2.108.0.tgz", + "integrity": "sha512-8oVv+nQddteOdUiqDZGxBJgwkib1NUt6WifsaP3Y+GJEzV42vNHxvjpmJbMuR7TTW4cjBV8mQS2TbTQmPhX/JQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-vulnerabilityscanning": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-vulnerabilityscanning/-/oci-vulnerabilityscanning-2.108.0.tgz", + "integrity": "sha512-duvDY4zrDXWdRWWyBGLpQSvfpjYHfNJHyxxMacHu5l0sZM3iKMjx56288PYSTanicknSJ7dKeh/2R5XlOGO35w==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-waa": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-waa/-/oci-waa-2.108.0.tgz", + "integrity": "sha512-k0yhzlWvM6ry7/eScX/nIB98q6s+yuMP/GUagja/U1AbVGUjLHBjbhi8hbjqtpfuRaUN3luxMS8nrs0t6ZQesQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-waas": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-waas/-/oci-waas-2.108.0.tgz", + "integrity": "sha512-KtjN2JZ7tN5rAZr5viJQs24xRGBWrjP7ZmeHPkdGW+96rHqExlDNfJAcyk0hhJNECSu/g400aPlQ9djfELXPMA==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-waf": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-waf/-/oci-waf-2.108.0.tgz", + "integrity": "sha512-delccqk+FkW2l9e0Bf9SzD6VYojctk8mJx6IasxGl/w3Dc3C9HoBi2l4tfz2sBgBExDDWAMwxUa3ygCX2N3r8Q==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-workrequests": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-workrequests/-/oci-workrequests-2.108.0.tgz", + "integrity": "sha512-vwIM+cEDZ2BhKX+bOH2POTMTnfFnfjs0QxprHb1F05wu5/a3ea35oCkcchyqa1uHh75tqnO/dGDlp6st6+IeIQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, + "node_modules/oci-zpr": { + "version": "2.108.0", + "resolved": "https://registry.npmjs.org/oci-zpr/-/oci-zpr-2.108.0.tgz", + "integrity": "sha512-Ktxh08Mozp4LJ5ADuDpfnaMZBSJQ04xSvjCod/kf2G3WTQ7OUctvppY1S7X2kCPnEfNORevkE/LPDDpCnZpGgQ==", + "license": "(UPL-1.0 OR Apache-2.0)", + "dependencies": { + "oci-common": "2.108.0", + "oci-workrequests": "2.108.0" + } + }, "node_modules/octokit-auth-probot": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/octokit-auth-probot/-/octokit-auth-probot-2.0.0.tgz", @@ -20275,6 +22164,15 @@ "node": ">=0.10" } }, + "node_modules/opossum": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/opossum/-/opossum-5.0.1.tgz", + "integrity": "sha512-iUDUQmFl3RanaBVLMDTZ6WtXj/Hk84pwJ5JWoJaQd1lXGifdApHhszI3biZvdBDdpTERCmB6x+7+uNvzhzVZIg==", + "license": "Apache-2.0", + "engines": { + "node": ">= 10" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -24108,6 +26006,43 @@ "node": ">= 0.6" } }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "license": "MIT", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sshpk/node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "license": "MIT" + }, + "node_modules/sshpk/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "license": "Unlicense" + }, "node_modules/ssri": { "version": "10.0.6", "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", @@ -26901,6 +28836,12 @@ "node": ">=18" } }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "license": "MIT" + }, "node_modules/whatwg-mimetype": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", diff --git a/backend/package.json b/backend/package.json index f5747fdda..30aa9f68c 100644 --- a/backend/package.json +++ b/backend/package.json @@ -209,6 +209,7 @@ "mysql2": "^3.9.8", "nanoid": "^3.3.8", "nodemailer": "^6.9.9", + "oci-sdk": "^2.108.0", "odbc": "^2.4.9", "openid-client": "^5.6.5", "ora": "^7.0.1", diff --git a/backend/src/lib/api-docs/constants.ts b/backend/src/lib/api-docs/constants.ts index 34c701507..a4556a75d 100644 --- a/backend/src/lib/api-docs/constants.ts +++ b/backend/src/lib/api-docs/constants.ts @@ -2039,6 +2039,13 @@ export const AppConnections = { AZURE_CLIENT_SECRETS: { code: "The OAuth code to use to connect with Azure Client Secrets.", tenantId: "The Tenant ID to use to connect with Azure Client Secrets." + }, + OCI: { + userOcid: "The OCID (Oracle Cloud Identifier) of the user making the request.", + tenancyOcid: "The OCID (Oracle Cloud Identifier) of the tenancy in Oracle Cloud Infrastructure.", + region: "The region identifier in Oracle Cloud Infrastructure where the vault is located.", + fingerprint: "The fingerprint of the public key uploaded to the user's API keys.", + privateKey: "The private key content in PEM format used to sign API requests." } } }; @@ -2186,6 +2193,11 @@ export const SecretSyncs = { TEAMCITY: { project: "The TeamCity project to sync secrets to.", buildConfig: "The TeamCity build configuration to sync secrets to." + }, + OCI_VAULT: { + compartmentOcid: "The OCID (Oracle Cloud Identifier) of the compartment where the vault is located.", + vaultOcid: "The OCID (Oracle Cloud Identifier) of the vault to sync secrets to.", + keyOcid: "The OCID (Oracle Cloud Identifier) of the encryption key to use when creating secrets in the vault." } } }; diff --git a/backend/src/server/routes/v1/app-connection-routers/app-connection-router.ts b/backend/src/server/routes/v1/app-connection-routers/app-connection-router.ts index f6c260ea5..b9ce3deb8 100644 --- a/backend/src/server/routes/v1/app-connection-routers/app-connection-router.ts +++ b/backend/src/server/routes/v1/app-connection-routers/app-connection-router.ts @@ -38,6 +38,7 @@ import { } from "@app/services/app-connection/humanitec"; import { LdapConnectionListItemSchema, SanitizedLdapConnectionSchema } from "@app/services/app-connection/ldap"; import { MsSqlConnectionListItemSchema, SanitizedMsSqlConnectionSchema } from "@app/services/app-connection/mssql"; +import { OCIConnectionListItemSchema, SanitizedOCIConnectionSchema } from "@app/services/app-connection/oci"; import { PostgresConnectionListItemSchema, SanitizedPostgresConnectionSchema @@ -76,7 +77,8 @@ const SanitizedAppConnectionSchema = z.union([ ...SanitizedAzureClientSecretsConnectionSchema.options, ...SanitizedWindmillConnectionSchema.options, ...SanitizedLdapConnectionSchema.options, - ...SanitizedTeamCityConnectionSchema.options + ...SanitizedTeamCityConnectionSchema.options, + ...SanitizedOCIConnectionSchema.options ]); const AppConnectionOptionsSchema = z.discriminatedUnion("app", [ @@ -97,7 +99,8 @@ const AppConnectionOptionsSchema = z.discriminatedUnion("app", [ AzureClientSecretsConnectionListItemSchema, WindmillConnectionListItemSchema, LdapConnectionListItemSchema, - TeamCityConnectionListItemSchema + TeamCityConnectionListItemSchema, + OCIConnectionListItemSchema ]); export const registerAppConnectionRouter = async (server: FastifyZodProvider) => { diff --git a/backend/src/server/routes/v1/app-connection-routers/index.ts b/backend/src/server/routes/v1/app-connection-routers/index.ts index eeae5e5e3..6f6fa1991 100644 --- a/backend/src/server/routes/v1/app-connection-routers/index.ts +++ b/backend/src/server/routes/v1/app-connection-routers/index.ts @@ -13,6 +13,7 @@ import { registerHCVaultConnectionRouter } from "./hc-vault-connection-router"; import { registerHumanitecConnectionRouter } from "./humanitec-connection-router"; import { registerLdapConnectionRouter } from "./ldap-connection-router"; import { registerMsSqlConnectionRouter } from "./mssql-connection-router"; +import { registerOCIConnectionRouter } from "./oci-connection-router"; import { registerPostgresConnectionRouter } from "./postgres-connection-router"; import { registerTeamCityConnectionRouter } from "./teamcity-connection-router"; import { registerTerraformCloudConnectionRouter } from "./terraform-cloud-router"; @@ -40,5 +41,6 @@ export const APP_CONNECTION_REGISTER_ROUTER_MAP: Record { + registerAppConnectionEndpoints({ + app: AppConnection.OCI, + server, + sanitizedResponseSchema: SanitizedOCIConnectionSchema, + createSchema: CreateOCIConnectionSchema, + updateSchema: UpdateOCIConnectionSchema + }); + + // The following endpoints are for internal Infisical App use only and not part of the public API + server.route({ + method: "GET", + url: `/:connectionId/compartments`, + config: { + rateLimit: readLimit + }, + schema: { + params: z.object({ + connectionId: z.string().uuid() + }), + response: { + 200: z + .object({ + id: z.string(), + name: z.string() + }) + .array() + } + }, + onRequest: verifyAuth([AuthMode.JWT]), + handler: async (req) => { + const { connectionId } = req.params; + + const compartments = await server.services.appConnection.oci.listCompartments(connectionId, req.permission); + return compartments; + } + }); + + server.route({ + method: "GET", + url: `/:connectionId/vaults`, + config: { + rateLimit: readLimit + }, + schema: { + params: z.object({ + connectionId: z.string().uuid() + }), + querystring: z.object({ + compartmentOcid: z.string().min(1, "Compartment OCID required") + }), + response: { + 200: z + .object({ + id: z.string(), + displayName: z.string() + }) + .array() + } + }, + onRequest: verifyAuth([AuthMode.JWT]), + handler: async (req) => { + const { connectionId } = req.params; + const { compartmentOcid } = req.query; + + const vaults = await server.services.appConnection.oci.listVaults( + { connectionId, compartmentOcid }, + req.permission + ); + return vaults; + } + }); + + server.route({ + method: "GET", + url: `/:connectionId/vault-keys`, + config: { + rateLimit: readLimit + }, + schema: { + params: z.object({ + connectionId: z.string().uuid() + }), + querystring: z.object({ + compartmentOcid: z.string().min(1, "Compartment OCID required"), + vaultOcid: z.string().min(1, "Vault OCID required") + }), + response: { + 200: z + .object({ + id: z.string(), + displayName: z.string() + }) + .array() + } + }, + onRequest: verifyAuth([AuthMode.JWT]), + handler: async (req) => { + const { connectionId } = req.params; + const { compartmentOcid, vaultOcid } = req.query; + + const keys = await server.services.appConnection.oci.listVaultKeys( + { connectionId, compartmentOcid, vaultOcid }, + req.permission + ); + return keys; + } + }); +}; diff --git a/backend/src/server/routes/v1/secret-sync-routers/index.ts b/backend/src/server/routes/v1/secret-sync-routers/index.ts index 75b3ac68e..b5bd62ad6 100644 --- a/backend/src/server/routes/v1/secret-sync-routers/index.ts +++ b/backend/src/server/routes/v1/secret-sync-routers/index.ts @@ -10,6 +10,7 @@ import { registerGcpSyncRouter } from "./gcp-sync-router"; import { registerGitHubSyncRouter } from "./github-sync-router"; import { registerHCVaultSyncRouter } from "./hc-vault-sync-router"; import { registerHumanitecSyncRouter } from "./humanitec-sync-router"; +import { registerOCIVaultSyncRouter } from "./oci-vault-sync-router"; import { registerTeamCitySyncRouter } from "./teamcity-sync-router"; import { registerTerraformCloudSyncRouter } from "./terraform-cloud-sync-router"; import { registerVercelSyncRouter } from "./vercel-sync-router"; @@ -31,5 +32,6 @@ export const SECRET_SYNC_REGISTER_ROUTER_MAP: Record + registerSyncSecretsEndpoints({ + destination: SecretSync.OCIVault, + server, + responseSchema: OCIVaultSyncSchema, + createSchema: CreateOCIVaultSyncSchema, + updateSchema: UpdateOCIVaultSyncSchema + }); diff --git a/backend/src/server/routes/v1/secret-sync-routers/secret-sync-router.ts b/backend/src/server/routes/v1/secret-sync-routers/secret-sync-router.ts index 359040d7f..a7a561738 100644 --- a/backend/src/server/routes/v1/secret-sync-routers/secret-sync-router.ts +++ b/backend/src/server/routes/v1/secret-sync-routers/secret-sync-router.ts @@ -24,6 +24,7 @@ import { GcpSyncListItemSchema, GcpSyncSchema } from "@app/services/secret-sync/ import { GitHubSyncListItemSchema, GitHubSyncSchema } from "@app/services/secret-sync/github"; import { HCVaultSyncListItemSchema, HCVaultSyncSchema } from "@app/services/secret-sync/hc-vault"; import { HumanitecSyncListItemSchema, HumanitecSyncSchema } from "@app/services/secret-sync/humanitec"; +import { OCIVaultSyncListItemSchema, OCIVaultSyncSchema } from "@app/services/secret-sync/oci-vault"; import { TeamCitySyncListItemSchema, TeamCitySyncSchema } from "@app/services/secret-sync/teamcity"; import { TerraformCloudSyncListItemSchema, TerraformCloudSyncSchema } from "@app/services/secret-sync/terraform-cloud"; import { VercelSyncListItemSchema, VercelSyncSchema } from "@app/services/secret-sync/vercel"; @@ -43,7 +44,8 @@ const SecretSyncSchema = z.discriminatedUnion("destination", [ VercelSyncSchema, WindmillSyncSchema, HCVaultSyncSchema, - TeamCitySyncSchema + TeamCitySyncSchema, + OCIVaultSyncSchema ]); const SecretSyncOptionsSchema = z.discriminatedUnion("destination", [ @@ -60,7 +62,8 @@ const SecretSyncOptionsSchema = z.discriminatedUnion("destination", [ VercelSyncListItemSchema, WindmillSyncListItemSchema, HCVaultSyncListItemSchema, - TeamCitySyncListItemSchema + TeamCitySyncListItemSchema, + OCIVaultSyncListItemSchema ]); export const registerSecretSyncRouter = async (server: FastifyZodProvider) => { diff --git a/backend/src/services/app-connection/app-connection-enums.ts b/backend/src/services/app-connection/app-connection-enums.ts index c2912c2b6..6e09f1293 100644 --- a/backend/src/services/app-connection/app-connection-enums.ts +++ b/backend/src/services/app-connection/app-connection-enums.ts @@ -16,7 +16,8 @@ export enum AppConnection { Auth0 = "auth0", HCVault = "hashicorp-vault", LDAP = "ldap", - TeamCity = "teamcity" + TeamCity = "teamcity", + OCI = "oci" } export enum AWSRegion { diff --git a/backend/src/services/app-connection/app-connection-fns.ts b/backend/src/services/app-connection/app-connection-fns.ts index 95afdcbd2..f6fd894a6 100644 --- a/backend/src/services/app-connection/app-connection-fns.ts +++ b/backend/src/services/app-connection/app-connection-fns.ts @@ -53,6 +53,7 @@ import { } from "./humanitec"; import { getLdapConnectionListItem, LdapConnectionMethod, validateLdapConnectionCredentials } from "./ldap"; import { getMsSqlConnectionListItem, MsSqlConnectionMethod } from "./mssql"; +import { getOCIConnectionListItem, OCIConnectionMethod, validateOCIConnectionCredentials } from "./oci"; import { getPostgresConnectionListItem, PostgresConnectionMethod } from "./postgres"; import { getTeamCityConnectionListItem, @@ -91,7 +92,8 @@ export const listAppConnectionOptions = () => { getAuth0ConnectionListItem(), getHCVaultConnectionListItem(), getLdapConnectionListItem(), - getTeamCityConnectionListItem() + getTeamCityConnectionListItem(), + getOCIConnectionListItem() ].sort((a, b) => a.name.localeCompare(b.name)); }; @@ -160,7 +162,8 @@ export const validateAppConnectionCredentials = async ( [AppConnection.Windmill]: validateWindmillConnectionCredentials as TAppConnectionCredentialsValidator, [AppConnection.HCVault]: validateHCVaultConnectionCredentials as TAppConnectionCredentialsValidator, [AppConnection.LDAP]: validateLdapConnectionCredentials as TAppConnectionCredentialsValidator, - [AppConnection.TeamCity]: validateTeamCityConnectionCredentials as TAppConnectionCredentialsValidator + [AppConnection.TeamCity]: validateTeamCityConnectionCredentials as TAppConnectionCredentialsValidator, + [AppConnection.OCI]: validateOCIConnectionCredentials as TAppConnectionCredentialsValidator }; return VALIDATE_APP_CONNECTION_CREDENTIALS_MAP[appConnection.app](appConnection); @@ -176,6 +179,7 @@ export const getAppConnectionMethodName = (method: TAppConnection["method"]) => case GitHubConnectionMethod.OAuth: return "OAuth"; case AwsConnectionMethod.AccessKey: + case OCIConnectionMethod.AccessKey: return "Access Key"; case AwsConnectionMethod.AssumeRole: return "Assume Role"; @@ -250,5 +254,6 @@ export const TRANSITION_CONNECTION_CREDENTIALS_TO_PLATFORM: Record< [AppConnection.Auth0]: platformManagedCredentialsNotSupported, [AppConnection.HCVault]: platformManagedCredentialsNotSupported, [AppConnection.LDAP]: platformManagedCredentialsNotSupported, // we could support this in the future - [AppConnection.TeamCity]: platformManagedCredentialsNotSupported + [AppConnection.TeamCity]: platformManagedCredentialsNotSupported, + [AppConnection.OCI]: platformManagedCredentialsNotSupported }; diff --git a/backend/src/services/app-connection/app-connection-maps.ts b/backend/src/services/app-connection/app-connection-maps.ts index 05e00446c..c32336453 100644 --- a/backend/src/services/app-connection/app-connection-maps.ts +++ b/backend/src/services/app-connection/app-connection-maps.ts @@ -18,5 +18,6 @@ export const APP_CONNECTION_NAME_MAP: Record = { [AppConnection.Auth0]: "Auth0", [AppConnection.HCVault]: "Hashicorp Vault", [AppConnection.LDAP]: "LDAP", - [AppConnection.TeamCity]: "TeamCity" + [AppConnection.TeamCity]: "TeamCity", + [AppConnection.OCI]: "OCI" }; diff --git a/backend/src/services/app-connection/app-connection-service.ts b/backend/src/services/app-connection/app-connection-service.ts index 7a8b1a09c..85b63138a 100644 --- a/backend/src/services/app-connection/app-connection-service.ts +++ b/backend/src/services/app-connection/app-connection-service.ts @@ -49,6 +49,8 @@ import { ValidateHumanitecConnectionCredentialsSchema } from "./humanitec"; import { humanitecConnectionService } from "./humanitec/humanitec-connection-service"; import { ValidateLdapConnectionCredentialsSchema } from "./ldap"; import { ValidateMsSqlConnectionCredentialsSchema } from "./mssql"; +import { ValidateOCIConnectionCredentialsSchema } from "./oci"; +import { ociConnectionService } from "./oci/oci-connection-service"; import { ValidatePostgresConnectionCredentialsSchema } from "./postgres"; import { ValidateTeamCityConnectionCredentialsSchema } from "./teamcity"; import { teamcityConnectionService } from "./teamcity/teamcity-connection-service"; @@ -85,7 +87,8 @@ const VALIDATE_APP_CONNECTION_CREDENTIALS_MAP: Record>>; @@ -150,6 +157,7 @@ export type TAppConnectionInput = { id: string } & ( | THCVaultConnectionInput | TLdapConnectionInput | TTeamCityConnectionInput + | TOCIConnectionInput ); export type TSqlConnectionInput = TPostgresConnectionInput | TMsSqlConnectionInput; @@ -180,7 +188,8 @@ export type TAppConnectionConfig = | TAuth0ConnectionConfig | THCVaultConnectionConfig | TLdapConnectionConfig - | TTeamCityConnectionConfig; + | TTeamCityConnectionConfig + | TOCIConnectionConfig; export type TValidateAppConnectionCredentialsSchema = | TValidateAwsConnectionCredentialsSchema @@ -200,7 +209,8 @@ export type TValidateAppConnectionCredentialsSchema = | TValidateAuth0ConnectionCredentialsSchema | TValidateHCVaultConnectionCredentialsSchema | TValidateLdapConnectionCredentialsSchema - | TValidateTeamCityConnectionCredentialsSchema; + | TValidateTeamCityConnectionCredentialsSchema + | TValidateOCIConnectionCredentialsSchema; export type TListAwsConnectionKmsKeys = { connectionId: string; diff --git a/backend/src/services/app-connection/oci/index.ts b/backend/src/services/app-connection/oci/index.ts new file mode 100644 index 000000000..eb2850d34 --- /dev/null +++ b/backend/src/services/app-connection/oci/index.ts @@ -0,0 +1,4 @@ +export * from "./oci-connection-enums"; +export * from "./oci-connection-fns"; +export * from "./oci-connection-schemas"; +export * from "./oci-connection-types"; diff --git a/backend/src/services/app-connection/oci/oci-connection-enums.ts b/backend/src/services/app-connection/oci/oci-connection-enums.ts new file mode 100644 index 000000000..1b4319651 --- /dev/null +++ b/backend/src/services/app-connection/oci/oci-connection-enums.ts @@ -0,0 +1,3 @@ +export enum OCIConnectionMethod { + AccessKey = "access-key" +} diff --git a/backend/src/services/app-connection/oci/oci-connection-fns.ts b/backend/src/services/app-connection/oci/oci-connection-fns.ts new file mode 100644 index 000000000..5dcf6ee7a --- /dev/null +++ b/backend/src/services/app-connection/oci/oci-connection-fns.ts @@ -0,0 +1,139 @@ +import { common, identity, keymanagement } from "oci-sdk"; + +import { BadRequestError } from "@app/lib/errors"; +import { AppConnection } from "@app/services/app-connection/app-connection-enums"; + +import { OCIConnectionMethod } from "./oci-connection-enums"; +import { TOCIConnection, TOCIConnectionConfig } from "./oci-connection-types"; + +export const getOCIProvider = async (config: TOCIConnectionConfig) => { + const { + credentials: { fingerprint, privateKey, region, tenancyOcid, userOcid } + } = config; + + const provider = new common.SimpleAuthenticationDetailsProvider( + tenancyOcid, + userOcid, + fingerprint, + privateKey, + null, + common.Region.fromRegionId(region) + ); + + return provider; +}; + +export const getOCIConnectionListItem = () => { + return { + name: "OCI" as const, + app: AppConnection.OCI as const, + methods: Object.values(OCIConnectionMethod) as [OCIConnectionMethod.AccessKey] + }; +}; + +export const validateOCIConnectionCredentials = async (config: TOCIConnectionConfig) => { + const provider = await getOCIProvider(config); + + try { + const identityClient = new identity.IdentityClient({ + authenticationDetailsProvider: provider + }); + + // Get user details - a lightweight call that validates all credentials + await identityClient.getUser({ userId: config.credentials.userOcid }); + } catch (error: unknown) { + if (error instanceof Error) { + throw new BadRequestError({ + message: `Failed to validate credentials: ${error.message || "Unknown error"}` + }); + } + throw new BadRequestError({ + message: "Unable to validate connection: verify credentials" + }); + } + + return config.credentials; +}; + +export const listOCICompartments = async (appConnection: TOCIConnection) => { + const provider = await getOCIProvider(appConnection); + + const identityClient = new identity.IdentityClient({ authenticationDetailsProvider: provider }); + const keyManagementClient = new keymanagement.KmsVaultClient({ + authenticationDetailsProvider: provider + }); + + const rootCompartment = await identityClient + .getTenancy({ + tenancyId: appConnection.credentials.tenancyOcid + }) + .then((response) => ({ + ...response.tenancy, + id: appConnection.credentials.tenancyOcid, + name: response.tenancy.name ? `${response.tenancy.name} (root)` : "root" + })); + + const compartments = await identityClient.listCompartments({ + compartmentId: appConnection.credentials.tenancyOcid, + compartmentIdInSubtree: true, + accessLevel: identity.requests.ListCompartmentsRequest.AccessLevel.Any, + lifecycleState: identity.models.Compartment.LifecycleState.Active + }); + + const allCompartments = [rootCompartment, ...compartments.items]; + const filteredCompartments = []; + + for await (const compartment of allCompartments) { + try { + // Check if user can list vaults in this compartment + await keyManagementClient.listVaults({ + compartmentId: compartment.id, + limit: 1 + }); + + filteredCompartments.push(compartment); + } catch (error) { + // Do nothing + } + } + + return filteredCompartments; +}; + +export const listOCIVaults = async (appConnection: TOCIConnection, compartmentOcid: string) => { + const provider = await getOCIProvider(appConnection); + + const keyManagementClient = new keymanagement.KmsVaultClient({ + authenticationDetailsProvider: provider + }); + + const vaults = await keyManagementClient.listVaults({ + compartmentId: compartmentOcid + }); + + return vaults.items.filter((v) => v.lifecycleState === keymanagement.models.Vault.LifecycleState.Active); +}; + +export const listOCIVaultKeys = async (appConnection: TOCIConnection, compartmentOcid: string, vaultOcid: string) => { + const provider = await getOCIProvider(appConnection); + + const kmsVaultClient = new keymanagement.KmsVaultClient({ + authenticationDetailsProvider: provider + }); + + const vault = await kmsVaultClient.getVault({ + vaultId: vaultOcid + }); + + const keyManagementClient = new keymanagement.KmsManagementClient({ + authenticationDetailsProvider: provider + }); + + keyManagementClient.endpoint = vault.vault.managementEndpoint; + + const keys = await keyManagementClient.listKeys({ + compartmentId: compartmentOcid + }); + + return keys.items.filter((v) => v.lifecycleState === keymanagement.models.KeySummary.LifecycleState.Enabled); +}; diff --git a/backend/src/services/app-connection/oci/oci-connection-schemas.ts b/backend/src/services/app-connection/oci/oci-connection-schemas.ts new file mode 100644 index 000000000..f09564455 --- /dev/null +++ b/backend/src/services/app-connection/oci/oci-connection-schemas.ts @@ -0,0 +1,65 @@ +import z from "zod"; + +import { AppConnections } from "@app/lib/api-docs"; +import { AppConnection } from "@app/services/app-connection/app-connection-enums"; +import { + BaseAppConnectionSchema, + GenericCreateAppConnectionFieldsSchema, + GenericUpdateAppConnectionFieldsSchema +} from "@app/services/app-connection/app-connection-schemas"; + +import { OCIConnectionMethod } from "./oci-connection-enums"; + +export const OCIConnectionAccessTokenCredentialsSchema = z.object({ + userOcid: z.string().trim().min(1, "User OCID required").describe(AppConnections.CREDENTIALS.OCI.userOcid), + tenancyOcid: z.string().trim().min(1, "Tenancy OCID required").describe(AppConnections.CREDENTIALS.OCI.tenancyOcid), + region: z.string().trim().min(1, "Region required").describe(AppConnections.CREDENTIALS.OCI.region), + fingerprint: z.string().trim().min(1, "Fingerprint required").describe(AppConnections.CREDENTIALS.OCI.fingerprint), + privateKey: z.string().trim().min(1, "Private Key required").describe(AppConnections.CREDENTIALS.OCI.privateKey) +}); + +const BaseOCIConnectionSchema = BaseAppConnectionSchema.extend({ app: z.literal(AppConnection.OCI) }); + +export const OCIConnectionSchema = BaseOCIConnectionSchema.extend({ + method: z.literal(OCIConnectionMethod.AccessKey), + credentials: OCIConnectionAccessTokenCredentialsSchema +}); + +export const SanitizedOCIConnectionSchema = z.discriminatedUnion("method", [ + BaseOCIConnectionSchema.extend({ + method: z.literal(OCIConnectionMethod.AccessKey), + credentials: OCIConnectionAccessTokenCredentialsSchema.pick({ + userOcid: true, + tenancyOcid: true, + region: true, + fingerprint: true + }) + }) +]); + +export const ValidateOCIConnectionCredentialsSchema = z.discriminatedUnion("method", [ + z.object({ + method: z.literal(OCIConnectionMethod.AccessKey).describe(AppConnections.CREATE(AppConnection.OCI).method), + credentials: OCIConnectionAccessTokenCredentialsSchema.describe( + AppConnections.CREATE(AppConnection.OCI).credentials + ) + }) +]); + +export const CreateOCIConnectionSchema = ValidateOCIConnectionCredentialsSchema.and( + GenericCreateAppConnectionFieldsSchema(AppConnection.OCI) +); + +export const UpdateOCIConnectionSchema = z + .object({ + credentials: OCIConnectionAccessTokenCredentialsSchema.optional().describe( + AppConnections.UPDATE(AppConnection.OCI).credentials + ) + }) + .and(GenericUpdateAppConnectionFieldsSchema(AppConnection.OCI)); + +export const OCIConnectionListItemSchema = z.object({ + name: z.literal("OCI"), + app: z.literal(AppConnection.OCI), + methods: z.nativeEnum(OCIConnectionMethod).array() +}); diff --git a/backend/src/services/app-connection/oci/oci-connection-service.ts b/backend/src/services/app-connection/oci/oci-connection-service.ts new file mode 100644 index 000000000..2d72135e5 --- /dev/null +++ b/backend/src/services/app-connection/oci/oci-connection-service.ts @@ -0,0 +1,70 @@ +import { logger } from "@app/lib/logger"; +import { OrgServiceActor } from "@app/lib/types"; + +import { AppConnection } from "../app-connection-enums"; +import { listOCICompartments, listOCIVaultKeys, listOCIVaults } from "./oci-connection-fns"; +import { TOCIConnection } from "./oci-connection-types"; + +type TGetAppConnectionFunc = ( + app: AppConnection, + connectionId: string, + actor: OrgServiceActor +) => Promise; + +type TListOCIVaultsDTO = { + connectionId: string; + compartmentOcid: string; +}; + +type TListOCIVaultKeysDTO = { + connectionId: string; + compartmentOcid: string; + vaultOcid: string; +}; + +export const ociConnectionService = (getAppConnection: TGetAppConnectionFunc) => { + const listCompartments = async (connectionId: string, actor: OrgServiceActor) => { + const appConnection = await getAppConnection(AppConnection.OCI, connectionId, actor); + + try { + const compartments = await listOCICompartments(appConnection); + return compartments; + } catch (error) { + logger.error(error, "Failed to establish connection with OCI"); + return []; + } + }; + + const listVaults = async ({ connectionId, compartmentOcid }: TListOCIVaultsDTO, actor: OrgServiceActor) => { + const appConnection = await getAppConnection(AppConnection.OCI, connectionId, actor); + + try { + const vaults = await listOCIVaults(appConnection, compartmentOcid); + return vaults; + } catch (error) { + logger.error(error, "Failed to establish connection with OCI"); + return []; + } + }; + + const listVaultKeys = async ( + { connectionId, compartmentOcid, vaultOcid }: TListOCIVaultKeysDTO, + actor: OrgServiceActor + ) => { + const appConnection = await getAppConnection(AppConnection.OCI, connectionId, actor); + + try { + const keys = await listOCIVaultKeys(appConnection, compartmentOcid, vaultOcid); + return keys; + } catch (error) { + logger.error(error, "Failed to establish connection with OCI"); + return []; + } + }; + + return { + listCompartments, + listVaults, + listVaultKeys + }; +}; diff --git a/backend/src/services/app-connection/oci/oci-connection-types.ts b/backend/src/services/app-connection/oci/oci-connection-types.ts new file mode 100644 index 000000000..74ddfe0c8 --- /dev/null +++ b/backend/src/services/app-connection/oci/oci-connection-types.ts @@ -0,0 +1,22 @@ +import z from "zod"; + +import { DiscriminativePick } from "@app/lib/types"; + +import { AppConnection } from "../app-connection-enums"; +import { + CreateOCIConnectionSchema, + OCIConnectionSchema, + ValidateOCIConnectionCredentialsSchema +} from "./oci-connection-schemas"; + +export type TOCIConnection = z.infer; + +export type TOCIConnectionInput = z.infer & { + app: AppConnection.OCI; +}; + +export type TValidateOCIConnectionCredentialsSchema = typeof ValidateOCIConnectionCredentialsSchema; + +export type TOCIConnectionConfig = DiscriminativePick & { + orgId: string; +}; diff --git a/backend/src/services/secret-sync/oci-vault/index.ts b/backend/src/services/secret-sync/oci-vault/index.ts new file mode 100644 index 000000000..cee990de4 --- /dev/null +++ b/backend/src/services/secret-sync/oci-vault/index.ts @@ -0,0 +1,4 @@ +export * from "./oci-vault-sync-constants"; +export * from "./oci-vault-sync-fns"; +export * from "./oci-vault-sync-schemas"; +export * from "./oci-vault-sync-types"; diff --git a/backend/src/services/secret-sync/oci-vault/oci-vault-sync-constants.ts b/backend/src/services/secret-sync/oci-vault/oci-vault-sync-constants.ts new file mode 100644 index 000000000..9e2aad056 --- /dev/null +++ b/backend/src/services/secret-sync/oci-vault/oci-vault-sync-constants.ts @@ -0,0 +1,10 @@ +import { AppConnection } from "@app/services/app-connection/app-connection-enums"; +import { SecretSync } from "@app/services/secret-sync/secret-sync-enums"; +import { TSecretSyncListItem } from "@app/services/secret-sync/secret-sync-types"; + +export const OCI_VAULT_SYNC_LIST_OPTION: TSecretSyncListItem = { + name: "OCI Vault", + destination: SecretSync.OCIVault, + connection: AppConnection.OCI, + canImportSecrets: true +}; diff --git a/backend/src/services/secret-sync/oci-vault/oci-vault-sync-fns.ts b/backend/src/services/secret-sync/oci-vault/oci-vault-sync-fns.ts new file mode 100644 index 000000000..95045e1e9 --- /dev/null +++ b/backend/src/services/secret-sync/oci-vault/oci-vault-sync-fns.ts @@ -0,0 +1,292 @@ +import { secrets, vault } from "oci-sdk"; + +import { delay } from "@app/lib/delay"; +import { getOCIProvider } from "@app/services/app-connection/oci"; +import { + TCreateOCIVaultVariable, + TDeleteOCIVaultVariable, + TOCIVaultListVariables, + TOCIVaultSyncWithCredentials, + TUnmarkOCIVaultVariableFromDeletion, + TUpdateOCIVaultVariable +} from "@app/services/secret-sync/oci-vault/oci-vault-sync-types"; +import { SecretSyncError } from "@app/services/secret-sync/secret-sync-errors"; +import { TSecretMap } from "@app/services/secret-sync/secret-sync-types"; + +const listOCIVaultVariables = async ({ provider, compartmentId, vaultId, onlyActive }: TOCIVaultListVariables) => { + const vaultsClient = new vault.VaultsClient({ authenticationDetailsProvider: provider }); + const secretsClient = new secrets.SecretsClient({ authenticationDetailsProvider: provider }); + + const secretsRes = await vaultsClient.listSecrets({ + compartmentId, + vaultId, + lifecycleState: onlyActive ? vault.models.SecretSummary.LifecycleState.Active : undefined + }); + + const result: Record = {}; + + for await (const s of secretsRes.items) { + let secretValue = ""; + + if (s.lifecycleState === vault.models.SecretSummary.LifecycleState.Active) { + const secretBundle = await secretsClient.getSecretBundle({ + secretId: s.id + }); + + secretValue = Buffer.from(secretBundle.secretBundle.secretBundleContent?.content || "", "base64").toString( + "utf-8" + ); + } + + result[s.secretName] = { + ...s, + name: s.secretName, + value: secretValue + }; + } + + return result; +}; + +const createOCIVaultVariable = async ({ + provider, + compartmentId, + vaultId, + keyId, + name, + value +}: TCreateOCIVaultVariable) => { + if (!value) return; + + const vaultsClient = new vault.VaultsClient({ authenticationDetailsProvider: provider }); + + return vaultsClient.createSecret({ + createSecretDetails: { + compartmentId, + vaultId, + keyId, + secretName: name, + enableAutoGeneration: false, + secretContent: { + content: Buffer.from(value).toString("base64"), + contentType: "BASE64" + } + } + }); +}; + +const updateOCIVaultVariable = async ({ provider, secretId, value }: TUpdateOCIVaultVariable) => { + if (!value) return; + + const vaultsClient = new vault.VaultsClient({ authenticationDetailsProvider: provider }); + + return vaultsClient.updateSecret({ + secretId, + updateSecretDetails: { + enableAutoGeneration: false, + secretContent: { + content: Buffer.from(value).toString("base64"), + contentType: "BASE64" + } + } + }); +}; + +const deleteOCIVaultVariable = async ({ provider, secretId }: TDeleteOCIVaultVariable) => { + const vaultsClient = new vault.VaultsClient({ authenticationDetailsProvider: provider }); + + // Schedule a secret deletion 7 days from now. OCI Vault requires a MINIMUM buffer period of 7 days + return vaultsClient.scheduleSecretDeletion({ + secretId, + scheduleSecretDeletionDetails: { + timeOfDeletion: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) + } + }); +}; + +const unmarkOCIVaultVariableFromDeletion = async ({ provider, secretId }: TUnmarkOCIVaultVariableFromDeletion) => { + const vaultsClient = new vault.VaultsClient({ authenticationDetailsProvider: provider }); + + return vaultsClient.cancelSecretDeletion({ + secretId + }); +}; + +export const OCIVaultSyncFns = { + syncSecrets: async (secretSync: TOCIVaultSyncWithCredentials, secretMap: TSecretMap) => { + const { + connection, + destinationConfig: { compartmentOcid, vaultOcid, keyOcid } + } = secretSync; + + const provider = await getOCIProvider(connection); + const variables = await listOCIVaultVariables({ provider, compartmentId: compartmentOcid, vaultId: vaultOcid }); + + // Throw an error if any keys are updating in OCI vault to prevent skipped updates + if ( + Object.entries(variables).some( + ([, secret]) => + secret.lifecycleState === vault.models.SecretSummary.LifecycleState.Updating || + secret.lifecycleState === vault.models.SecretSummary.LifecycleState.CancellingDeletion || + secret.lifecycleState === vault.models.SecretSummary.LifecycleState.Creating || + secret.lifecycleState === vault.models.SecretSummary.LifecycleState.Deleting || + secret.lifecycleState === vault.models.SecretSummary.LifecycleState.SchedulingDeletion + ) + ) { + throw new SecretSyncError({ + error: "Cannot sync while keys are updating in OCI Vault." + }); + } + + // Create secrets + for await (const entry of Object.entries(secretMap)) { + const [key, { value }] = entry; + + // skip secrets that don't have a value set + if (!value) { + // eslint-disable-next-line no-continue + continue; + } + + const existingVariable = Object.values(variables).find((v) => v.secretName === key); + + if (!existingVariable) { + try { + await createOCIVaultVariable({ + compartmentId: compartmentOcid, + vaultId: vaultOcid, + provider, + keyId: keyOcid, + name: key, + value + }); + } catch (error) { + throw new SecretSyncError({ + error, + secretKey: key + }); + } + } else if (existingVariable.lifecycleState === vault.models.SecretSummary.LifecycleState.PendingDeletion) { + // If a secret exists but is pending deletion, cancel the deletion and update the secret + await unmarkOCIVaultVariableFromDeletion({ + provider, + compartmentId: compartmentOcid, + vaultId: vaultOcid, + secretId: existingVariable.id + }); + + const vaultsClient = new vault.VaultsClient({ authenticationDetailsProvider: provider }); + const MAX_RETRIES = 10; + + for (let i = 0; i < MAX_RETRIES; i += 1) { + // eslint-disable-next-line no-await-in-loop + await delay(5000); + + // eslint-disable-next-line no-await-in-loop + const secret = await vaultsClient.getSecret({ + secretId: existingVariable.id + }); + + if (secret.secret.lifecycleState === vault.models.SecretSummary.LifecycleState.Active) { + // eslint-disable-next-line no-await-in-loop + await updateOCIVaultVariable({ + provider, + compartmentId: compartmentOcid, + vaultId: vaultOcid, + secretId: existingVariable.id, + value + }); + break; + } + + if (i === MAX_RETRIES - 1) { + throw new SecretSyncError({ + error: "Failed to update secret after cancelling deletion.", + secretKey: key + }); + } + } + } + } + + // Update and delete secrets + for await (const [key, variable] of Object.entries(variables)) { + // Only update / delete active secrets + if (variable.lifecycleState === vault.models.SecretSummary.LifecycleState.Active) { + if (key in secretMap && secretMap[key].value.length > 0) { + if (variable.value !== secretMap[key].value) { + try { + await updateOCIVaultVariable({ + compartmentId: compartmentOcid, + vaultId: vaultOcid, + provider, + secretId: variable.id, + value: secretMap[key].value + }); + } catch (error) { + throw new SecretSyncError({ + error, + secretKey: key + }); + } + } + } else if (!secretSync.syncOptions.disableSecretDeletion) { + try { + await deleteOCIVaultVariable({ + compartmentId: compartmentOcid, + vaultId: vaultOcid, + provider, + secretId: variable.id + }); + } catch (error) { + throw new SecretSyncError({ + error, + secretKey: key + }); + } + } + } + } + }, + removeSecrets: async (secretSync: TOCIVaultSyncWithCredentials, secretMap: TSecretMap) => { + const { + connection, + destinationConfig: { compartmentOcid, vaultOcid } + } = secretSync; + + const provider = await getOCIProvider(connection); + const variables = await listOCIVaultVariables({ + provider, + compartmentId: compartmentOcid, + vaultId: vaultOcid, + onlyActive: true + }); + + for await (const [key, variable] of Object.entries(variables)) { + if (key in secretMap) { + try { + await deleteOCIVaultVariable({ + compartmentId: compartmentOcid, + vaultId: vaultOcid, + provider, + secretId: variable.id + }); + } catch (error) { + throw new SecretSyncError({ + error, + secretKey: key + }); + } + } + } + }, + getSecrets: async (secretSync: TOCIVaultSyncWithCredentials) => { + const { + connection, + destinationConfig: { compartmentOcid, vaultOcid } + } = secretSync; + + const provider = await getOCIProvider(connection); + return listOCIVaultVariables({ provider, compartmentId: compartmentOcid, vaultId: vaultOcid, onlyActive: true }); + } +}; diff --git a/backend/src/services/secret-sync/oci-vault/oci-vault-sync-schemas.ts b/backend/src/services/secret-sync/oci-vault/oci-vault-sync-schemas.ts new file mode 100644 index 000000000..84a58bc8a --- /dev/null +++ b/backend/src/services/secret-sync/oci-vault/oci-vault-sync-schemas.ts @@ -0,0 +1,70 @@ +import RE2 from "re2"; +import { z } from "zod"; + +import { SecretSyncs } from "@app/lib/api-docs"; +import { AppConnection } from "@app/services/app-connection/app-connection-enums"; +import { SecretSync } from "@app/services/secret-sync/secret-sync-enums"; +import { + BaseSecretSyncSchema, + GenericCreateSecretSyncFieldsSchema, + GenericUpdateSecretSyncFieldsSchema +} from "@app/services/secret-sync/secret-sync-schemas"; +import { TSyncOptionsConfig } from "@app/services/secret-sync/secret-sync-types"; + +const OCIVaultSyncDestinationConfigSchema = z.object({ + compartmentOcid: z + .string() + .trim() + .min(1, "Compartment OCID required") + .refine( + (val) => new RE2("^ocid1\\.(tenancy|compartment)\\.oc1\\..+$").test(val), + "Invalid Compartment OCID format. Must start with ocid1.tenancy.oc1. or ocid1.compartment.oc1." + ) + .describe(SecretSyncs.DESTINATION_CONFIG.OCI_VAULT.compartmentOcid), + vaultOcid: z + .string() + .trim() + .min(1, "Vault OCID required") + .refine( + (val) => new RE2("^ocid1\\.vault\\.oc1\\..+$").test(val), + "Invalid Vault OCID format. Must start with ocid1.vault.oc1." + ) + .describe(SecretSyncs.DESTINATION_CONFIG.OCI_VAULT.vaultOcid), + keyOcid: z + .string() + .trim() + .min(1, "Key OCID required") + .refine( + (val) => new RE2("^ocid1\\.key\\.oc1\\..+$").test(val), + "Invalid Key OCID format. Must start with ocid1.key.oc1." + ) + .describe(SecretSyncs.DESTINATION_CONFIG.OCI_VAULT.keyOcid) +}); + +const OCIVaultSyncOptionsConfig: TSyncOptionsConfig = { canImportSecrets: true }; + +export const OCIVaultSyncSchema = BaseSecretSyncSchema(SecretSync.OCIVault, OCIVaultSyncOptionsConfig).extend({ + destination: z.literal(SecretSync.OCIVault), + destinationConfig: OCIVaultSyncDestinationConfigSchema +}); + +export const CreateOCIVaultSyncSchema = GenericCreateSecretSyncFieldsSchema( + SecretSync.OCIVault, + OCIVaultSyncOptionsConfig +).extend({ + destinationConfig: OCIVaultSyncDestinationConfigSchema +}); + +export const UpdateOCIVaultSyncSchema = GenericUpdateSecretSyncFieldsSchema( + SecretSync.OCIVault, + OCIVaultSyncOptionsConfig +).extend({ + destinationConfig: OCIVaultSyncDestinationConfigSchema.optional() +}); + +export const OCIVaultSyncListItemSchema = z.object({ + name: z.literal("OCI Vault"), + connection: z.literal(AppConnection.OCI), + destination: z.literal(SecretSync.OCIVault), + canImportSecrets: z.literal(true) +}); diff --git a/backend/src/services/secret-sync/oci-vault/oci-vault-sync-types.ts b/backend/src/services/secret-sync/oci-vault/oci-vault-sync-types.ts new file mode 100644 index 000000000..c040cd0c0 --- /dev/null +++ b/backend/src/services/secret-sync/oci-vault/oci-vault-sync-types.ts @@ -0,0 +1,48 @@ +import { SimpleAuthenticationDetailsProvider } from "oci-sdk"; +import { z } from "zod"; + +import { TOCIConnection } from "@app/services/app-connection/oci"; + +import { CreateOCIVaultSyncSchema, OCIVaultSyncListItemSchema, OCIVaultSyncSchema } from "./oci-vault-sync-schemas"; + +export type TOCIVaultSync = z.infer; + +export type TOCIVaultSyncInput = z.infer; + +export type TOCIVaultSyncListItem = z.infer; + +export type TOCIVaultSyncWithCredentials = TOCIVaultSync & { + connection: TOCIConnection; +}; + +export type TOCIVaultVariable = { + id: string; + name: string; + value: string; +}; + +export type TOCIVaultListVariables = { + provider: SimpleAuthenticationDetailsProvider; + compartmentId: string; + vaultId: string; + onlyActive?: boolean; // Whether to filter for only active secrets. Removes deleted / scheduled for deletion secrets +}; + +export type TCreateOCIVaultVariable = TOCIVaultListVariables & { + keyId: string; + name: string; + value: string; +}; + +export type TUpdateOCIVaultVariable = TOCIVaultListVariables & { + secretId: string; + value: string; +}; + +export type TDeleteOCIVaultVariable = TOCIVaultListVariables & { + secretId: string; +}; + +export type TUnmarkOCIVaultVariableFromDeletion = TOCIVaultListVariables & { + secretId: string; +}; diff --git a/backend/src/services/secret-sync/secret-sync-enums.ts b/backend/src/services/secret-sync/secret-sync-enums.ts index 9d59ebb76..a0982c5b6 100644 --- a/backend/src/services/secret-sync/secret-sync-enums.ts +++ b/backend/src/services/secret-sync/secret-sync-enums.ts @@ -12,7 +12,8 @@ export enum SecretSync { Vercel = "vercel", Windmill = "windmill", HCVault = "hashicorp-vault", - TeamCity = "teamcity" + TeamCity = "teamcity", + OCIVault = "oci-vault" } export enum SecretSyncInitialSyncBehavior { diff --git a/backend/src/services/secret-sync/secret-sync-fns.ts b/backend/src/services/secret-sync/secret-sync-fns.ts index 5749852d7..d029a000a 100644 --- a/backend/src/services/secret-sync/secret-sync-fns.ts +++ b/backend/src/services/secret-sync/secret-sync-fns.ts @@ -28,6 +28,7 @@ import { GcpSyncFns } from "./gcp/gcp-sync-fns"; import { HC_VAULT_SYNC_LIST_OPTION, HCVaultSyncFns } from "./hc-vault"; import { HUMANITEC_SYNC_LIST_OPTION } from "./humanitec"; import { HumanitecSyncFns } from "./humanitec/humanitec-sync-fns"; +import { OCI_VAULT_SYNC_LIST_OPTION, OCIVaultSyncFns } from "./oci-vault"; import { TEAMCITY_SYNC_LIST_OPTION, TeamCitySyncFns } from "./teamcity"; import { TERRAFORM_CLOUD_SYNC_LIST_OPTION, TerraformCloudSyncFns } from "./terraform-cloud"; import { VERCEL_SYNC_LIST_OPTION, VercelSyncFns } from "./vercel"; @@ -47,7 +48,8 @@ const SECRET_SYNC_LIST_OPTIONS: Record = { [SecretSync.Vercel]: VERCEL_SYNC_LIST_OPTION, [SecretSync.Windmill]: WINDMILL_SYNC_LIST_OPTION, [SecretSync.HCVault]: HC_VAULT_SYNC_LIST_OPTION, - [SecretSync.TeamCity]: TEAMCITY_SYNC_LIST_OPTION + [SecretSync.TeamCity]: TEAMCITY_SYNC_LIST_OPTION, + [SecretSync.OCIVault]: OCI_VAULT_SYNC_LIST_OPTION }; export const listSecretSyncOptions = () => { @@ -148,6 +150,8 @@ export const SecretSyncFns = { return HCVaultSyncFns.syncSecrets(secretSync, secretMap); case SecretSync.TeamCity: return TeamCitySyncFns.syncSecrets(secretSync, secretMap); + case SecretSync.OCIVault: + return OCIVaultSyncFns.syncSecrets(secretSync, secretMap); default: throw new Error( `Unhandled sync destination for sync secrets fns: ${(secretSync as TSecretSyncWithCredentials).destination}` @@ -213,6 +217,9 @@ export const SecretSyncFns = { case SecretSync.TeamCity: secretMap = await TeamCitySyncFns.getSecrets(secretSync); break; + case SecretSync.OCIVault: + secretMap = await OCIVaultSyncFns.getSecrets(secretSync); + break; default: throw new Error( `Unhandled sync destination for get secrets fns: ${(secretSync as TSecretSyncWithCredentials).destination}` @@ -270,6 +277,8 @@ export const SecretSyncFns = { return HCVaultSyncFns.removeSecrets(secretSync, secretMap); case SecretSync.TeamCity: return TeamCitySyncFns.removeSecrets(secretSync, secretMap); + case SecretSync.OCIVault: + return OCIVaultSyncFns.removeSecrets(secretSync, secretMap); default: throw new Error( `Unhandled sync destination for remove secrets fns: ${(secretSync as TSecretSyncWithCredentials).destination}` diff --git a/backend/src/services/secret-sync/secret-sync-maps.ts b/backend/src/services/secret-sync/secret-sync-maps.ts index c6d7adc8c..21cb912b4 100644 --- a/backend/src/services/secret-sync/secret-sync-maps.ts +++ b/backend/src/services/secret-sync/secret-sync-maps.ts @@ -15,7 +15,8 @@ export const SECRET_SYNC_NAME_MAP: Record = { [SecretSync.Vercel]: "Vercel", [SecretSync.Windmill]: "Windmill", [SecretSync.HCVault]: "Hashicorp Vault", - [SecretSync.TeamCity]: "TeamCity" + [SecretSync.TeamCity]: "TeamCity", + [SecretSync.OCIVault]: "OCI Vault" }; export const SECRET_SYNC_CONNECTION_MAP: Record = { @@ -32,5 +33,6 @@ export const SECRET_SYNC_CONNECTION_MAP: Record = { [SecretSync.Vercel]: AppConnection.Vercel, [SecretSync.Windmill]: AppConnection.Windmill, [SecretSync.HCVault]: AppConnection.HCVault, - [SecretSync.TeamCity]: AppConnection.TeamCity + [SecretSync.TeamCity]: AppConnection.TeamCity, + [SecretSync.OCIVault]: AppConnection.OCI }; diff --git a/backend/src/services/secret-sync/secret-sync-types.ts b/backend/src/services/secret-sync/secret-sync-types.ts index e88174cc6..64d027e18 100644 --- a/backend/src/services/secret-sync/secret-sync-types.ts +++ b/backend/src/services/secret-sync/secret-sync-types.ts @@ -67,6 +67,7 @@ import { THumanitecSyncListItem, THumanitecSyncWithCredentials } from "./humanitec"; +import { TOCIVaultSync, TOCIVaultSyncInput, TOCIVaultSyncListItem, TOCIVaultSyncWithCredentials } from "./oci-vault"; import { TTeamCitySync, TTeamCitySyncInput, @@ -95,7 +96,8 @@ export type TSecretSync = | TVercelSync | TWindmillSync | THCVaultSync - | TTeamCitySync; + | TTeamCitySync + | TOCIVaultSync; export type TSecretSyncWithCredentials = | TAwsParameterStoreSyncWithCredentials @@ -111,7 +113,8 @@ export type TSecretSyncWithCredentials = | TVercelSyncWithCredentials | TWindmillSyncWithCredentials | THCVaultSyncWithCredentials - | TTeamCitySyncWithCredentials; + | TTeamCitySyncWithCredentials + | TOCIVaultSyncWithCredentials; export type TSecretSyncInput = | TAwsParameterStoreSyncInput @@ -127,7 +130,8 @@ export type TSecretSyncInput = | TVercelSyncInput | TWindmillSyncInput | THCVaultSyncInput - | TTeamCitySyncInput; + | TTeamCitySyncInput + | TOCIVaultSyncInput; export type TSecretSyncListItem = | TAwsParameterStoreSyncListItem @@ -143,7 +147,8 @@ export type TSecretSyncListItem = | TVercelSyncListItem | TWindmillSyncListItem | THCVaultSyncListItem - | TTeamCitySyncListItem; + | TTeamCitySyncListItem + | TOCIVaultSyncListItem; export type TSyncOptionsConfig = { canImportSecrets: boolean; diff --git a/docs/api-reference/endpoints/app-connections/oci/available.mdx b/docs/api-reference/endpoints/app-connections/oci/available.mdx new file mode 100644 index 000000000..19d83e5b7 --- /dev/null +++ b/docs/api-reference/endpoints/app-connections/oci/available.mdx @@ -0,0 +1,4 @@ +--- +title: "Available" +openapi: "GET /api/v1/app-connections/oci/available" +--- diff --git a/docs/api-reference/endpoints/app-connections/oci/create.mdx b/docs/api-reference/endpoints/app-connections/oci/create.mdx new file mode 100644 index 000000000..e15877121 --- /dev/null +++ b/docs/api-reference/endpoints/app-connections/oci/create.mdx @@ -0,0 +1,8 @@ +--- +title: "Create" +openapi: "POST /api/v1/app-connections/oci" +--- + + + Check out the configuration docs for [OCI Connections](/integrations/app-connections/oci) to learn how to obtain the required credentials. + diff --git a/docs/api-reference/endpoints/app-connections/oci/delete.mdx b/docs/api-reference/endpoints/app-connections/oci/delete.mdx new file mode 100644 index 000000000..990700885 --- /dev/null +++ b/docs/api-reference/endpoints/app-connections/oci/delete.mdx @@ -0,0 +1,4 @@ +--- +title: "Delete" +openapi: "DELETE /api/v1/app-connections/oci/{connectionId}" +--- diff --git a/docs/api-reference/endpoints/app-connections/oci/get-by-id.mdx b/docs/api-reference/endpoints/app-connections/oci/get-by-id.mdx new file mode 100644 index 000000000..a7541b227 --- /dev/null +++ b/docs/api-reference/endpoints/app-connections/oci/get-by-id.mdx @@ -0,0 +1,4 @@ +--- +title: "Get by ID" +openapi: "GET /api/v1/app-connections/oci/{connectionId}" +--- diff --git a/docs/api-reference/endpoints/app-connections/oci/get-by-name.mdx b/docs/api-reference/endpoints/app-connections/oci/get-by-name.mdx new file mode 100644 index 000000000..1c920e14f --- /dev/null +++ b/docs/api-reference/endpoints/app-connections/oci/get-by-name.mdx @@ -0,0 +1,4 @@ +--- +title: "Get by Name" +openapi: "GET /api/v1/app-connections/oci/connection-name/{connectionName}" +--- diff --git a/docs/api-reference/endpoints/app-connections/oci/list.mdx b/docs/api-reference/endpoints/app-connections/oci/list.mdx new file mode 100644 index 000000000..ba4430073 --- /dev/null +++ b/docs/api-reference/endpoints/app-connections/oci/list.mdx @@ -0,0 +1,4 @@ +--- +title: "List" +openapi: "GET /api/v1/app-connections/oci" +--- diff --git a/docs/api-reference/endpoints/app-connections/oci/update.mdx b/docs/api-reference/endpoints/app-connections/oci/update.mdx new file mode 100644 index 000000000..c012009a2 --- /dev/null +++ b/docs/api-reference/endpoints/app-connections/oci/update.mdx @@ -0,0 +1,8 @@ +--- +title: "Update" +openapi: "PATCH /api/v1/app-connections/oci/{connectionId}" +--- + + + Check out the configuration docs for [OCI Connections](/integrations/app-connections/oci) to learn how to obtain the required credentials. + diff --git a/docs/api-reference/endpoints/secret-syncs/oci-vault/create.mdx b/docs/api-reference/endpoints/secret-syncs/oci-vault/create.mdx new file mode 100644 index 000000000..fa3ac2738 --- /dev/null +++ b/docs/api-reference/endpoints/secret-syncs/oci-vault/create.mdx @@ -0,0 +1,4 @@ +--- +title: "Create" +openapi: "POST /api/v1/secret-syncs/oci-vault" +--- diff --git a/docs/api-reference/endpoints/secret-syncs/oci-vault/delete.mdx b/docs/api-reference/endpoints/secret-syncs/oci-vault/delete.mdx new file mode 100644 index 000000000..81f208308 --- /dev/null +++ b/docs/api-reference/endpoints/secret-syncs/oci-vault/delete.mdx @@ -0,0 +1,4 @@ +--- +title: "Delete" +openapi: "DELETE /api/v1/secret-syncs/oci-vault/{syncId}" +--- diff --git a/docs/api-reference/endpoints/secret-syncs/oci-vault/get-by-id.mdx b/docs/api-reference/endpoints/secret-syncs/oci-vault/get-by-id.mdx new file mode 100644 index 000000000..52b3201dc --- /dev/null +++ b/docs/api-reference/endpoints/secret-syncs/oci-vault/get-by-id.mdx @@ -0,0 +1,4 @@ +--- +title: "Get by ID" +openapi: "GET /api/v1/secret-syncs/oci-vault/{syncId}" +--- diff --git a/docs/api-reference/endpoints/secret-syncs/oci-vault/get-by-name.mdx b/docs/api-reference/endpoints/secret-syncs/oci-vault/get-by-name.mdx new file mode 100644 index 000000000..eabc8794c --- /dev/null +++ b/docs/api-reference/endpoints/secret-syncs/oci-vault/get-by-name.mdx @@ -0,0 +1,4 @@ +--- +title: "Get by Name" +openapi: "GET /api/v1/secret-syncs/oci-vault/sync-name/{syncName}" +--- diff --git a/docs/api-reference/endpoints/secret-syncs/oci-vault/import-secrets.mdx b/docs/api-reference/endpoints/secret-syncs/oci-vault/import-secrets.mdx new file mode 100644 index 000000000..27ca686d6 --- /dev/null +++ b/docs/api-reference/endpoints/secret-syncs/oci-vault/import-secrets.mdx @@ -0,0 +1,4 @@ +--- +title: "Import Secrets" +openapi: "POST /api/v1/secret-syncs/oci-vault/{syncId}/import-secrets" +--- diff --git a/docs/api-reference/endpoints/secret-syncs/oci-vault/list.mdx b/docs/api-reference/endpoints/secret-syncs/oci-vault/list.mdx new file mode 100644 index 000000000..88cd2a44a --- /dev/null +++ b/docs/api-reference/endpoints/secret-syncs/oci-vault/list.mdx @@ -0,0 +1,4 @@ +--- +title: "List" +openapi: "GET /api/v1/secret-syncs/oci-vault" +--- diff --git a/docs/api-reference/endpoints/secret-syncs/oci-vault/remove-secrets.mdx b/docs/api-reference/endpoints/secret-syncs/oci-vault/remove-secrets.mdx new file mode 100644 index 000000000..e98e7140e --- /dev/null +++ b/docs/api-reference/endpoints/secret-syncs/oci-vault/remove-secrets.mdx @@ -0,0 +1,4 @@ +--- +title: "Remove Secrets" +openapi: "POST /api/v1/secret-syncs/oci-vault/{syncId}/remove-secrets" +--- diff --git a/docs/api-reference/endpoints/secret-syncs/oci-vault/sync-secrets.mdx b/docs/api-reference/endpoints/secret-syncs/oci-vault/sync-secrets.mdx new file mode 100644 index 000000000..38ea4331c --- /dev/null +++ b/docs/api-reference/endpoints/secret-syncs/oci-vault/sync-secrets.mdx @@ -0,0 +1,4 @@ +--- +title: "Sync Secrets" +openapi: "POST /api/v1/secret-syncs/oci-vault/{syncId}/sync-secrets" +--- diff --git a/docs/api-reference/endpoints/secret-syncs/oci-vault/update.mdx b/docs/api-reference/endpoints/secret-syncs/oci-vault/update.mdx new file mode 100644 index 000000000..06f1d9d1c --- /dev/null +++ b/docs/api-reference/endpoints/secret-syncs/oci-vault/update.mdx @@ -0,0 +1,4 @@ +--- +title: "Update" +openapi: "PATCH /api/v1/secret-syncs/oci-vault/{syncId}" +--- diff --git a/docs/images/app-connections/oci/add-api-key.png b/docs/images/app-connections/oci/add-api-key.png new file mode 100644 index 000000000..049ea4c87 Binary files /dev/null and b/docs/images/app-connections/oci/add-api-key.png differ diff --git a/docs/images/app-connections/oci/app-connection-created.png b/docs/images/app-connections/oci/app-connection-created.png new file mode 100644 index 000000000..73edfa441 Binary files /dev/null and b/docs/images/app-connections/oci/app-connection-created.png differ diff --git a/docs/images/app-connections/oci/app-connection-modal.png b/docs/images/app-connections/oci/app-connection-modal.png new file mode 100644 index 000000000..c4ca6c0fb Binary files /dev/null and b/docs/images/app-connections/oci/app-connection-modal.png differ diff --git a/docs/images/app-connections/oci/app-connection-option.png b/docs/images/app-connections/oci/app-connection-option.png new file mode 100644 index 000000000..1651316c6 Binary files /dev/null and b/docs/images/app-connections/oci/app-connection-option.png differ diff --git a/docs/images/app-connections/oci/click-create-policy.png b/docs/images/app-connections/oci/click-create-policy.png new file mode 100644 index 000000000..edc5a74e9 Binary files /dev/null and b/docs/images/app-connections/oci/click-create-policy.png differ diff --git a/docs/images/app-connections/oci/click-create-user.png b/docs/images/app-connections/oci/click-create-user.png new file mode 100644 index 000000000..d4422b1a4 Binary files /dev/null and b/docs/images/app-connections/oci/click-create-user.png differ diff --git a/docs/images/app-connections/oci/create-group.png b/docs/images/app-connections/oci/create-group.png new file mode 100644 index 000000000..9063ed737 Binary files /dev/null and b/docs/images/app-connections/oci/create-group.png differ diff --git a/docs/images/app-connections/oci/create-policy.png b/docs/images/app-connections/oci/create-policy.png new file mode 100644 index 000000000..ea666e09e Binary files /dev/null and b/docs/images/app-connections/oci/create-policy.png differ diff --git a/docs/images/app-connections/oci/create-user.png b/docs/images/app-connections/oci/create-user.png new file mode 100644 index 000000000..f10488544 Binary files /dev/null and b/docs/images/app-connections/oci/create-user.png differ diff --git a/docs/images/app-connections/oci/search-domains.png b/docs/images/app-connections/oci/search-domains.png new file mode 100644 index 000000000..b56f85350 Binary files /dev/null and b/docs/images/app-connections/oci/search-domains.png differ diff --git a/docs/images/app-connections/oci/search-policies.png b/docs/images/app-connections/oci/search-policies.png new file mode 100644 index 000000000..d541fdbbe Binary files /dev/null and b/docs/images/app-connections/oci/search-policies.png differ diff --git a/docs/images/app-connections/oci/select-api-keys.png b/docs/images/app-connections/oci/select-api-keys.png new file mode 100644 index 000000000..7c63e0919 Binary files /dev/null and b/docs/images/app-connections/oci/select-api-keys.png differ diff --git a/docs/images/app-connections/oci/select-domain.png b/docs/images/app-connections/oci/select-domain.png new file mode 100644 index 000000000..9190de801 Binary files /dev/null and b/docs/images/app-connections/oci/select-domain.png differ diff --git a/docs/images/app-connections/oci/select-groups.png b/docs/images/app-connections/oci/select-groups.png new file mode 100644 index 000000000..d958900a3 Binary files /dev/null and b/docs/images/app-connections/oci/select-groups.png differ diff --git a/docs/images/app-connections/oci/select-users.png b/docs/images/app-connections/oci/select-users.png new file mode 100644 index 000000000..392fd7000 Binary files /dev/null and b/docs/images/app-connections/oci/select-users.png differ diff --git a/docs/images/app-connections/oci/user-info.png b/docs/images/app-connections/oci/user-info.png new file mode 100644 index 000000000..24688d084 Binary files /dev/null and b/docs/images/app-connections/oci/user-info.png differ diff --git a/docs/images/secret-syncs/oci-vault/configure-destination.png b/docs/images/secret-syncs/oci-vault/configure-destination.png new file mode 100644 index 000000000..553380635 Binary files /dev/null and b/docs/images/secret-syncs/oci-vault/configure-destination.png differ diff --git a/docs/images/secret-syncs/oci-vault/configure-details.png b/docs/images/secret-syncs/oci-vault/configure-details.png new file mode 100644 index 000000000..27cf890e8 Binary files /dev/null and b/docs/images/secret-syncs/oci-vault/configure-details.png differ diff --git a/docs/images/secret-syncs/oci-vault/configure-source.png b/docs/images/secret-syncs/oci-vault/configure-source.png new file mode 100644 index 000000000..0953466fc Binary files /dev/null and b/docs/images/secret-syncs/oci-vault/configure-source.png differ diff --git a/docs/images/secret-syncs/oci-vault/configure-sync-options.png b/docs/images/secret-syncs/oci-vault/configure-sync-options.png new file mode 100644 index 000000000..6f40e0dbb Binary files /dev/null and b/docs/images/secret-syncs/oci-vault/configure-sync-options.png differ diff --git a/docs/images/secret-syncs/oci-vault/copy-compartment-ocid.png b/docs/images/secret-syncs/oci-vault/copy-compartment-ocid.png new file mode 100644 index 000000000..fb4355807 Binary files /dev/null and b/docs/images/secret-syncs/oci-vault/copy-compartment-ocid.png differ diff --git a/docs/images/secret-syncs/oci-vault/review-configuration.png b/docs/images/secret-syncs/oci-vault/review-configuration.png new file mode 100644 index 000000000..2abe7820f Binary files /dev/null and b/docs/images/secret-syncs/oci-vault/review-configuration.png differ diff --git a/docs/images/secret-syncs/oci-vault/search-compartment.png b/docs/images/secret-syncs/oci-vault/search-compartment.png new file mode 100644 index 000000000..005f06ecd Binary files /dev/null and b/docs/images/secret-syncs/oci-vault/search-compartment.png differ diff --git a/docs/images/secret-syncs/oci-vault/select-compartment.png b/docs/images/secret-syncs/oci-vault/select-compartment.png new file mode 100644 index 000000000..3eae44c32 Binary files /dev/null and b/docs/images/secret-syncs/oci-vault/select-compartment.png differ diff --git a/docs/images/secret-syncs/oci-vault/select-option.png b/docs/images/secret-syncs/oci-vault/select-option.png new file mode 100644 index 000000000..49a61ccae Binary files /dev/null and b/docs/images/secret-syncs/oci-vault/select-option.png differ diff --git a/docs/images/secret-syncs/oci-vault/sync-created.png b/docs/images/secret-syncs/oci-vault/sync-created.png new file mode 100644 index 000000000..c68fedc68 Binary files /dev/null and b/docs/images/secret-syncs/oci-vault/sync-created.png differ diff --git a/docs/integrations/app-connections/oci.mdx b/docs/integrations/app-connections/oci.mdx new file mode 100644 index 000000000..ff51ce1d9 --- /dev/null +++ b/docs/integrations/app-connections/oci.mdx @@ -0,0 +1,189 @@ +--- +title: "OCI Connection" +description: "Learn how to configure an Oracle Cloud Infrastructure Connection for Infisical." +--- + +Infisical supports the use of [API Signing Key Authentication](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm) to connect with OCI. + +## Create OCI User + + + + ![Search Domains](/images/app-connections/oci/search-domains.png) + + + Select the domain in which you want to create the Infisical user account. + + ![Select Domain](/images/app-connections/oci/select-domain.png) + + + ![Select Users](/images/app-connections/oci/select-users.png) + + + ![Click Create User](/images/app-connections/oci/click-create-user.png) + + + The name, email, and username can be anything. + + ![Create User](/images/app-connections/oci/create-user.png) + + + After you've created a user, you'll be redirected to the user's page. Navigate to 'API keys'. + + ![Select API Keys](/images/app-connections/oci/select-api-keys.png) + + + Click on 'Add API key' and then download or import the private key. After you've obtained the private key, click 'Add'. + + ![Add API Key](/images/app-connections/oci/add-api-key.png) + + + After creating the API key, you'll be shown a modal with relevant information. Save the highlighted values (and the private key) for later steps. + + ![User Info](/images/app-connections/oci/user-info.png) + + + +## Create OCI Group + + + + ![Search Domains](/images/app-connections/oci/search-domains.png) + + + Select the domain in which you want to create the Infisical user account. + + ![Select Domain](/images/app-connections/oci/select-domain.png) + + + ![Select Groups](/images/app-connections/oci/select-groups.png) + + + The name and description can be anything. **Ensure that you assign the user created in earlier steps to this group**. + + ![Create Group](/images/app-connections/oci/create-group.png) + + + After creating the group, take note of its name. It will be used in later steps. + + + +## Create OCI Policy + + + + ![Search Policies](/images/app-connections/oci/search-policies.png) + + + ![Click Create Policy](/images/app-connections/oci/click-create-policy.png) + + + The name and description can be anything. Click 'Show manual editor' and paste in the policy rules relevant to your task: + + + + ``` + Allow group to manage secret-family in compartment + Allow group to use keys in compartment + Allow group to use vaults in compartment + Allow group to inspect compartments in tenancy + ``` + + - **Group Name:** The name of the group you created in earlier steps. + - **Compartment Name:** The name of the compartment which has your secrets vault. + + If you'd like to grant Infisical access to all compartments, replace instances of `compartment ` with `tenancy`. + + + + ![Create Policy](/images/app-connections/oci/create-policy.png) + + + **You must create this policy on the root compartment**, otherwise some functionality may not work. + + + + +## Create OCI Connection in Infisical + + + + + + In your Infisical dashboard, go to **Organization Settings** and select the [**App Connections**](https://app.infisical.com/organization/app-connections) tab. + + ![App Connections Tab](/images/app-connections/general/add-connection.png) + + + Click the **+ Add Connection** button and select the **OCI Connection** option from the available integrations. + + ![Select OCI Connection](/images/app-connections/oci/app-connection-option.png) + + + Complete the OCI Connection form by entering: + - A descriptive name for the connection + - An optional description for future reference + - The User OCID from [earlier steps](https://infisical.com/docs/integrations/app-connections/oci#create-oci-user) + - The Tenancy OCID from [earlier steps](https://infisical.com/docs/integrations/app-connections/oci#create-oci-user) + - The Region from [earlier steps](https://infisical.com/docs/integrations/app-connections/oci#create-oci-user) + - The Fingerprint from [earlier steps](https://infisical.com/docs/integrations/app-connections/oci#create-oci-user) + - The Private Key PEM from [earlier steps](https://infisical.com/docs/integrations/app-connections/oci#create-oci-user) + + ![OCI Connection Modal](/images/app-connections/oci/app-connection-modal.png) + + + After clicking Create, your **OCI Connection** is established and ready to use with your Infisical projects. + + ![OCI Connection Created](/images/app-connections/oci/app-connection-created.png) + + + + + To create an OCI Connection, make an API request to the [Create OCI Connection](/api-reference/endpoints/app-connections/oci/create) API endpoint. + + ### Sample request + + ```bash Request + curl --request POST \ + --url https://app.infisical.com/api/v1/app-connections/oci \ + --header 'Content-Type: application/json' \ + --data '{ + "name": "my-oci-connection", + "method": "access-key", + "credentials": { + "userOcid": "ocid1.user.oc1..aaaaaaaagrp35tbkvvad4y2j7sug7xonua7dl2gfp4at2u5i5xj4ghnitg3a", + "tenancyOcid": "ocid1.tenancy.oc1..aaaaaaaaotfma465m4zumfe2ua64mj2m5dwmlw2llh4g4dnfttnakiifonta", + "region": "us-ashburn-1", + "fingerprint": "9c:f6:18:23:92:73:f8:e1:85:2c:6a:e3:2c:7d:ec:8f", + "privateKey": "[PRIVATE KEY PEM]" + } + }' + ``` + + ### Sample response + + ```bash Response + { + "appConnection": { + "id": "e5d18aca-86f7-4026-a95e-efb8aeb0d8e6", + "name": "my-oci-connection", + "description": null, + "version": 1, + "orgId": "6f03caa1-a5de-43ce-b127-95a145d3464c", + "createdAt": "2025-04-23T19:46:34.831Z", + "updatedAt": "2025-04-23T19:46:34.831Z", + "isPlatformManagedCredentials": false, + "credentialsHash": "7c2d371dec195f82a6a0d5b41c970a229cfcaf88e894a5b6395e2dbd0280661f", + "app": "oci", + "method": "access-key", + "credentials": { + "userOcid": "ocid1.user.oc1..aaaaaaaagrp35tbkvvad4y2j7sug7xonua7dl2gfp4at2u5i5xj4ghnitg3a", + "tenancyOcid": "ocid1.tenancy.oc1..aaaaaaaaotfma465m4zumfe2ua64mj2m5dwmlw2llh4g4dnfttnakiifonta", + "region": "us-ashburn-1", + "fingerprint": "9c:f6:18:23:92:73:f8:e1:85:2c:6a:e3:2c:7d:ec:8f" + } + } + } + ``` + + diff --git a/docs/integrations/secret-syncs/oci-vault.mdx b/docs/integrations/secret-syncs/oci-vault.mdx new file mode 100644 index 000000000..7f3c5fd19 --- /dev/null +++ b/docs/integrations/secret-syncs/oci-vault.mdx @@ -0,0 +1,177 @@ +--- +title: "OCI Vault Sync" +description: "Learn how to configure an Oracle Cloud Infrastructure Vault Sync for Infisical." +--- + +**Prerequisites:** +- Create an [OCI Connection](/integrations/app-connections/oci) with the required **Secret Sync** permissions +- [Create](https://docs.oracle.com/en-us/iaas/Content/Identity/compartments/To_create_a_compartment.htm) or use an existing OCI Compartment (which the OCI Connection is authorized to access) +- [Create](https://docs.oracle.com/en-us/iaas/Content/KeyManagement/Tasks/managingvaults_topic-To_create_a_new_vault.htm#createnewvault) or use an existing OCI Vault + + + + + + Navigate to **Project** > **Integrations** and select the **Secret Syncs** tab. Click on the **Add Sync** button. + + ![Secret Syncs Tab](/images/secret-syncs/general/secret-sync-tab.png) + + + ![Select OCI Vault](/images/secret-syncs/oci-vault/select-option.png) + + + Configure the **Source** from where secrets should be retrieved, then click **Next**. + + ![Configure Source](/images/secret-syncs/oci-vault/configure-source.png) + + - **Environment**: The project environment to retrieve secrets from. + - **Secret Path**: The folder path to retrieve secrets from. + + + If you need to sync secrets from multiple folder locations, check out [secret imports](/documentation/platform/secret-reference#secret-imports). + + + + Configure the **Destination** to where secrets should be deployed, then click **Next**. + + ![Configure Destination](/images/secret-syncs/oci-vault/configure-destination.png) + + - **OCI Connection**: The OCI Connection to authenticate with. + - **Compartment**: The compartment where the vault is located. + - **Vault**: The vault to sync secrets to. + - **Encryption Key**: The encryption key to use when creating secrets in the vault. + + + Configure the **Sync Options** to specify how secrets should be synced, then click **Next**. + + ![Configure Sync Options](/images/secret-syncs/oci-vault/configure-sync-options.png) + + - **Initial Sync Behavior**: Determines how Infisical should resolve the initial sync. + - **Overwrite Destination Secrets**: Removes any secrets at the destination endpoint not present in Infisical. + - **Import Secrets (Prioritize Infisical)**: Imports secrets from the destination endpoint before syncing, prioritizing values from Infisical over OCI Vault when keys conflict. + - **Import Secrets (Prioritize OCI Vault)**: Imports secrets from the destination endpoint before syncing, prioritizing values from OCI Vault over Infisical when keys conflict. + + - **Auto-Sync Enabled**: If enabled, secrets will automatically be synced from the source location when changes occur. Disable to enforce manual syncing only. + - **Disable Secret Deletion**: If enabled, Infisical will not remove secrets from the sync destination. Enable this option if you intend to manage some secrets manually outside of Infisical. + + + Configure the **Details** of your OCI Vault Sync, then click **Next**. + + ![Configure Details](/images/secret-syncs/oci-vault/configure-details.png) + + - **Name**: The name of your sync. Must be slug-friendly. + - **Description**: An optional description for your sync. + + + Review your OCI Vault Sync configuration, then click **Create Sync**. + + ![Review Configuration](/images/secret-syncs/oci-vault/review-configuration.png) + + + If enabled, your OCI Vault Sync will begin syncing your secrets to the destination endpoint. + + ![Sync Created](/images/secret-syncs/oci-vault/sync-created.png) + + + + + To create an **OCI Vault Sync**, make an API request to the [Create OCI Vault Sync](/api-reference/endpoints/secret-syncs/oci-vault/create) API endpoint. + + ### Sample request + + ```bash Request + curl --request POST \ + --url https://app.infisical.com/api/v1/secret-syncs/oci-vault \ + --header 'Content-Type: application/json' \ + --data '{ + "name": "my-oci-vault-sync", + "projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a", + "description": "an example sync", + "connectionId": "3c90c3cc-0d44-4b50-8888-8dd25736052a", + "environment": "dev", + "secretPath": "/my-secrets", + "isEnabled": true, + "syncOptions": { + "initialSyncBehavior": "overwrite-destination" + }, + "destinationConfig": { + "compartmentOcid": "...", + "vaultOcid": "...", + "keyOcid": "..." + } + }' + ``` + + ### Sample response + + ```bash Response + { + "secretSync": { + "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", + "name": "my-oci-vault-sync", + "description": "an example sync", + "isEnabled": true, + "version": 1, + "folderId": "3c90c3cc-0d44-4b50-8888-8dd25736052a", + "connectionId": "3c90c3cc-0d44-4b50-8888-8dd25736052a", + "createdAt": "2023-11-07T05:31:56Z", + "updatedAt": "2023-11-07T05:31:56Z", + "syncStatus": "succeeded", + "lastSyncJobId": "123", + "lastSyncMessage": null, + "lastSyncedAt": "2023-11-07T05:31:56Z", + "importStatus": null, + "lastImportJobId": null, + "lastImportMessage": null, + "lastImportedAt": null, + "removeStatus": null, + "lastRemoveJobId": null, + "lastRemoveMessage": null, + "lastRemovedAt": null, + "syncOptions": { + "initialSyncBehavior": "overwrite-destination" + }, + "projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a", + "connection": { + "app": "oci", + "name": "my-oci-connection", + "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a" + }, + "environment": { + "slug": "dev", + "name": "Development", + "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a" + }, + "folder": { + "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a", + "path": "/my-secrets" + }, + "destination": "oci-vault", + "destinationConfig": { + "compartmentOcid": "...", + "vaultOcid": "...", + "keyOcid": "..." + } + } + } + ``` + + + +## FAQ + + + + When Infisical attempts to sync secrets, the sync will fail and attempt to re-sync if **any secret** has one of the following lifecycle states: + - SchedulingDeletion + - CancellingDeletion + - Deleting + - Creating + - Updating + + We do this to prevent any desync issues. + + + In the case that a variable is created or updated while it's scheduled for deletion in OCI Vault, we cancel the deletion and update the variable. This action may take up to a minute since Infisical must wait for OCI to completely cancel the deletion and then update the variable. + + diff --git a/docs/mint.json b/docs/mint.json index 0255d946f..46075033a 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -469,6 +469,7 @@ "integrations/app-connections/humanitec", "integrations/app-connections/ldap", "integrations/app-connections/mssql", + "integrations/app-connections/oci", "integrations/app-connections/postgres", "integrations/app-connections/teamcity", "integrations/app-connections/terraform-cloud", @@ -495,6 +496,7 @@ "integrations/secret-syncs/github", "integrations/secret-syncs/hashicorp-vault", "integrations/secret-syncs/humanitec", + "integrations/secret-syncs/oci-vault", "integrations/secret-syncs/teamcity", "integrations/secret-syncs/terraform-cloud", "integrations/secret-syncs/vercel", @@ -1171,6 +1173,18 @@ "api-reference/endpoints/app-connections/mssql/delete" ] }, + { + "group": "OCI", + "pages": [ + "api-reference/endpoints/app-connections/oci/list", + "api-reference/endpoints/app-connections/oci/available", + "api-reference/endpoints/app-connections/oci/get-by-id", + "api-reference/endpoints/app-connections/oci/get-by-name", + "api-reference/endpoints/app-connections/oci/create", + "api-reference/endpoints/app-connections/oci/update", + "api-reference/endpoints/app-connections/oci/delete" + ] + }, { "group": "PostgreSQL", "pages": [ @@ -1374,6 +1388,20 @@ "api-reference/endpoints/secret-syncs/humanitec/remove-secrets" ] }, + { + "group": "OCI", + "pages": [ + "api-reference/endpoints/secret-syncs/oci-vault/list", + "api-reference/endpoints/secret-syncs/oci-vault/get-by-id", + "api-reference/endpoints/secret-syncs/oci-vault/get-by-name", + "api-reference/endpoints/secret-syncs/oci-vault/create", + "api-reference/endpoints/secret-syncs/oci-vault/update", + "api-reference/endpoints/secret-syncs/oci-vault/delete", + "api-reference/endpoints/secret-syncs/oci-vault/sync-secrets", + "api-reference/endpoints/secret-syncs/oci-vault/import-secrets", + "api-reference/endpoints/secret-syncs/oci-vault/remove-secrets" + ] + }, { "group": "TeamCity", "pages": [ diff --git a/frontend/public/images/integrations/Oracle.png b/frontend/public/images/integrations/Oracle.png new file mode 100644 index 000000000..14845d2f2 Binary files /dev/null and b/frontend/public/images/integrations/Oracle.png differ diff --git a/frontend/src/components/secret-syncs/SecretSyncStatusBadge.tsx b/frontend/src/components/secret-syncs/SecretSyncStatusBadge.tsx index dbf543f61..53b53d5c0 100644 --- a/frontend/src/components/secret-syncs/SecretSyncStatusBadge.tsx +++ b/frontend/src/components/secret-syncs/SecretSyncStatusBadge.tsx @@ -40,7 +40,14 @@ export const SecretSyncStatusBadge = ({ status }: Props) => { return ( - + {text} ); diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/OCIVaultSyncFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/OCIVaultSyncFields.tsx new file mode 100644 index 000000000..26fa601f6 --- /dev/null +++ b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/OCIVaultSyncFields.tsx @@ -0,0 +1,175 @@ +import { Controller, useFormContext, useWatch } from "react-hook-form"; +import { SingleValue } from "react-select"; +import { faCircleInfo } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import { SecretSyncConnectionField } from "@app/components/secret-syncs/forms/SecretSyncConnectionField"; +import { FilterableSelect, FormControl, Tooltip } from "@app/components/v2"; +import { + useOCIConnectionListCompartments, + useOCIConnectionListVaultKeys, + useOCIConnectionListVaults +} from "@app/hooks/api/appConnections/oci"; +import { SecretSync } from "@app/hooks/api/secretSyncs"; + +import { TSecretSyncForm } from "../schemas"; + +export const OCIVaultSyncFields = () => { + const { control, setValue } = useFormContext< + TSecretSyncForm & { destination: SecretSync.OCIVault } + >(); + + const connectionId = useWatch({ name: "connection.id", control }); + + // Compartments + const { data: compartments, isLoading: isCompartmentsLoading } = useOCIConnectionListCompartments( + connectionId, + { + enabled: Boolean(connectionId) + } + ); + + // Vaults + const selectedCompartment = useWatch({ name: "destinationConfig.compartmentOcid", control }); + const { data: vaults, isLoading: isVaultsLoading } = useOCIConnectionListVaults( + { connectionId, compartmentOcid: selectedCompartment }, + { + enabled: Boolean(connectionId && selectedCompartment) + } + ); + + // Keys + const selectedVault = useWatch({ name: "destinationConfig.vaultOcid", control }); + const { data: keys, isLoading: isKeysLoading } = useOCIConnectionListVaultKeys( + { connectionId, compartmentOcid: selectedCompartment, vaultOcid: selectedVault }, + { + enabled: Boolean(connectionId && selectedCompartment && selectedVault) + } + ); + + return ( + <> + { + setValue("destinationConfig.compartmentOcid", ""); + setValue("destinationConfig.vaultOcid", ""); + setValue("destinationConfig.keyOcid", ""); + }} + /> + + ( + +
+ Don't see the compartment you're looking for?{" "} + +
+ + } + > + c.id === value) ?? null} + onChange={(option) => { + onChange((option as SingleValue<{ id: string }>)?.id ?? null); + setValue("destinationConfig.vaultOcid", ""); + setValue("destinationConfig.keyOcid", ""); + }} + options={compartments} + placeholder="Select a compartment..." + getOptionLabel={(option) => option.name} + getOptionValue={(option) => option.id} + /> +
+ )} + /> + + ( + +
+ Don't see the vault you're looking for?{" "} + +
+ + } + > + v.id === value) ?? null} + onChange={(option) => { + onChange((option as SingleValue<{ id: string }>)?.id ?? null); + setValue("destinationConfig.keyOcid", ""); + }} + options={vaults} + placeholder="Select a vault..." + getOptionLabel={(option) => option.displayName} + getOptionValue={(option) => option.id} + /> +
+ )} + /> + + ( + +
+ Don't see the key you're looking for?{" "} + +
+ + } + > + v.id === value) ?? null} + onChange={(option) => { + onChange((option as SingleValue<{ id: string }>)?.id ?? null); + }} + options={keys} + placeholder="Select a key..." + getOptionLabel={(option) => option.displayName} + getOptionValue={(option) => option.id} + /> +
+ )} + /> + + ); +}; diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/SecretSyncDestinationFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/SecretSyncDestinationFields.tsx index 1d7a1dd55..2cac1ae20 100644 --- a/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/SecretSyncDestinationFields.tsx +++ b/frontend/src/components/secret-syncs/forms/SecretSyncDestinationFields/SecretSyncDestinationFields.tsx @@ -13,6 +13,7 @@ import { GcpSyncFields } from "./GcpSyncFields"; import { GitHubSyncFields } from "./GitHubSyncFields"; import { HCVaultSyncFields } from "./HCVaultSyncFields"; import { HumanitecSyncFields } from "./HumanitecSyncFields"; +import { OCIVaultSyncFields } from "./OCIVaultSyncFields"; import { TeamCitySyncFields } from "./TeamCitySyncFields"; import { TerraformCloudSyncFields } from "./TerraformCloudSyncFields"; import { VercelSyncFields } from "./VercelSyncFields"; @@ -52,6 +53,8 @@ export const SecretSyncDestinationFields = () => { return ; case SecretSync.TeamCity: return ; + case SecretSync.OCIVault: + return ; default: throw new Error(`Unhandled Destination Config Field: ${destination}`); } diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncOptionsFields/SecretSyncOptionsFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncOptionsFields/SecretSyncOptionsFields.tsx index e4aa4ad65..9eec461cd 100644 --- a/frontend/src/components/secret-syncs/forms/SecretSyncOptionsFields/SecretSyncOptionsFields.tsx +++ b/frontend/src/components/secret-syncs/forms/SecretSyncOptionsFields/SecretSyncOptionsFields.tsx @@ -45,6 +45,7 @@ export const SecretSyncOptionsFields = ({ hideInitialSync }: Props) => { case SecretSync.Windmill: case SecretSync.HCVault: case SecretSync.TeamCity: + case SecretSync.OCIVault: AdditionalSyncOptionsFieldsComponent = null; break; default: diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/OCIVaultSyncReviewFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/OCIVaultSyncReviewFields.tsx new file mode 100644 index 000000000..16166c88c --- /dev/null +++ b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/OCIVaultSyncReviewFields.tsx @@ -0,0 +1,26 @@ +import { useFormContext } from "react-hook-form"; + +import { TSecretSyncForm } from "@app/components/secret-syncs/forms/schemas"; +import { GenericFieldLabel } from "@app/components/v2"; +import { SecretSync } from "@app/hooks/api/secretSyncs"; + +export const OCIVaultSyncReviewFields = () => { + const { watch } = useFormContext(); + const compartmentOcid = watch("destinationConfig.compartmentOcid"); + const vaultOcid = watch("destinationConfig.vaultOcid"); + const keyOcid = watch("destinationConfig.keyOcid"); + + return ( + <> + + {compartmentOcid} + + + {vaultOcid} + + + {keyOcid} + + + ); +}; diff --git a/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/SecretSyncReviewFields.tsx b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/SecretSyncReviewFields.tsx index 62402e540..b7f62c139 100644 --- a/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/SecretSyncReviewFields.tsx +++ b/frontend/src/components/secret-syncs/forms/SecretSyncReviewFields/SecretSyncReviewFields.tsx @@ -23,6 +23,7 @@ import { GcpSyncReviewFields } from "./GcpSyncReviewFields"; import { GitHubSyncReviewFields } from "./GitHubSyncReviewFields"; import { HCVaultSyncReviewFields } from "./HCVaultSyncReviewFields"; import { HumanitecSyncReviewFields } from "./HumanitecSyncReviewFields"; +import { OCIVaultSyncReviewFields } from "./OCIVaultSyncReviewFields"; import { TeamCitySyncReviewFields } from "./TeamCitySyncReviewFields"; import { TerraformCloudSyncReviewFields } from "./TerraformCloudSyncReviewFields"; import { VercelSyncReviewFields } from "./VercelSyncReviewFields"; @@ -96,6 +97,9 @@ export const SecretSyncReviewFields = () => { case SecretSync.TeamCity: DestinationFieldsComponent = ; break; + case SecretSync.OCIVault: + DestinationFieldsComponent = ; + break; default: throw new Error(`Unhandled Destination Review Fields: ${destination}`); } diff --git a/frontend/src/components/secret-syncs/forms/schemas/oci-vault-sync-destination-schema.ts b/frontend/src/components/secret-syncs/forms/schemas/oci-vault-sync-destination-schema.ts new file mode 100644 index 000000000..84eb6a362 --- /dev/null +++ b/frontend/src/components/secret-syncs/forms/schemas/oci-vault-sync-destination-schema.ts @@ -0,0 +1,33 @@ +import { z } from "zod"; + +import { BaseSecretSyncSchema } from "@app/components/secret-syncs/forms/schemas/base-secret-sync-schema"; +import { SecretSync } from "@app/hooks/api/secretSyncs"; + +export const OCIVaultSyncDestinationSchema = BaseSecretSyncSchema().merge( + z.object({ + destination: z.literal(SecretSync.OCIVault), + destinationConfig: z.object({ + compartmentOcid: z + .string() + .trim() + .min(1, "Compartment OCID required") + .regex( + /^ocid1\.(tenancy|compartment)\.oc1\..+$/, + "Invalid Compartment OCID format. Must start with ocid1.tenancy.oc1. or ocid1.compartment.oc1." + ), + vaultOcid: z + .string() + .trim() + .min(1, "Vault OCID required") + .regex( + /^ocid1\.vault\.oc1\..+$/, + "Invalid Vault OCID format. Must start with ocid1.vault.oc1." + ), + keyOcid: z + .string() + .trim() + .min(1, "Key OCID required") + .regex(/^ocid1\.key\.oc1\..+$/, "Invalid Key OCID format. Must start with ocid1.key.oc1.") + }) + }) +); diff --git a/frontend/src/components/secret-syncs/forms/schemas/secret-sync-schema.ts b/frontend/src/components/secret-syncs/forms/schemas/secret-sync-schema.ts index bc6184bc7..232b8cedf 100644 --- a/frontend/src/components/secret-syncs/forms/schemas/secret-sync-schema.ts +++ b/frontend/src/components/secret-syncs/forms/schemas/secret-sync-schema.ts @@ -10,6 +10,7 @@ import { GcpSyncDestinationSchema } from "./gcp-sync-destination-schema"; import { GitHubSyncDestinationSchema } from "./github-sync-destination-schema"; import { HCVaultSyncDestinationSchema } from "./hc-vault-sync-destination-schema"; import { HumanitecSyncDestinationSchema } from "./humanitec-sync-destination-schema"; +import { OCIVaultSyncDestinationSchema } from "./oci-vault-sync-destination-schema"; import { TeamCitySyncDestinationSchema } from "./teamcity-sync-destination-schema"; import { TerraformCloudSyncDestinationSchema } from "./terraform-cloud-destination-schema"; import { VercelSyncDestinationSchema } from "./vercel-sync-destination-schema"; @@ -29,7 +30,8 @@ const SecretSyncUnionSchema = z.discriminatedUnion("destination", [ VercelSyncDestinationSchema, WindmillSyncDestinationSchema, HCVaultSyncDestinationSchema, - TeamCitySyncDestinationSchema + TeamCitySyncDestinationSchema, + OCIVaultSyncDestinationSchema ]); export const SecretSyncFormSchema = SecretSyncUnionSchema; diff --git a/frontend/src/components/v2/GenericFieldLabel/GenericFieldLabel.tsx b/frontend/src/components/v2/GenericFieldLabel/GenericFieldLabel.tsx index 5200e1898..95eaf5745 100644 --- a/frontend/src/components/v2/GenericFieldLabel/GenericFieldLabel.tsx +++ b/frontend/src/components/v2/GenericFieldLabel/GenericFieldLabel.tsx @@ -6,14 +6,21 @@ type Props = { children?: ReactNode; className?: string; labelClassName?: string; + truncate?: boolean; }; -export const GenericFieldLabel = ({ label, children, className, labelClassName }: Props) => { +export const GenericFieldLabel = ({ + label, + children, + className, + labelClassName, + truncate +}: Props) => { return ( -
+

{label}

{children ? ( -

{children}

+

{children}

) : (

None

)} diff --git a/frontend/src/helpers/appConnections.ts b/frontend/src/helpers/appConnections.ts index 68715f9a0..8caa13a5b 100644 --- a/frontend/src/helpers/appConnections.ts +++ b/frontend/src/helpers/appConnections.ts @@ -30,6 +30,7 @@ import { VercelConnectionMethod, WindmillConnectionMethod } from "@app/hooks/api/appConnections/types"; +import { OCIConnectionMethod } from "@app/hooks/api/appConnections/types/oci-connection"; export const APP_CONNECTION_MAP: Record< AppConnection, @@ -61,7 +62,8 @@ export const APP_CONNECTION_MAP: Record< [AppConnection.Auth0]: { name: "Auth0", image: "Auth0.png", size: 40 }, [AppConnection.HCVault]: { name: "Hashicorp Vault", image: "Vault.png", size: 65 }, [AppConnection.LDAP]: { name: "LDAP", image: "LDAP.png", size: 65 }, - [AppConnection.TeamCity]: { name: "TeamCity", image: "TeamCity.png" } + [AppConnection.TeamCity]: { name: "TeamCity", image: "TeamCity.png" }, + [AppConnection.OCI]: { name: "OCI", image: "Oracle.png" } }; export const getAppConnectionMethodDetails = (method: TAppConnection["method"]) => { @@ -74,6 +76,7 @@ export const getAppConnectionMethodDetails = (method: TAppConnection["method"]) case GitHubConnectionMethod.OAuth: return { name: "OAuth", icon: faPassport }; case AwsConnectionMethod.AccessKey: + case OCIConnectionMethod.AccessKey: return { name: "Access Key", icon: faKey }; case AwsConnectionMethod.AssumeRole: return { name: "Assume Role", icon: faUser }; diff --git a/frontend/src/helpers/secretSyncs.ts b/frontend/src/helpers/secretSyncs.ts index 58d9f3e48..80df92ac3 100644 --- a/frontend/src/helpers/secretSyncs.ts +++ b/frontend/src/helpers/secretSyncs.ts @@ -47,6 +47,10 @@ export const SECRET_SYNC_MAP: Record = { [SecretSync.Vercel]: AppConnection.Vercel, [SecretSync.Windmill]: AppConnection.Windmill, [SecretSync.HCVault]: AppConnection.HCVault, - [SecretSync.TeamCity]: AppConnection.TeamCity + [SecretSync.TeamCity]: AppConnection.TeamCity, + [SecretSync.OCIVault]: AppConnection.OCI }; export const SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP: Record< diff --git a/frontend/src/hooks/api/appConnections/enums.ts b/frontend/src/hooks/api/appConnections/enums.ts index 5e1f84cb4..06a5056af 100644 --- a/frontend/src/hooks/api/appConnections/enums.ts +++ b/frontend/src/hooks/api/appConnections/enums.ts @@ -16,5 +16,6 @@ export enum AppConnection { Auth0 = "auth0", HCVault = "hashicorp-vault", LDAP = "ldap", - TeamCity = "teamcity" + TeamCity = "teamcity", + OCI = "oci" } diff --git a/frontend/src/hooks/api/appConnections/oci/index.ts b/frontend/src/hooks/api/appConnections/oci/index.ts new file mode 100644 index 000000000..2c1906d36 --- /dev/null +++ b/frontend/src/hooks/api/appConnections/oci/index.ts @@ -0,0 +1,2 @@ +export * from "./queries"; +export * from "./types"; diff --git a/frontend/src/hooks/api/appConnections/oci/queries.tsx b/frontend/src/hooks/api/appConnections/oci/queries.tsx new file mode 100644 index 000000000..f0e2659b7 --- /dev/null +++ b/frontend/src/hooks/api/appConnections/oci/queries.tsx @@ -0,0 +1,108 @@ +import { useQuery, UseQueryOptions } from "@tanstack/react-query"; + +import { apiRequest } from "@app/config/request"; + +import { appConnectionKeys } from "../queries"; +import { + TListOCIVaultKeys, + TListOCIVaults, + TOCICompartment, + TOCIVault, + TOCIVaultKey +} from "./types"; + +const ociConnectionKeys = { + all: [...appConnectionKeys.all, "oci"] as const, + listCompartments: (connectionId: string) => + [...ociConnectionKeys.all, "compartments", connectionId] as const, + listVaults: (connectionId: string, compartmentOcid: string) => + [...ociConnectionKeys.all, "vaults", connectionId, compartmentOcid] as const, + listVaultKeys: (connectionId: string, compartmentOcid: string, vaultOcid: string) => + [...ociConnectionKeys.all, "keys", connectionId, compartmentOcid, vaultOcid] as const +}; + +export const useOCIConnectionListCompartments = ( + connectionId: string, + options?: Omit< + UseQueryOptions< + TOCICompartment[], + unknown, + TOCICompartment[], + ReturnType + >, + "queryKey" | "queryFn" + > +) => { + return useQuery({ + queryKey: ociConnectionKeys.listCompartments(connectionId), + queryFn: async () => { + const { data } = await apiRequest.get( + `/api/v1/app-connections/oci/${connectionId}/compartments` + ); + + return data; + }, + ...options + }); +}; + +export const useOCIConnectionListVaults = ( + { connectionId, compartmentOcid }: TListOCIVaults, + options?: Omit< + UseQueryOptions< + TOCIVault[], + unknown, + TOCIVault[], + ReturnType + >, + "queryKey" | "queryFn" + > +) => { + return useQuery({ + queryKey: ociConnectionKeys.listVaults(connectionId, compartmentOcid), + queryFn: async () => { + const { data } = await apiRequest.get( + `/api/v1/app-connections/oci/${connectionId}/vaults`, + { + params: { + compartmentOcid + } + } + ); + + return data; + }, + ...options + }); +}; + +export const useOCIConnectionListVaultKeys = ( + { connectionId, compartmentOcid, vaultOcid }: TListOCIVaultKeys, + options?: Omit< + UseQueryOptions< + TOCIVaultKey[], + unknown, + TOCIVaultKey[], + ReturnType + >, + "queryKey" | "queryFn" + > +) => { + return useQuery({ + queryKey: ociConnectionKeys.listVaultKeys(connectionId, compartmentOcid, vaultOcid), + queryFn: async () => { + const { data } = await apiRequest.get( + `/api/v1/app-connections/oci/${connectionId}/vault-keys`, + { + params: { + compartmentOcid, + vaultOcid + } + } + ); + + return data; + }, + ...options + }); +}; diff --git a/frontend/src/hooks/api/appConnections/oci/types.ts b/frontend/src/hooks/api/appConnections/oci/types.ts new file mode 100644 index 000000000..da12116bd --- /dev/null +++ b/frontend/src/hooks/api/appConnections/oci/types.ts @@ -0,0 +1,27 @@ +// Response types +export type TOCICompartment = { + id: string; + name: string; +}; + +export type TOCIVault = { + id: string; + displayName: string; +}; + +export type TOCIVaultKey = { + id: string; + displayName: string; +}; + +// Param types +export type TListOCIVaults = { + connectionId: string; + compartmentOcid: string; +}; + +export type TListOCIVaultKeys = { + connectionId: string; + compartmentOcid: string; + vaultOcid: string; +}; diff --git a/frontend/src/hooks/api/appConnections/types/app-options.ts b/frontend/src/hooks/api/appConnections/types/app-options.ts index 910716c02..79cbb81b9 100644 --- a/frontend/src/hooks/api/appConnections/types/app-options.ts +++ b/frontend/src/hooks/api/appConnections/types/app-options.ts @@ -84,6 +84,10 @@ export type TTeamCityConnectionOption = TAppConnectionOptionBase & { app: AppConnection.TeamCity; }; +export type TOCIConnectionOption = TAppConnectionOptionBase & { + app: AppConnection.OCI; +}; + export type TAppConnectionOption = | TAwsConnectionOption | TGitHubConnectionOption @@ -101,7 +105,8 @@ export type TAppConnectionOption = | TWindmillConnectionOption | TAuth0ConnectionOption | THCVaultConnectionOption - | TTeamCityConnectionOption; + | TTeamCityConnectionOption + | TOCIConnectionOption; export type TAppConnectionOptionMap = { [AppConnection.AWS]: TAwsConnectionOption; @@ -122,4 +127,5 @@ export type TAppConnectionOptionMap = { [AppConnection.HCVault]: THCVaultConnectionOption; [AppConnection.LDAP]: TLdapConnectionOption; [AppConnection.TeamCity]: TTeamCityConnectionOption; + [AppConnection.OCI]: TOCIConnectionOption; }; diff --git a/frontend/src/hooks/api/appConnections/types/index.ts b/frontend/src/hooks/api/appConnections/types/index.ts index 00c0c3f3a..2b29c2cd4 100644 --- a/frontend/src/hooks/api/appConnections/types/index.ts +++ b/frontend/src/hooks/api/appConnections/types/index.ts @@ -13,6 +13,7 @@ import { THCVaultConnection } from "./hc-vault-connection"; import { THumanitecConnection } from "./humanitec-connection"; import { TLdapConnection } from "./ldap-connection"; import { TMsSqlConnection } from "./mssql-connection"; +import { TOCIConnection } from "./oci-connection"; import { TPostgresConnection } from "./postgres-connection"; import { TTeamCityConnection } from "./teamcity-connection"; import { TTerraformCloudConnection } from "./terraform-cloud-connection"; @@ -32,6 +33,7 @@ export * from "./hc-vault-connection"; export * from "./humanitec-connection"; export * from "./ldap-connection"; export * from "./mssql-connection"; +export * from "./oci-connection"; export * from "./postgres-connection"; export * from "./teamcity-connection"; export * from "./terraform-cloud-connection"; @@ -56,7 +58,8 @@ export type TAppConnection = | TAuth0Connection | THCVaultConnection | TLdapConnection - | TTeamCityConnection; + | TTeamCityConnection + | TOCIConnection; export type TAvailableAppConnection = Pick; @@ -102,4 +105,5 @@ export type TAppConnectionMap = { [AppConnection.HCVault]: THCVaultConnection; [AppConnection.LDAP]: TLdapConnection; [AppConnection.TeamCity]: TTeamCityConnection; + [AppConnection.OCI]: TOCIConnection; }; diff --git a/frontend/src/hooks/api/appConnections/types/oci-connection.ts b/frontend/src/hooks/api/appConnections/types/oci-connection.ts new file mode 100644 index 000000000..f6b5c2cad --- /dev/null +++ b/frontend/src/hooks/api/appConnections/types/oci-connection.ts @@ -0,0 +1,17 @@ +import { AppConnection } from "@app/hooks/api/appConnections/enums"; +import { TRootAppConnection } from "@app/hooks/api/appConnections/types/root-connection"; + +export enum OCIConnectionMethod { + AccessKey = "access-key" +} + +export type TOCIConnection = TRootAppConnection & { app: AppConnection.OCI } & { + method: OCIConnectionMethod.AccessKey; + credentials: { + userOcid: string; + tenancyOcid: string; + region: string; + fingerprint: string; + privateKey: string; + }; +}; diff --git a/frontend/src/hooks/api/secretSyncs/enums.ts b/frontend/src/hooks/api/secretSyncs/enums.ts index d078765bc..65a31e427 100644 --- a/frontend/src/hooks/api/secretSyncs/enums.ts +++ b/frontend/src/hooks/api/secretSyncs/enums.ts @@ -12,7 +12,8 @@ export enum SecretSync { Vercel = "vercel", Windmill = "windmill", HCVault = "hashicorp-vault", - TeamCity = "teamcity" + TeamCity = "teamcity", + OCIVault = "oci-vault" } export enum SecretSyncStatus { diff --git a/frontend/src/hooks/api/secretSyncs/types/index.ts b/frontend/src/hooks/api/secretSyncs/types/index.ts index 2dba65649..e3de6029a 100644 --- a/frontend/src/hooks/api/secretSyncs/types/index.ts +++ b/frontend/src/hooks/api/secretSyncs/types/index.ts @@ -11,6 +11,7 @@ import { TGcpSync } from "./gcp-sync"; import { TGitHubSync } from "./github-sync"; import { THCVaultSync } from "./hc-vault-sync"; import { THumanitecSync } from "./humanitec-sync"; +import { TOCIVaultSync } from "./oci-vault-sync"; import { TTeamCitySync } from "./teamcity-sync"; import { TTerraformCloudSync } from "./terraform-cloud-sync"; import { TVercelSync } from "./vercel-sync"; @@ -36,7 +37,8 @@ export type TSecretSync = | TVercelSync | TWindmillSync | THCVaultSync - | TTeamCitySync; + | TTeamCitySync + | TOCIVaultSync; export type TListSecretSyncs = { secretSyncs: TSecretSync[] }; diff --git a/frontend/src/hooks/api/secretSyncs/types/oci-vault-sync.ts b/frontend/src/hooks/api/secretSyncs/types/oci-vault-sync.ts new file mode 100644 index 000000000..9dd0062f4 --- /dev/null +++ b/frontend/src/hooks/api/secretSyncs/types/oci-vault-sync.ts @@ -0,0 +1,17 @@ +import { AppConnection } from "@app/hooks/api/appConnections/enums"; +import { SecretSync } from "@app/hooks/api/secretSyncs"; +import { TRootSecretSync } from "@app/hooks/api/secretSyncs/types/root-sync"; + +export type TOCIVaultSync = TRootSecretSync & { + destination: SecretSync.OCIVault; + destinationConfig: { + compartmentOcid: string; + vaultOcid: string; + keyOcid: string; + }; + connection: { + app: AppConnection.OCI; + name: string; + id: string; + }; +}; diff --git a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/AppConnectionForm.tsx b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/AppConnectionForm.tsx index 5c004ce96..238dc4e04 100644 --- a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/AppConnectionForm.tsx +++ b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/AppConnectionForm.tsx @@ -22,6 +22,7 @@ import { HCVaultConnectionForm } from "./HCVaultConnectionForm"; import { HumanitecConnectionForm } from "./HumanitecConnectionForm"; import { LdapConnectionForm } from "./LdapConnectionForm"; import { MsSqlConnectionForm } from "./MsSqlConnectionForm"; +import { OCIConnectionForm } from "./OCIConnectionForm"; import { PostgresConnectionForm } from "./PostgresConnectionForm"; import { TeamCityConnectionForm } from "./TeamCityConnectionForm"; import { TerraformCloudConnectionForm } from "./TerraformCloudConnectionForm"; @@ -101,6 +102,8 @@ const CreateForm = ({ app, onComplete }: CreateFormProps) => { return ; case AppConnection.TeamCity: return ; + case AppConnection.OCI: + return ; default: throw new Error(`Unhandled App ${app}`); } @@ -173,6 +176,8 @@ const UpdateForm = ({ appConnection, onComplete }: UpdateFormProps) => { return ; case AppConnection.TeamCity: return ; + case AppConnection.OCI: + return ; default: throw new Error(`Unhandled App ${(appConnection as TAppConnection).app}`); diff --git a/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/OCIConnectionForm.tsx b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/OCIConnectionForm.tsx new file mode 100644 index 000000000..6ea355dd2 --- /dev/null +++ b/frontend/src/pages/organization/AppConnections/AppConnectionsPage/components/AppConnectionForm/OCIConnectionForm.tsx @@ -0,0 +1,215 @@ +import { Controller, FormProvider, useForm } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { z } from "zod"; + +import { + Button, + FormControl, + Input, + ModalClose, + SecretInput, + Select, + SelectItem +} from "@app/components/v2"; +import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections"; +import { OCIConnectionMethod, TOCIConnection } from "@app/hooks/api/appConnections"; +import { AppConnection } from "@app/hooks/api/appConnections/enums"; + +import { + genericAppConnectionFieldsSchema, + GenericAppConnectionsFields +} from "./GenericAppConnectionFields"; + +type Props = { + appConnection?: TOCIConnection; + onSubmit: (formData: FormData) => void; +}; + +const rootSchema = genericAppConnectionFieldsSchema.extend({ + app: z.literal(AppConnection.OCI) +}); + +const formSchema = z.discriminatedUnion("method", [ + rootSchema.extend({ + method: z.literal(OCIConnectionMethod.AccessKey), + credentials: z.object({ + userOcid: z + .string() + .trim() + .min(1, "User OCID required") + .regex(/^ocid1\.user\.oc1\.\..+$/, "Invalid User OCID format"), + tenancyOcid: z + .string() + .trim() + .min(1, "Tenancy OCID required") + .regex(/^ocid1\.tenancy\.oc1\.\..+$/, "Invalid Tenancy OCID format"), + region: z.string().trim().min(1, "Region required"), + fingerprint: z.string().trim().min(1, "Fingerprint required"), + privateKey: z.string().trim().min(1, "Private Key required") + }) + }) +]); + +type FormData = z.infer; + +export const OCIConnectionForm = ({ appConnection, onSubmit }: Props) => { + const isUpdate = Boolean(appConnection); + + const form = useForm({ + resolver: zodResolver(formSchema), + defaultValues: appConnection ?? { + app: AppConnection.OCI, + method: OCIConnectionMethod.AccessKey + } + }); + + const { + handleSubmit, + control, + formState: { isSubmitting, isDirty } + } = form; + + return ( + +
+ {!isUpdate && } + ( + + + + )} + /> + ( + + + + )} + /> + ( + + + + )} + /> + ( + + + + )} + /> + ( + + + + )} + /> + ( + + onChange(e.target.value)} + /> + + )} + /> +
+ + + + +
+ +
+ ); +}; diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/OCIVaultSyncDestinationCol.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/OCIVaultSyncDestinationCol.tsx new file mode 100644 index 000000000..e6d598269 --- /dev/null +++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/OCIVaultSyncDestinationCol.tsx @@ -0,0 +1,14 @@ +import { TOCIVaultSync } from "@app/hooks/api/secretSyncs/types/oci-vault-sync"; + +import { getSecretSyncDestinationColValues } from "../helpers"; +import { SecretSyncTableCell } from "../SecretSyncTableCell"; + +type Props = { + secretSync: TOCIVaultSync; +}; + +export const OCIVaultSyncDestinationCol = ({ secretSync }: Props) => { + const { primaryText, secondaryText } = getSecretSyncDestinationColValues(secretSync); + + return ; +}; diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/SecretSyncDestinationCol.tsx b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/SecretSyncDestinationCol.tsx index abfbf100c..898980881 100644 --- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/SecretSyncDestinationCol.tsx +++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/SecretSyncDestinationCol/SecretSyncDestinationCol.tsx @@ -10,6 +10,7 @@ import { GcpSyncDestinationCol } from "./GcpSyncDestinationCol"; import { GitHubSyncDestinationCol } from "./GitHubSyncDestinationCol"; import { HCVaultSyncDestinationCol } from "./HCVaultSyncDestinationCol"; import { HumanitecSyncDestinationCol } from "./HumanitecSyncDestinationCol"; +import { OCIVaultSyncDestinationCol } from "./OCIVaultSyncDestinationCol"; import { TeamCitySyncDestinationCol } from "./TeamCitySyncDestinationCol"; import { TerraformCloudSyncDestinationCol } from "./TerraformCloudSyncDestinationCol"; import { VercelSyncDestinationCol } from "./VercelSyncDestinationCol"; @@ -49,6 +50,8 @@ export const SecretSyncDestinationCol = ({ secretSync }: Props) => { return ; case SecretSync.TeamCity: return ; + case SecretSync.OCIVault: + return ; default: throw new Error( `Unhandled Secret Sync Destination Col: ${(secretSync as TSecretSync).destination}` diff --git a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/helpers/index.ts b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/helpers/index.ts index b1fe387e5..4bf0eeed2 100644 --- a/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/helpers/index.ts +++ b/frontend/src/pages/secret-manager/IntegrationsListPage/components/SecretSyncsTab/SecretSyncTable/helpers/index.ts @@ -102,6 +102,10 @@ export const getSecretSyncDestinationColValues = (secretSync: TSecretSync) => { primaryText = destinationConfig.project; secondaryText = destinationConfig.buildConfig; break; + case SecretSync.OCIVault: + primaryText = destinationConfig.compartmentOcid; + secondaryText = destinationConfig.vaultOcid; + break; default: throw new Error(`Unhandled Destination Col Values ${destination}`); } diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/OCIVaultSyncDestinationSection.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/OCIVaultSyncDestinationSection.tsx new file mode 100644 index 000000000..8a987ae26 --- /dev/null +++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/OCIVaultSyncDestinationSection.tsx @@ -0,0 +1,42 @@ +import { GenericFieldLabel } from "@app/components/secret-syncs"; +import { Tooltip } from "@app/components/v2"; +import { TOCIVaultSync } from "@app/hooks/api/secretSyncs/types/oci-vault-sync"; + +type Props = { + secretSync: TOCIVaultSync; +}; + +export const OCIVaultSyncDestinationSection = ({ secretSync }: Props) => { + const { + destinationConfig: { compartmentOcid, keyOcid, vaultOcid } + } = secretSync; + + return ( + <> + +
+ + {compartmentOcid.substring(0, 21)}... + {compartmentOcid.substring(compartmentOcid.length - 6)} + +
+
+ +
+ + {vaultOcid.substring(0, 15)}... + {vaultOcid.substring(vaultOcid.length - 6)} + +
+
+ +
+ + {keyOcid.substring(0, 13)}... + {keyOcid.substring(keyOcid.length - 6)} + +
+
+ + ); +}; diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/SecretSyncDestinatonSection.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/SecretSyncDestinatonSection.tsx index 4ea5798d9..b0c989ee2 100644 --- a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/SecretSyncDestinatonSection.tsx +++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/SecretSyncDestinatonSection.tsx @@ -20,6 +20,7 @@ import { GcpSyncDestinationSection } from "./GcpSyncDestinationSection"; import { GitHubSyncDestinationSection } from "./GitHubSyncDestinationSection"; import { HCVaultSyncDestinationSection } from "./HCVaultSyncDestinationSection"; import { HumanitecSyncDestinationSection } from "./HumanitecSyncDestinationSection"; +import { OCIVaultSyncDestinationSection } from "./OCIVaultSyncDestinationSection"; import { TeamCitySyncDestinationSection } from "./TeamCitySyncDestinationSection"; import { TerraformCloudSyncDestinationSection } from "./TerraformCloudSyncDestinationSection"; import { VercelSyncDestinationSection } from "./VercelSyncDestinationSection"; @@ -81,6 +82,9 @@ export const SecretSyncDestinationSection = ({ secretSync, onEditDestination }: case SecretSync.TeamCity: DestinationComponents = ; break; + case SecretSync.OCIVault: + DestinationComponents = ; + break; default: throw new Error(`Unhandled Destination Section components: ${destination}`); } diff --git a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncOptionsSection/SecretSyncOptionsSection.tsx b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncOptionsSection/SecretSyncOptionsSection.tsx index 5995e7cd1..ca229b55c 100644 --- a/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncOptionsSection/SecretSyncOptionsSection.tsx +++ b/frontend/src/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncOptionsSection/SecretSyncOptionsSection.tsx @@ -54,6 +54,7 @@ export const SecretSyncOptionsSection = ({ secretSync, onEditOptions }: Props) = case SecretSync.Windmill: case SecretSync.HCVault: case SecretSync.TeamCity: + case SecretSync.OCIVault: AdditionalSyncOptionsComponent = null; break; default: