diff --git a/docs/changelog/next_release/294.feature.rst b/docs/changelog/next_release/294.feature.rst new file mode 100644 index 00000000..21df154a --- /dev/null +++ b/docs/changelog/next_release/294.feature.rst @@ -0,0 +1 @@ +Added OAuth2ClientCredentials to Iceberg REST Catalog \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 9d367f50..993ecc97 100644 --- a/poetry.lock +++ b/poetry.lock @@ -600,14 +600,14 @@ zstd = ["zstandard (==0.23.0)"] [[package]] name = "certifi" -version = "2025.10.5" +version = "2025.11.12" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" groups = ["main", "docs", "test"] files = [ - {file = "certifi-2025.10.5-py3-none-any.whl", hash = "sha256:0f212c2744a9bb6de0c56639a6f68afe01ecd92d91f14ae897c4fe7bbeeef0de"}, - {file = "certifi-2025.10.5.tar.gz", hash = "sha256:47c09d31ccf2acf0be3f701ea53595ee7e0b8fa08801c6624be771df09ae7b43"}, + {file = "certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b"}, + {file = "certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316"}, ] [[package]] @@ -1353,52 +1353,104 @@ dev = ["pyTest", "pyTest-cov"] [[package]] name = "frozendict" -version = "2.4.6" +version = "2.4.7" description = "A simple immutable dictionary" optional = true python-versions = ">=3.6" groups = ["main"] markers = "extra == \"worker\"" files = [ - {file = "frozendict-2.4.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c3a05c0a50cab96b4bb0ea25aa752efbfceed5ccb24c007612bc63e51299336f"}, - {file = "frozendict-2.4.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f5b94d5b07c00986f9e37a38dd83c13f5fe3bf3f1ccc8e88edea8fe15d6cd88c"}, - {file = "frozendict-2.4.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4c789fd70879ccb6289a603cdebdc4953e7e5dea047d30c1b180529b28257b5"}, - {file = "frozendict-2.4.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da6a10164c8a50b34b9ab508a9420df38f4edf286b9ca7b7df8a91767baecb34"}, - {file = "frozendict-2.4.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9a8a43036754a941601635ea9c788ebd7a7efbed2becba01b54a887b41b175b9"}, - {file = "frozendict-2.4.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c9905dcf7aa659e6a11b8051114c9fa76dfde3a6e50e6dc129d5aece75b449a2"}, - {file = "frozendict-2.4.6-cp310-cp310-win_amd64.whl", hash = "sha256:323f1b674a2cc18f86ab81698e22aba8145d7a755e0ac2cccf142ee2db58620d"}, - {file = "frozendict-2.4.6-cp310-cp310-win_arm64.whl", hash = "sha256:eabd21d8e5db0c58b60d26b4bb9839cac13132e88277e1376970172a85ee04b3"}, - {file = "frozendict-2.4.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:eddabeb769fab1e122d3a6872982c78179b5bcc909fdc769f3cf1964f55a6d20"}, - {file = "frozendict-2.4.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:377a65be0a700188fc21e669c07de60f4f6d35fae8071c292b7df04776a1c27b"}, - {file = "frozendict-2.4.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce1e9217b85eec6ba9560d520d5089c82dbb15f977906eb345d81459723dd7e3"}, - {file = "frozendict-2.4.6-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:7291abacf51798d5ffe632771a69c14fb423ab98d63c4ccd1aa382619afe2f89"}, - {file = "frozendict-2.4.6-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:e72fb86e48811957d66ffb3e95580af7b1af1e6fbd760ad63d7bd79b2c9a07f8"}, - {file = "frozendict-2.4.6-cp36-cp36m-win_amd64.whl", hash = "sha256:622301b1c29c4f9bba633667d592a3a2b093cb408ba3ce578b8901ace3931ef3"}, - {file = "frozendict-2.4.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a4e3737cb99ed03200cd303bdcd5514c9f34b29ee48f405c1184141bd68611c9"}, - {file = "frozendict-2.4.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49ffaf09241bc1417daa19362a2241a4aa435f758fd4375c39ce9790443a39cd"}, - {file = "frozendict-2.4.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d69418479bfb834ba75b0e764f058af46ceee3d655deb6a0dd0c0c1a5e82f09"}, - {file = "frozendict-2.4.6-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:c131f10c4d3906866454c4e89b87a7e0027d533cce8f4652aa5255112c4d6677"}, - {file = "frozendict-2.4.6-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:fc67cbb3c96af7a798fab53d52589752c1673027e516b702ab355510ddf6bdff"}, - {file = "frozendict-2.4.6-cp37-cp37m-win_amd64.whl", hash = "sha256:7730f8ebe791d147a1586cbf6a42629351d4597773317002181b66a2da0d509e"}, - {file = "frozendict-2.4.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:807862e14b0e9665042458fde692c4431d660c4219b9bb240817f5b918182222"}, - {file = "frozendict-2.4.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9647c74efe3d845faa666d4853cfeabbaee403b53270cabfc635b321f770e6b8"}, - {file = "frozendict-2.4.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:665fad3f0f815aa41294e561d98dbedba4b483b3968e7e8cab7d728d64b96e33"}, - {file = "frozendict-2.4.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f42e6b75254ea2afe428ad6d095b62f95a7ae6d4f8272f0bd44a25dddd20f67"}, - {file = "frozendict-2.4.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:02331541611f3897f260900a1815b63389654951126e6e65545e529b63c08361"}, - {file = "frozendict-2.4.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:18d50a2598350b89189da9150058191f55057581e40533e470db46c942373acf"}, - {file = "frozendict-2.4.6-cp38-cp38-win_amd64.whl", hash = "sha256:1b4a3f8f6dd51bee74a50995c39b5a606b612847862203dd5483b9cd91b0d36a"}, - {file = "frozendict-2.4.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a76cee5c4be2a5d1ff063188232fffcce05dde6fd5edd6afe7b75b247526490e"}, - {file = "frozendict-2.4.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba5ef7328706db857a2bdb2c2a17b4cd37c32a19c017cff1bb7eeebc86b0f411"}, - {file = "frozendict-2.4.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:669237c571856be575eca28a69e92a3d18f8490511eff184937283dc6093bd67"}, - {file = "frozendict-2.4.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0aaa11e7c472150efe65adbcd6c17ac0f586896096ab3963775e1c5c58ac0098"}, - {file = "frozendict-2.4.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:b8f2829048f29fe115da4a60409be2130e69402e29029339663fac39c90e6e2b"}, - {file = "frozendict-2.4.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:94321e646cc39bebc66954a31edd1847d3a2a3483cf52ff051cd0996e7db07db"}, - {file = "frozendict-2.4.6-cp39-cp39-win_amd64.whl", hash = "sha256:74b6b26c15dddfefddeb89813e455b00ebf78d0a3662b89506b4d55c6445a9f4"}, - {file = "frozendict-2.4.6-cp39-cp39-win_arm64.whl", hash = "sha256:7088102345d1606450bd1801a61139bbaa2cb0d805b9b692f8d81918ea835da6"}, - {file = "frozendict-2.4.6-py311-none-any.whl", hash = "sha256:d065db6a44db2e2375c23eac816f1a022feb2fa98cbb50df44a9e83700accbea"}, - {file = "frozendict-2.4.6-py312-none-any.whl", hash = "sha256:49344abe90fb75f0f9fdefe6d4ef6d4894e640fadab71f11009d52ad97f370b9"}, - {file = "frozendict-2.4.6-py313-none-any.whl", hash = "sha256:7134a2bb95d4a16556bb5f2b9736dceb6ea848fa5b6f3f6c2d6dba93b44b4757"}, - {file = "frozendict-2.4.6.tar.gz", hash = "sha256:df7cd16470fbd26fc4969a208efadc46319334eb97def1ddf48919b351192b8e"}, + {file = "frozendict-2.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bd37c087a538944652363cfd77fb7abe8100cc1f48afea0b88b38bf0f469c3d2"}, + {file = "frozendict-2.4.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2b96f224a5431889f04b2bc99c0e9abe285679464273ead83d7d7f2a15907d35"}, + {file = "frozendict-2.4.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5c1781f28c4bbb177644b3cb6d5cf7da59be374b02d91cdde68d1d5ef32e046b"}, + {file = "frozendict-2.4.7-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8a06f6c3d3b8d487226fdde93f621e04a54faecc5bf5d9b16497b8f9ead0ac3e"}, + {file = "frozendict-2.4.7-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b809d1c861436a75b2b015dbfd94f6154fa4e7cb0a70e389df1d5f6246b21d1e"}, + {file = "frozendict-2.4.7-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:75eefdf257a84ea73d553eb80d0abbff0af4c9df62529e4600fd3f96ff17eeb3"}, + {file = "frozendict-2.4.7-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a4d2b27d8156922c9739dd2ff4f3934716e17cfd1cf6fb61aa17af7d378555e9"}, + {file = "frozendict-2.4.7-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2ebd953c41408acfb8041ff9e6c3519c09988fb7e007df7ab6b56e229029d788"}, + {file = "frozendict-2.4.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c64d34b802912ee6d107936e970b90750385a1fdfd38d310098b2918ba4cbf2"}, + {file = "frozendict-2.4.7-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:294a7d7d51dd979021a8691b46aedf9bd4a594ce3ed33a4bdf0a712d6929d712"}, + {file = "frozendict-2.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f65d1b90e9ddc791ea82ef91a9ae0ab27ef6c0cfa88fadfa0e5ca5a22f8fa22f"}, + {file = "frozendict-2.4.7-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:82d5272d08451bcef6fb6235a0a04cf1816b6b6815cec76be5ace1de17e0c1a4"}, + {file = "frozendict-2.4.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5943c3f683d3f32036f6ca975e920e383d85add1857eee547742de9c1f283716"}, + {file = "frozendict-2.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:88c6bea948da03087035bb9ca9625305d70e084aa33f11e17048cb7dda4ca293"}, + {file = "frozendict-2.4.7-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:ffd1a9f9babec9119712e76a39397d8aa0d72ef8c4ccad917c6175d7e7f81b74"}, + {file = "frozendict-2.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0ff6f57854cc8aa8b30947ec005f9246d96e795a78b21441614e85d39b708822"}, + {file = "frozendict-2.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d774df483c12d6cba896eb9a1337bbc5ad3f564eb18cfaaee3e95fb4402f2a86"}, + {file = "frozendict-2.4.7-cp310-cp310-win32.whl", hash = "sha256:a10d38fa300f6bef230fae1fdb4bc98706b78c8a3a2f3140fde748469ef3cfe8"}, + {file = "frozendict-2.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:dd518f300e5eb6a8827bee380f2e1a31c01dc0af069b13abdecd4e5769bd8a97"}, + {file = "frozendict-2.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:3842cfc2d69df5b9978f2e881b7678a282dbdd6846b11b5159f910bc633cbe4f"}, + {file = "frozendict-2.4.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:735be62d757e1e7e496ccb6401efe82b473faa653e95eec0826cd7819a29a34c"}, + {file = "frozendict-2.4.7-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fff8584e3bbdc5c1713cd016fbf4b88babfffd4e5e89b39020f2a208dd24c900"}, + {file = "frozendict-2.4.7-cp36-cp36m-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:91a06ee46b3e3ef3b237046b914c0c905eab9fdfeac677e9b51473b482e24c28"}, + {file = "frozendict-2.4.7-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fd7ba56cf6340c732ecb78787c4e9600c4bd01372af7313ded21037126d33ec6"}, + {file = "frozendict-2.4.7-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d1b4426457757c30ad86b57cdbcc0adaa328399f1ec3d231a0a2ce7447248987"}, + {file = "frozendict-2.4.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b22d337c76b765cb7961d4ee47fe29f89e30921eb47bf856b14dc7641f4df3e5"}, + {file = "frozendict-2.4.7-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57134ef5df1dd32229c148c75a7b89245dbdb89966a155d6dfd4bda653e8c7af"}, + {file = "frozendict-2.4.7-cp36-cp36m-musllinux_1_2_aarch64.whl", hash = "sha256:c89617a784e1c24a31f5aa4809402f8072a26b64ddbc437897f6391ff69b0ee9"}, + {file = "frozendict-2.4.7-cp36-cp36m-musllinux_1_2_armv7l.whl", hash = "sha256:176dd384dfe1d0d79449e05f67764c57c6f0f3095378bf00deb33165d5d2df5b"}, + {file = "frozendict-2.4.7-cp36-cp36m-musllinux_1_2_i686.whl", hash = "sha256:b1a94e8935c69ae30043b465af496f447950f2c03660aee8657074084faae0b3"}, + {file = "frozendict-2.4.7-cp36-cp36m-musllinux_1_2_ppc64le.whl", hash = "sha256:c570649ceccfa5e11ad9351e9009dc484c315a51a56aa02ced07ae97644bb7aa"}, + {file = "frozendict-2.4.7-cp36-cp36m-musllinux_1_2_s390x.whl", hash = "sha256:e0d450c9d444befe2668bf9386ac2945a2f38152248d58f6b3feea63db59ba08"}, + {file = "frozendict-2.4.7-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:7469912c1a04102457871ff675aebe600dbb7e79a6450a166cc8079b88f6ca79"}, + {file = "frozendict-2.4.7-cp36-cp36m-win32.whl", hash = "sha256:2808bab8e21887a8c106cca5f6f0ab5bda7ee81e159409a10f53d57542ccd99c"}, + {file = "frozendict-2.4.7-cp36-cp36m-win_amd64.whl", hash = "sha256:ca17ac727ffeeba6c46f5a88e0284a7cb1520fb03127645fcdd7041080adf849"}, + {file = "frozendict-2.4.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ef11dd996208c5a96eab0683f7a17cb4b992948464d2498520efd75a10a2aac"}, + {file = "frozendict-2.4.7-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b960e700dc95faca7dd6919d0dce183ef89bfe01554d323cf5de7331a2e80f83"}, + {file = "frozendict-2.4.7-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:fc43257a06e6117da6a8a0779243b974cdb9205fed82e32eb669f6746c75d27d"}, + {file = "frozendict-2.4.7-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0ece525da7d0aa3eb56c3e479f30612028d545081c15450d67d771a303ee7d4c"}, + {file = "frozendict-2.4.7-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ddffe7c0b3be414f88185e212758989c65b497315781290eb029e2c1e1fd64e"}, + {file = "frozendict-2.4.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05dd27415f913cd11649009f53d97eb565ce7b76787d7869c4733738c10e8d27"}, + {file = "frozendict-2.4.7-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0664092614d2b9d0aa404731f33ad5459a54fe8dab9d1fd45aa714fa6de4d0ef"}, + {file = "frozendict-2.4.7-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:830d181781bb263c9fa430b81f82c867546f5dcb368e73931c8591f533a04afb"}, + {file = "frozendict-2.4.7-cp37-cp37m-musllinux_1_2_armv7l.whl", hash = "sha256:c93827e0854393cd904b927ceb529afc17776706f5b9e45c7eaf6a40b3fc7b25"}, + {file = "frozendict-2.4.7-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:6d30dbba6eb1497c695f3108c2c292807e7a237c67a1b9ff92c04e89969d22d1"}, + {file = "frozendict-2.4.7-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:ec846bde66b75d68518c7b24a0a46d09db0aee5a6aefd2209d9901faf6e9df21"}, + {file = "frozendict-2.4.7-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:1df8e22f7d24172c08434b10911f3971434bb5a59b4d1b0078ae33a623625294"}, + {file = "frozendict-2.4.7-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:39abe54264ae69a0b2e00fabdb5118604f36a5b927d33e7532cd594c5142ebf4"}, + {file = "frozendict-2.4.7-cp37-cp37m-win32.whl", hash = "sha256:d10c2ea7c90ba204cd053167ba214d0cdd00f3184c7b8d117a56d7fd2b0c6553"}, + {file = "frozendict-2.4.7-cp37-cp37m-win_amd64.whl", hash = "sha256:346a53640f15c1640a3503f60ba99df39e4ab174979f10db4304bbb378df5cbd"}, + {file = "frozendict-2.4.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:cc520f3f4af14f456143a534d554175dbc0f0636ffd653e63675cd591862a9d9"}, + {file = "frozendict-2.4.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7fd0d0bd3a79e009dddbf5fedfd927ad495c218cd7b13a112d28a37e2079725c"}, + {file = "frozendict-2.4.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a404857e48d85a517bb5b974d740f8c4fccb25d8df98885f3a2a4d950870b845"}, + {file = "frozendict-2.4.7-cp38-cp38-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:f42e2c25d3eee4ea3da88466f38ed0dce8c622a1a9d92572e5ee53b7a6bb9ef1"}, + {file = "frozendict-2.4.7-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1a083e9ee7a1904e545a6307c7db1dd76200077520fcbf7a98d886f81b57dd7"}, + {file = "frozendict-2.4.7-cp38-cp38-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f556ea05d9c5f6dae50d57ce6234e4ab1fbf4551dd0d52b4fed6ef537d9f3d3c"}, + {file = "frozendict-2.4.7-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:739ee81e574f33b46f1e6d9312f3ec2c549bdd574a4ebb6bf106775c9d85ca7b"}, + {file = "frozendict-2.4.7-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:48ab42b01952bc11543577de9fe5d9ca7c41b35dda36326a07fb47d84b3d5f22"}, + {file = "frozendict-2.4.7-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34233deb8d09e798e874a6ac00b054d2e842164d982ebd43eb91b9f0a6a34876"}, + {file = "frozendict-2.4.7-cp38-cp38-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:76bd99f3508cb2ec87976f2e3fe7d92fb373a661cacffb863013d15e4cfaf0eb"}, + {file = "frozendict-2.4.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a265e95e7087f44b88a6d78a63ea95a2ca0eb0a21ab4f76047f4c164a8beb413"}, + {file = "frozendict-2.4.7-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:1662f1b72b4f4a2ffdfdc4981ece275ca11f90244208ac1f1fc2c17fc9c9437a"}, + {file = "frozendict-2.4.7-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:2e5d2c30f4a3fea83a14b0a5722f21c10de5c755ab5637c70de5eb60886d58cd"}, + {file = "frozendict-2.4.7-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:2cf0a665bf2f1ce69d3cd8b6d3574b1d32ae00981a16fa1d255d2da8a2e44b7c"}, + {file = "frozendict-2.4.7-cp38-cp38-musllinux_1_2_riscv64.whl", hash = "sha256:708382875c3cfe91be625dddcba03dee2dfdadbad2c431568a8c7f2f2af0bbee"}, + {file = "frozendict-2.4.7-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:7fe194f37052a8f45a1a8507e36229e28b79f3d21542ae55ea6a18c6a444f625"}, + {file = "frozendict-2.4.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d8930877a2dd40461968d9238d95c754e51b33ce7d2a45500f88ffeed5cb7202"}, + {file = "frozendict-2.4.7-cp38-cp38-win32.whl", hash = "sha256:6991469a889ee8a108fe5ed1b044447c7b7a07da9067e93c59cbfac8c1d625cf"}, + {file = "frozendict-2.4.7-cp38-cp38-win_amd64.whl", hash = "sha256:ebae8f4a07372acfc3963fc8d68070cdaab70272c3dd836f057ebbe9b7d38643"}, + {file = "frozendict-2.4.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1c521ad3d747aa475e9040e231f5f1847c04423bae5571c010a9d969e6983c40"}, + {file = "frozendict-2.4.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70e655c3aa5f893807830f549a7275031a181dbebeaf74c461b51adc755d9335"}, + {file = "frozendict-2.4.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11d35075f979c96f528d74ccbf89322a7ef8211977dd566bc384985ebce689be"}, + {file = "frozendict-2.4.7-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d4d7ec24d3bfcfac3baf4dffd7fcea3fa8474b087ce32696232132064aa062cf"}, + {file = "frozendict-2.4.7-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5694417864875ca959932e3b98e2b7d5d27c75177bf510939d0da583712ddf58"}, + {file = "frozendict-2.4.7-cp39-cp39-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:57a754671c5746e11140363aa2f4e7a75c8607de6e85a2bf89dcd1daf51885a7"}, + {file = "frozendict-2.4.7-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:313e0e1d8b22b317aa1f7dd48aec8cbb0416ddd625addf7648a69148fcb9ccff"}, + {file = "frozendict-2.4.7-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:176a66094428b9fd66270927b9787e3b8b1c9505ef92723c7b0ef1923dbe3c4a"}, + {file = "frozendict-2.4.7-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de1fff2683d8af01299ec01eb21a24b6097ce92015fc1fbefa977cecf076a3fc"}, + {file = "frozendict-2.4.7-cp39-cp39-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:115a822ecd754574e11205e0880e9d61258d960863d6fd1b90883aa800f6d3b3"}, + {file = "frozendict-2.4.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:de8d2c98777ba266f5466e211778d4e3bd00635a207c54f6f7511d8613b86dd3"}, + {file = "frozendict-2.4.7-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:1e307be0e1f26cbc9593f6bdad5238a1408a50f39f63c9c39eb93c7de5926767"}, + {file = "frozendict-2.4.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:78a55f320ca924545494ce153df02d4349156cd95dc4603c1f0e80c42c889249"}, + {file = "frozendict-2.4.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:e89492dfcc4c27a718f8b5a4c8df1a2dec6c689718cccd70cb2ceba69ab8c642"}, + {file = "frozendict-2.4.7-cp39-cp39-musllinux_1_2_riscv64.whl", hash = "sha256:1e801d62e35df24be2c6f7f43c114058712efa79a8549c289437754dad0207a3"}, + {file = "frozendict-2.4.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:3ed9e2f3547a59f4ef5c233614c6faa6221d33004cb615ae1c07ffc551cfe178"}, + {file = "frozendict-2.4.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ad0448ed5569f0a9b9b010af9fb5b6d9bdc0b4b877a3ddb188396c4742e62284"}, + {file = "frozendict-2.4.7-cp39-cp39-win32.whl", hash = "sha256:eab9ef8a9268042e819de03079b984eb0894f05a7b63c4e5319b1cf1ef362ba7"}, + {file = "frozendict-2.4.7-cp39-cp39-win_amd64.whl", hash = "sha256:8dfe2f4840b043436ee5bdd07b0fa5daecedf086e6957e7df050a56ab6db078d"}, + {file = "frozendict-2.4.7-cp39-cp39-win_arm64.whl", hash = "sha256:cc2085926872a1b26deda4b81b2254d2e5d2cb2c4d7b327abe4c820b7c93f40b"}, + {file = "frozendict-2.4.7-py3-none-any.whl", hash = "sha256:972af65924ea25cf5b4d9326d549e69a9a4918d8a76a9d3a7cd174d98b237550"}, + {file = "frozendict-2.4.7.tar.gz", hash = "sha256:e478fb2a1391a56c8a6e10cc97c4a9002b410ecd1ac28c18d780661762e271bd"}, ] [[package]] @@ -1514,6 +1566,8 @@ files = [ {file = "greenlet-3.2.4-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2ca18a03a8cfb5b25bc1cbe20f3d9a4c80d8c3b13ba3df49ac3961af0b1018d"}, {file = "greenlet-3.2.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9fe0a28a7b952a21e2c062cd5756d34354117796c6d9215a87f55e38d15402c5"}, {file = "greenlet-3.2.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8854167e06950ca75b898b104b63cc646573aa5fef1353d4508ecdd1ee76254f"}, + {file = "greenlet-3.2.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f47617f698838ba98f4ff4189aef02e7343952df3a615f847bb575c3feb177a7"}, + {file = "greenlet-3.2.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af41be48a4f60429d5cad9d22175217805098a9ef7c40bfef44f7669fb9d74d8"}, {file = "greenlet-3.2.4-cp310-cp310-win_amd64.whl", hash = "sha256:73f49b5368b5359d04e18d15828eecc1806033db5233397748f4ca813ff1056c"}, {file = "greenlet-3.2.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:96378df1de302bc38e99c3a9aa311967b7dc80ced1dcc6f171e99842987882a2"}, {file = "greenlet-3.2.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1ee8fae0519a337f2329cb78bd7a8e128ec0f881073d43f023c7b8d4831d5246"}, @@ -1523,6 +1577,8 @@ files = [ {file = "greenlet-3.2.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2523e5246274f54fdadbce8494458a2ebdcdbc7b802318466ac5606d3cded1f8"}, {file = "greenlet-3.2.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1987de92fec508535687fb807a5cea1560f6196285a4cde35c100b8cd632cc52"}, {file = "greenlet-3.2.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:55e9c5affaa6775e2c6b67659f3a71684de4c549b3dd9afca3bc773533d284fa"}, + {file = "greenlet-3.2.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c9c6de1940a7d828635fbd254d69db79e54619f165ee7ce32fda763a9cb6a58c"}, + {file = "greenlet-3.2.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03c5136e7be905045160b1b9fdca93dd6727b180feeafda6818e6496434ed8c5"}, {file = "greenlet-3.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:9c40adce87eaa9ddb593ccb0fa6a07caf34015a29bf8d344811665b573138db9"}, {file = "greenlet-3.2.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3b67ca49f54cede0186854a008109d6ee71f66bd57bb36abd6d0a0267b540cdd"}, {file = "greenlet-3.2.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddf9164e7a5b08e9d22511526865780a576f19ddd00d62f8a665949327fde8bb"}, @@ -1532,6 +1588,8 @@ files = [ {file = "greenlet-3.2.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b3812d8d0c9579967815af437d96623f45c0f2ae5f04e366de62a12d83a8fb0"}, {file = "greenlet-3.2.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:abbf57b5a870d30c4675928c37278493044d7c14378350b3aa5d484fa65575f0"}, {file = "greenlet-3.2.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:20fb936b4652b6e307b8f347665e2c615540d4b42b3b4c8a321d8286da7e520f"}, + {file = "greenlet-3.2.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee7a6ec486883397d70eec05059353b8e83eca9168b9f3f9a361971e77e0bcd0"}, + {file = "greenlet-3.2.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:326d234cbf337c9c3def0676412eb7040a35a768efc92504b947b3e9cfc7543d"}, {file = "greenlet-3.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:a7d4e128405eea3814a12cc2605e0e6aedb4035bf32697f72deca74de4105e02"}, {file = "greenlet-3.2.4-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:1a921e542453fe531144e91e1feedf12e07351b1cf6c9e8a3325ea600a715a31"}, {file = "greenlet-3.2.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd3c8e693bff0fff6ba55f140bf390fa92c994083f838fece0f63be121334945"}, @@ -1541,6 +1599,8 @@ files = [ {file = "greenlet-3.2.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23768528f2911bcd7e475210822ffb5254ed10d71f4028387e5a99b4c6699671"}, {file = "greenlet-3.2.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:00fadb3fedccc447f517ee0d3fd8fe49eae949e1cd0f6a611818f4f6fb7dc83b"}, {file = "greenlet-3.2.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:d25c5091190f2dc0eaa3f950252122edbbadbb682aa7b1ef2f8af0f8c0afefae"}, + {file = "greenlet-3.2.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e343822feb58ac4d0a1211bd9399de2b3a04963ddeec21530fc426cc121f19b"}, + {file = "greenlet-3.2.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca7f6f1f2649b89ce02f6f229d7c19f680a6238af656f61e0115b24857917929"}, {file = "greenlet-3.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:554b03b6e73aaabec3745364d6239e9e012d64c68ccd0b8430c64ccc14939a8b"}, {file = "greenlet-3.2.4-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:49a30d5fda2507ae77be16479bdb62a660fa51b1eb4928b524975b3bde77b3c0"}, {file = "greenlet-3.2.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:299fd615cd8fc86267b47597123e3f43ad79c9d8a22bebdce535e53550763e2f"}, @@ -1548,6 +1608,8 @@ files = [ {file = "greenlet-3.2.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b4a1870c51720687af7fa3e7cda6d08d801dae660f75a76f3845b642b4da6ee1"}, {file = "greenlet-3.2.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:061dc4cf2c34852b052a8620d40f36324554bc192be474b9e9770e8c042fd735"}, {file = "greenlet-3.2.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44358b9bf66c8576a9f57a590d5f5d6e72fa4228b763d0e43fee6d3b06d3a337"}, + {file = "greenlet-3.2.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2917bdf657f5859fbf3386b12d68ede4cf1f04c90c3a6bc1f013dd68a22e2269"}, + {file = "greenlet-3.2.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:015d48959d4add5d6c9f6c5210ee3803a830dce46356e3bc326d6776bde54681"}, {file = "greenlet-3.2.4-cp314-cp314-win_amd64.whl", hash = "sha256:e37ab26028f12dbb0ff65f29a8d3d44a765c61e729647bf2ddfbbed621726f01"}, {file = "greenlet-3.2.4-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:b6a7c19cf0d2742d0809a4c05975db036fdff50cd294a93632d6a310bf9ac02c"}, {file = "greenlet-3.2.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:27890167f55d2387576d1f41d9487ef171849ea0359ce1510ca6e06c8bece11d"}, @@ -1557,6 +1619,8 @@ files = [ {file = "greenlet-3.2.4-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9913f1a30e4526f432991f89ae263459b1c64d1608c0d22a5c79c287b3c70df"}, {file = "greenlet-3.2.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b90654e092f928f110e0007f572007c9727b5265f7632c2fa7415b4689351594"}, {file = "greenlet-3.2.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:81701fd84f26330f0d5f4944d4e92e61afe6319dcd9775e39396e39d7c3e5f98"}, + {file = "greenlet-3.2.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:28a3c6b7cd72a96f61b0e4b2a36f681025b60ae4779cc73c1535eb5f29560b10"}, + {file = "greenlet-3.2.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:52206cd642670b0b320a1fd1cbfd95bca0e043179c1d8a045f2c6109dfe973be"}, {file = "greenlet-3.2.4-cp39-cp39-win32.whl", hash = "sha256:65458b409c1ed459ea899e939f0e1cdb14f58dbc803f2f93c5eab5694d32671b"}, {file = "greenlet-3.2.4-cp39-cp39-win_amd64.whl", hash = "sha256:d2e685ade4dafd447ede19c31277a224a239a0a1a4eca4e6390efedf20260cfb"}, {file = "greenlet-3.2.4.tar.gz", hash = "sha256:0dca0d95ff849f9a364385f36ab49f50065d76964944638be9691e1832e9f86d"}, diff --git a/syncmaster/dto/connections.py b/syncmaster/dto/connections.py index 1dcbb506..4624e698 100644 --- a/syncmaster/dto/connections.py +++ b/syncmaster/dto/connections.py @@ -74,10 +74,8 @@ class HiveConnectionDTO(ConnectionDTO): @dataclass -class IcebergRESTCatalogS3ConnectionDTO(ConnectionDTO): +class IcebergRESTCatalogS3ConnectionBaseDTO(ConnectionDTO): metastore_url: str - metastore_username: str - metastore_password: str s3_warehouse_path: str s3_host: str s3_bucket: str @@ -91,6 +89,33 @@ class IcebergRESTCatalogS3ConnectionDTO(ConnectionDTO): type: ClassVar[str] = "iceberg_rest_s3" +@dataclass(kw_only=True) +class IcebergRESTCatalogBasicAuthS3DTO(IcebergRESTCatalogS3ConnectionBaseDTO): + metastore_username: str + metastore_password: str + metastore_auth_type: Literal["basic"] = "basic" + + +@dataclass(kw_only=True) +class IcebergRESTCatalogOAuth2ClientCredentialsS3DTO(IcebergRESTCatalogS3ConnectionBaseDTO): + metastore_oauth2_client_id: str + metastore_oauth2_client_secret: str + metastore_oauth2_scopes: list[str] + metastore_oauth2_resource: str | None = None + metastore_oauth2_audience: str | None = None + metastore_oauth2_server_uri: str | None = None + metastore_auth_type: Literal["oauth2"] = "oauth2" + + +# TODO: should be refactored +class IcebergRESTCatalogS3ConnectionDTO: + def __new__(cls, **data): + if "metastore_oauth2_client_id" in data: + return IcebergRESTCatalogOAuth2ClientCredentialsS3DTO(**data) + + return IcebergRESTCatalogBasicAuthS3DTO(**data) + + @dataclass class HDFSConnectionDTO(ConnectionDTO): user: str diff --git a/syncmaster/schemas/v1/auth/__init__.py b/syncmaster/schemas/v1/auth/__init__.py index e13da280..be2bd504 100644 --- a/syncmaster/schemas/v1/auth/__init__.py +++ b/syncmaster/schemas/v1/auth/__init__.py @@ -6,12 +6,6 @@ ReadBasicAuthSchema, UpdateBasicAuthSchema, ) -from syncmaster.schemas.v1.auth.iceberg_rest_basic import ( - CreateIcebergRESTCatalogBasicAuthSchema, - IcebergRESTCatalogBasicAuthSchema, - ReadIcebergRESTCatalogBasicAuthSchema, - UpdateIcebergRESTCatalogBasicAuthSchema, -) from syncmaster.schemas.v1.auth.s3 import ( CreateS3AuthSchema, ReadS3AuthSchema, @@ -41,8 +35,4 @@ "UpdateSambaAuthSchema", "AuthTokenSchema", "TokenPayloadSchema", - "IcebergRESTCatalogBasicAuthSchema", - "CreateIcebergRESTCatalogBasicAuthSchema", - "ReadIcebergRESTCatalogBasicAuthSchema", - "UpdateIcebergRESTCatalogBasicAuthSchema", ] diff --git a/syncmaster/schemas/v1/auth/iceberg/__init__.py b/syncmaster/schemas/v1/auth/iceberg/__init__.py new file mode 100644 index 00000000..eb9bf462 --- /dev/null +++ b/syncmaster/schemas/v1/auth/iceberg/__init__.py @@ -0,0 +1,2 @@ +# SPDX-FileCopyrightText: 2023-2024 MTS PJSC +# SPDX-License-Identifier: Apache-2.0 diff --git a/syncmaster/schemas/v1/auth/iceberg/auth.py b/syncmaster/schemas/v1/auth/iceberg/auth.py new file mode 100644 index 00000000..23b08c27 --- /dev/null +++ b/syncmaster/schemas/v1/auth/iceberg/auth.py @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2023-2024 MTS PJSC +# SPDX-License-Identifier: Apache-2.0 +from typing import Annotated + +from pydantic import Field + +from syncmaster.schemas.v1.auth.iceberg.basic import ( + CreateIcebergRESTCatalogBasicAuthSchema, + ReadIcebergRESTCatalogBasicAuthSchema, + UpdateIcebergRESTCatalogBasicAuthSchema, +) +from syncmaster.schemas.v1.auth.iceberg.oauth2_client_credentials import ( + CreateIcebergRESTCatalogOAuth2ClientCredentialsAuthSchema, + ReadIcebergRESTCatalogOAuth2ClientCredentialsAuthSchema, + UpdateIcebergRESTCatalogOAuth2ClientCredentialsAuthSchema, +) + +CreateIcebergRESTCatalogS3ConnectionAuthDataSchema = Annotated[ + CreateIcebergRESTCatalogBasicAuthSchema | CreateIcebergRESTCatalogOAuth2ClientCredentialsAuthSchema, + Field(discriminator="type"), +] + +ReadIcebergRESTCatalogS3ConnectionAuthDataSchema = Annotated[ + ReadIcebergRESTCatalogBasicAuthSchema | ReadIcebergRESTCatalogOAuth2ClientCredentialsAuthSchema, + Field(discriminator="type"), +] + +UpdateIcebergRESTCatalogS3ConnectionAuthDataSchema = Annotated[ + UpdateIcebergRESTCatalogBasicAuthSchema | UpdateIcebergRESTCatalogOAuth2ClientCredentialsAuthSchema, + Field(discriminator="type"), +] diff --git a/syncmaster/schemas/v1/auth/iceberg_rest_basic.py b/syncmaster/schemas/v1/auth/iceberg/basic.py similarity index 100% rename from syncmaster/schemas/v1/auth/iceberg_rest_basic.py rename to syncmaster/schemas/v1/auth/iceberg/basic.py diff --git a/syncmaster/schemas/v1/auth/iceberg/oauth2_client_credentials.py b/syncmaster/schemas/v1/auth/iceberg/oauth2_client_credentials.py new file mode 100644 index 00000000..16b5c647 --- /dev/null +++ b/syncmaster/schemas/v1/auth/iceberg/oauth2_client_credentials.py @@ -0,0 +1,39 @@ +# SPDX-FileCopyrightText: 2023-2024 MTS PJSC +# SPDX-License-Identifier: Apache-2.0 +from typing import Literal + +from pydantic import BaseModel, Field, SecretStr + + +class IcebergRESTCatalogOAuth2ClientCredentialsAuthSchema(BaseModel): + type: Literal["iceberg_rest_oauth2_client_credentials_s3_basic"] + + +class CreateIcebergRESTCatalogOAuth2ClientCredentialsAuthSchema(IcebergRESTCatalogOAuth2ClientCredentialsAuthSchema): + metastore_oauth2_client_id: str + metastore_oauth2_client_secret: SecretStr + metastore_oauth2_scopes: list[str] = Field(default_factory=list) + metastore_oauth2_resource: str | None = None + metastore_oauth2_audience: str | None = None + metastore_oauth2_server_uri: str | None = None + s3_access_key: str + s3_secret_key: SecretStr + + +class ReadIcebergRESTCatalogOAuth2ClientCredentialsAuthSchema(IcebergRESTCatalogOAuth2ClientCredentialsAuthSchema): + metastore_oauth2_client_id: str + metastore_oauth2_scopes: list[str] + metastore_oauth2_resource: str | None + metastore_oauth2_audience: str | None + metastore_oauth2_server_uri: str | None + s3_access_key: str + + +class UpdateIcebergRESTCatalogOAuth2ClientCredentialsAuthSchema( + CreateIcebergRESTCatalogOAuth2ClientCredentialsAuthSchema, +): + metastore_oauth2_client_secret: SecretStr | None = None + s3_secret_key: SecretStr | None = None + + def get_secret_fields(self) -> tuple[str, ...]: + return ("metastore_oauth2_client_secret", "s3_secret_key") diff --git a/syncmaster/schemas/v1/connections/connection_base.py b/syncmaster/schemas/v1/connections/connection_base.py index 77e931bf..dfbc0f1a 100644 --- a/syncmaster/schemas/v1/connections/connection_base.py +++ b/syncmaster/schemas/v1/connections/connection_base.py @@ -4,14 +4,23 @@ from syncmaster.schemas.v1.auth import ( ReadBasicAuthSchema, - ReadIcebergRESTCatalogBasicAuthSchema, ReadS3AuthSchema, ReadSambaAuthSchema, ) +from syncmaster.schemas.v1.auth.iceberg.basic import ( + ReadIcebergRESTCatalogBasicAuthSchema, +) +from syncmaster.schemas.v1.auth.iceberg.oauth2_client_credentials import ( + ReadIcebergRESTCatalogOAuth2ClientCredentialsAuthSchema, +) from syncmaster.schemas.v1.types import NameConstr ReadConnectionAuthDataSchema = ( - ReadBasicAuthSchema | ReadS3AuthSchema | ReadSambaAuthSchema | ReadIcebergRESTCatalogBasicAuthSchema + ReadBasicAuthSchema + | ReadS3AuthSchema + | ReadSambaAuthSchema + | ReadIcebergRESTCatalogBasicAuthSchema + | ReadIcebergRESTCatalogOAuth2ClientCredentialsAuthSchema ) diff --git a/syncmaster/schemas/v1/connections/iceberg.py b/syncmaster/schemas/v1/connections/iceberg.py index 941529db..8998d443 100644 --- a/syncmaster/schemas/v1/connections/iceberg.py +++ b/syncmaster/schemas/v1/connections/iceberg.py @@ -5,10 +5,10 @@ from pydantic import BaseModel, Field -from syncmaster.schemas.v1.auth.iceberg_rest_basic import ( - CreateIcebergRESTCatalogBasicAuthSchema, - ReadIcebergRESTCatalogBasicAuthSchema, - UpdateIcebergRESTCatalogBasicAuthSchema, +from syncmaster.schemas.v1.auth.iceberg.auth import ( + CreateIcebergRESTCatalogS3ConnectionAuthDataSchema, + ReadIcebergRESTCatalogS3ConnectionAuthDataSchema, + UpdateIcebergRESTCatalogS3ConnectionAuthDataSchema, ) from syncmaster.schemas.v1.connection_types import ICEBERG_REST_S3_TYPE from syncmaster.schemas.v1.connections.connection_base import ( @@ -50,7 +50,7 @@ class CreateIcebergConnectionSchema(CreateConnectionBaseSchema): "Data required to connect to the database. These are the parameters that are specified in the URL request." ), ) - auth_data: CreateIcebergRESTCatalogBasicAuthSchema = Field( + auth_data: CreateIcebergRESTCatalogS3ConnectionAuthDataSchema = Field( description="Credentials for authorization", ) @@ -58,10 +58,10 @@ class CreateIcebergConnectionSchema(CreateConnectionBaseSchema): class ReadIcebergConnectionSchema(ReadConnectionBaseSchema): type: ICEBERG_REST_S3_TYPE data: ReadIcebergRESTCatalogS3ConnectionDataSchema = Field(alias="connection_data") - auth_data: ReadIcebergRESTCatalogBasicAuthSchema | None = None + auth_data: ReadIcebergRESTCatalogS3ConnectionAuthDataSchema | None = None class UpdateIcebergConnectionSchema(CreateIcebergConnectionSchema): - auth_data: UpdateIcebergRESTCatalogBasicAuthSchema = Field( + auth_data: UpdateIcebergRESTCatalogS3ConnectionAuthDataSchema = Field( description="Credentials for authorization", ) diff --git a/syncmaster/worker/handlers/db/iceberg.py b/syncmaster/worker/handlers/db/iceberg.py index b4336b4b..77fb461a 100644 --- a/syncmaster/worker/handlers/db/iceberg.py +++ b/syncmaster/worker/handlers/db/iceberg.py @@ -8,7 +8,7 @@ from onetl.connection import Iceberg from onetl.hooks import slot, support_hooks -from syncmaster.dto.connections import IcebergRESTCatalogS3ConnectionDTO +from syncmaster.dto.connections import IcebergRESTCatalogS3ConnectionBaseDTO from syncmaster.dto.transfers import IcebergRESTCatalogS3TransferDTO from syncmaster.worker.handlers.db.base import DBHandler @@ -20,7 +20,7 @@ @support_hooks class IcebergRESTCatalogS3Handler(DBHandler): connection: Iceberg - connection_dto: IcebergRESTCatalogS3ConnectionDTO + connection_dto: IcebergRESTCatalogS3ConnectionBaseDTO transfer_dto: IcebergRESTCatalogS3TransferDTO _operators = { "regexp": "RLIKE", @@ -33,10 +33,7 @@ def connect(self, spark: SparkSession): catalog_name=self.transfer_dto.catalog_name, catalog=Iceberg.RESTCatalog( uri=self.connection_dto.metastore_url, - auth=Iceberg.RESTCatalog.BasicAuth( - user=self.connection_dto.metastore_username, - password=self.connection_dto.metastore_password, - ), + auth=self._make_auth(), ), warehouse=Iceberg.S3Warehouse( path=self.connection_dto.s3_warehouse_path, @@ -91,3 +88,18 @@ def _get_reading_options(self) -> dict: def _quote_field(self, field: str) -> str: return f"`{field}`" + + def _make_auth(self): + if self.connection_dto.metastore_auth_type == "oauth2": + return Iceberg.RESTCatalog.OAuth2ClientCredentials( + client_id=self.connection_dto.metastore_oauth2_client_id, + client_secret=self.connection_dto.metastore_oauth2_client_secret, + scopes=self.connection_dto.metastore_oauth2_scopes, + resource=self.connection_dto.metastore_oauth2_resource, + audience=self.connection_dto.metastore_oauth2_audience, + server_uri=self.connection_dto.metastore_oauth2_server_uri, + ) + return Iceberg.RESTCatalog.BasicAuth( + user=self.connection_dto.metastore_username, + password=self.connection_dto.metastore_password, + ) diff --git a/tests/test_unit/test_connections/test_db_connection/test_create_iceberg_connection.py b/tests/test_unit/test_connections/test_db_connection/test_create_iceberg_connection.py index 88056887..97bbb1b0 100644 --- a/tests/test_unit/test_connections/test_db_connection/test_create_iceberg_connection.py +++ b/tests/test_unit/test_connections/test_db_connection/test_create_iceberg_connection.py @@ -88,3 +88,89 @@ async def test_developer_plus_can_create_iceberg_rest_s3_connection( "s3_access_key": decrypted["s3_access_key"], }, } + + +async def test_developer_plus_can_create_iceberg_rest_s3_connection_with_oauth2_client_credentials( + client: AsyncClient, + group: MockGroup, + session: AsyncSession, + settings: Settings, + role_developer_plus: UserTestRoles, +): + user = group.get_member_of_role(role_developer_plus) + + result = await client.post( + "v1/connections", + headers={"Authorization": f"Bearer {user.token}"}, + json={ + "group_id": group.id, + "name": "New connection", + "description": "", + "type": "iceberg_rest_s3", + "connection_data": { + "metastore_url": "https://rest.domain.com", + "s3_warehouse_path": "/some/warehouse", + "s3_protocol": "http", + "s3_host": "localhost", + "s3_port": 9010, + "s3_bucket": "some_bucket", + "s3_region": "us-east-1", + "s3_bucket_style": "path", + }, + "auth_data": { + "type": "iceberg_rest_oauth2_client_credentials_s3_basic", + "metastore_oauth2_client_id": "my_client_id", + "metastore_oauth2_client_secret": "my_client_secret", + "metastore_oauth2_scopes": ["catalog:read"], + "metastore_oauth2_audience": "iceberg-catalog", + "metastore_oauth2_server_uri": "https://oauth.example.com/token", + "s3_access_key": "access_key", + "s3_secret_key": "secret_key", + }, + }, + ) + connection = ( + await session.scalars( + select(Connection).filter_by( + name="New connection", + ), + ) + ).first() + + creds = ( + await session.scalars( + select(AuthData).filter_by( + connection_id=connection.id, + ), + ) + ).one() + + decrypted = decrypt_auth_data(creds.value, settings=settings) + assert result.status_code == 200, result.json() + assert result.json() == { + "id": connection.id, + "group_id": connection.group_id, + "name": connection.name, + "description": connection.description, + "type": connection.type, + "connection_data": { + "metastore_url": connection.data["metastore_url"], + "s3_warehouse_path": connection.data["s3_warehouse_path"], + "s3_protocol": connection.data["s3_protocol"], + "s3_host": connection.data["s3_host"], + "s3_port": connection.data["s3_port"], + "s3_bucket": connection.data["s3_bucket"], + "s3_region": connection.data["s3_region"], + "s3_bucket_style": connection.data["s3_bucket_style"], + "s3_additional_params": connection.data["s3_additional_params"], + }, + "auth_data": { + "type": decrypted["type"], + "metastore_oauth2_client_id": decrypted["metastore_oauth2_client_id"], + "metastore_oauth2_scopes": decrypted["metastore_oauth2_scopes"], + "metastore_oauth2_audience": decrypted["metastore_oauth2_audience"], + "metastore_oauth2_resource": decrypted["metastore_oauth2_resource"], + "metastore_oauth2_server_uri": decrypted["metastore_oauth2_server_uri"], + "s3_access_key": decrypted["s3_access_key"], + }, + } diff --git a/tests/test_unit/test_connections/test_db_connection/test_update_iceberg_connection.py b/tests/test_unit/test_connections/test_db_connection/test_update_iceberg_connection.py index 910ec370..baf256af 100644 --- a/tests/test_unit/test_connections/test_db_connection/test_update_iceberg_connection.py +++ b/tests/test_unit/test_connections/test_db_connection/test_update_iceberg_connection.py @@ -89,3 +89,100 @@ async def test_developer_plus_can_update_iceberg_rest_s3_connection( "s3_access_key": "new_access_key", }, } + + +@pytest.mark.parametrize( + "connection_type,create_connection_data,create_connection_auth_data", + [ + ( + "iceberg_rest_s3", + { + "metastore_url": "http://domain.com:8000", + "s3_warehouse_path": "/some/warehouse", + "s3_protocol": "http", + "s3_host": "localhost", + "s3_port": 9010, + "s3_bucket": "some_bucket", + "s3_region": "us-east-1", + "s3_bucket_style": "path", + }, + { + "type": "iceberg_rest_oauth2_client_credentials_s3_basic", + "metastore_oauth2_client_id": "my_client_id", + "metastore_oauth2_client_secret": "my_client_secret", + "metastore_oauth2_scopes": ["catalog:read"], + "metastore_oauth2_audience": "iceberg-catalog", + "metastore_oauth2_resource": None, + "metastore_oauth2_server_uri": "https://oauth.example.com/token", + "s3_access_key": "access_key", + "s3_secret_key": "secret_key", + }, + ), + ], + indirect=["create_connection_data", "create_connection_auth_data"], +) +async def test_developer_plus_can_update_iceberg_rest_s3_connection_with_oauth2_client_credentials( + client: AsyncClient, + group_connection: MockConnection, + role_developer_plus: UserTestRoles, +): + user = group_connection.owner_group.get_member_of_role(role_developer_plus) + connection_json = await fetch_connection_json(client, user.token, group_connection) + + result = await client.put( + f"v1/connections/{group_connection.id}", + headers={"Authorization": f"Bearer {user.token}"}, + json={ + **connection_json, + "type": group_connection.type, + "connection_data": { + "metastore_url": "http://rest.domain.com:8000", + "s3_warehouse_path": "/some/new/warehouse", + "s3_protocol": "https", + "s3_host": "s3.domain.com", + "s3_bucket": "new_bucket", + "s3_region": "us-east-2", + "s3_bucket_style": "domain", + }, + "auth_data": { + "type": "iceberg_rest_oauth2_client_credentials_s3_basic", + "metastore_oauth2_client_id": "my_new_client_id", + "metastore_oauth2_client_secret": "my_new_client_secret", + "metastore_oauth2_scopes": ["catalog:write"], + "metastore_oauth2_audience": "iceberg-new-catalog", + "metastore_oauth2_resource": "iceberg-new-resource", + "metastore_oauth2_server_uri": "https://oauth.new.example.com/token", + "s3_access_key": "new_access_key", + "s3_secret_key": "new_secret_key", + }, + }, + ) + + assert result.status_code == 200, result.json() + assert result.json() == { + "id": group_connection.id, + "name": group_connection.name, + "description": group_connection.description, + "group_id": group_connection.group_id, + "type": group_connection.type, + "connection_data": { + "metastore_url": "http://rest.domain.com:8000", + "s3_warehouse_path": "/some/new/warehouse", + "s3_protocol": "https", + "s3_host": "s3.domain.com", + "s3_port": None, + "s3_bucket": "new_bucket", + "s3_region": "us-east-2", + "s3_bucket_style": "domain", + "s3_additional_params": {}, + }, + "auth_data": { + "type": group_connection.credentials.value["type"], + "metastore_oauth2_client_id": "my_new_client_id", + "metastore_oauth2_scopes": ["catalog:write"], + "metastore_oauth2_audience": "iceberg-new-catalog", + "metastore_oauth2_resource": "iceberg-new-resource", + "metastore_oauth2_server_uri": "https://oauth.new.example.com/token", + "s3_access_key": "new_access_key", + }, + } diff --git a/tests/test_unit/utils.py b/tests/test_unit/utils.py index b31bfe5e..74575170 100644 --- a/tests/test_unit/utils.py +++ b/tests/test_unit/utils.py @@ -278,6 +278,11 @@ async def fetch_connection_json(client: AsyncClient, user_token: str, mock_conne elif auth_data["type"] == "iceberg_rest_basic_s3_basic": auth_data["metastore_password"] = mock_connection.credentials.value["metastore_password"] auth_data["s3_secret_key"] = mock_connection.credentials.value["s3_secret_key"] + elif auth_data["type"] == "iceberg_rest_oauth2_client_credentials_s3_basic": + auth_data["metastore_oauth2_client_secret"] = mock_connection.credentials.value[ + "metastore_oauth2_client_secret" + ] + auth_data["s3_secret_key"] = mock_connection.credentials.value["s3_secret_key"] return connection_json diff --git a/tests/utils.py b/tests/utils.py index 31844b40..d3b63d07 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -145,6 +145,11 @@ def verify_transfer_auth_data(run_data: dict[str, Any], source_auth: str, target assert auth_data["metastore_username"] assert "s3_secret_key" not in auth_data assert "metastore_password" not in auth_data + elif auth_type == "iceberg_rest_oauth2_client_credentials_s3_basic": + assert auth_data["s3_access_key"] + assert auth_data["metastore_oauth2_client_id"] + assert "s3_secret_key" not in auth_data + assert "metastore_oauth2_client_secret" not in auth_data else: assert auth_data["user"] assert "password" not in auth_data