From 0b35ed35911f5f150382b63ba9174c9627200d61 Mon Sep 17 00:00:00 2001 From: PaperMtn Date: Sun, 1 Sep 2024 22:07:14 +0100 Subject: [PATCH 1/6] Migrate to Poetry build and dependency management --- Dockerfile | 43 +++++- poetry.lock | 238 ++++++++++++++++++++++++++++++ pyproject.toml | 38 ++++- requirements.txt | 3 - setup.cfg | 35 ----- src/__init__.py | 0 src/slack_watchman/__init__.py | 13 +- src/slack_watchman/__version__.py | 35 ----- 8 files changed, 314 insertions(+), 91 deletions(-) create mode 100644 poetry.lock delete mode 100644 requirements.txt delete mode 100644 setup.cfg delete mode 100644 src/__init__.py delete mode 100644 src/slack_watchman/__version__.py diff --git a/Dockerfile b/Dockerfile index c1601ea..383733c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,40 @@ # syntax=docker/dockerfile:1 -FROM python:3.10 -COPY . /opt/slack-watchman +#FROM python:3.12-slim-bullseye +#WORKDIR /opt/slack-watchman +#COPY . /opt/slack-watchman +#RUN pip install poetry +#ENV PYTHONPATH=/opt/slack-watchman \ +# SLACK_WATCHMAN_TOKEN="" \ +# SLACK_WATCHMAN_COOKIE="" \ +# SLACK_WATCHMAN_URL="" +#RUN poetry config virtualenvs.create false && \ +# poetry install --no-dev && \ +# chmod -R 700 . && \ +# poetry build && \ +# pip install dist/*.whl +#STOPSIGNAL SIGINT +#WORKDIR /opt/slack-watchman +#ENTRYPOINT ["slack-watchman"] + +# syntax=docker/dockerfile:1 +FROM python:3.12-slim-bullseye AS builder WORKDIR /opt/slack-watchman -ENV PYTHONPATH=/opt/slack-watchman SLACK_WATCHMAN_TOKEN="" SLACK_WATCHMAN_COOKIE="" SLACK_WATCHMAN_URL="" -RUN pip3 install -r requirements.txt build && \ - chmod -R 700 . && \ - python3 -m build && \ - python3 -m pip install dist/*.whl -STOPSIGNAL SIGINT +COPY . . +RUN pip install poetry +RUN poetry config virtualenvs.create false && \ + poetry install --no-dev && \ + poetry build + +FROM python:3.12-slim-bullseye WORKDIR /opt/slack-watchman +COPY --from=builder /opt/slack-watchman/dist/*.whl /opt/slack-watchman/dist/ +COPY --from=builder /opt/slack-watchman/pyproject.toml /opt/slack-watchman/poetry.lock /opt/slack-watchman/ +ENV PYTHONPATH=/opt/slack-watchman \ + SLACK_WATCHMAN_TOKEN="" \ + SLACK_WATCHMAN_COOKIE="" \ + SLACK_WATCHMAN_URL="" +RUN pip install dist/*.whl && \ + chmod -R 700 . +STOPSIGNAL SIGINT ENTRYPOINT ["slack-watchman"] \ No newline at end of file diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..2f53189 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,238 @@ +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. + +[[package]] +name = "certifi" +version = "2024.8.30" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "idna" +version = "3.8" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, + {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, +] + +[[package]] +name = "requests" +version = "2.32.3" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "urllib3" +version = "2.2.2" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[metadata] +lock-version = "2.0" +python-versions = ">=3.10" +content-hash = "e1ea022f613b62aab2d599e878268a445dd9e1b6bf8ae74caa03a88c5ed6bf97" diff --git a/pyproject.toml b/pyproject.toml index 374b58c..8cb0a05 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,34 @@ -[build-system] -requires = [ - "setuptools>=42", - "wheel" +[tool.poetry] +name = "slack-watchman" +version = "4.1.0" +description = "Monitoring and enumerating Slack for exposed secrets" +authors = ["PaperMtn "] +license = "GPL-3.0" +readme = "README.md" +homepage = "https://github.com/PaperMtn/slack-watchman" +repository = "https://github.com/PaperMtn/slack-watchman" +keywords = [ "audit", "slack", "slack-watchman", "watchman", "blue-team", "red-team", "threat-hunting" ] +classifiers = [ + "Intended Audience :: Information Technology", + "Topic :: Cybersecurity", + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12" ] -build-backend = "setuptools.build_meta" + +[tool.poetry.urls] +"Blog" = "https://papermtn.co.uk/category/tools/slack-watchman/" + +[tool.poetry.dependencies] +python = ">=3.10" +colorama = "^0.4.6" +pyyaml = "^6.0.2" +requests = "^2.32.3" + +[tool.poetry.scripts] +slack-watchman = "slack_watchman:main" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 1193a43..0000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -requests -colorama -PyYAML \ No newline at end of file diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 6249596..0000000 --- a/setup.cfg +++ /dev/null @@ -1,35 +0,0 @@ -[metadata] -name = slack-watchman -version = attr: slack_watchman.__version__.__version__ -description = Monitoring and enumerating Slack for exposed secrets -long_description = file: README.md, CHANGELOG.md -long_description_content_type = text/markdown -license = GPL-3.0 -url = https://github.com/PaperMtn/slack-watchman -author = PaperMtn -author_email = papermtn@protonmail.com -keywords = audit, slack, slack-watchman, watchman, blue-team, red-team, threat-hunting -classifiers = - Intended Audience :: Information Technology - Topic :: Security - License :: OSI Approved :: GNU General Public License v3 (GPLv3) - Programming Language :: Python :: 3.10 - -[options] -zip_safe = False -package_dir = - = src -include_package_data = True -packages = find_namespace: -python_requires = >=3.10 -install_requires = - requests - PyYAML - colorama - -[options.entry_points] -console_scripts = - slack-watchman = slack_watchman:main - -[options.packages.find] -where = src \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/slack_watchman/__init__.py b/src/slack_watchman/__init__.py index 3ff4b2c..c9ce494 100644 --- a/src/slack_watchman/__init__.py +++ b/src/slack_watchman/__init__.py @@ -4,12 +4,14 @@ import sys import time import traceback +from importlib import metadata + import yaml from pathlib import Path from typing import List from . import sw_logger -from . import __version__ +# from . import __version__ from . import slack_wrapper as slack from . import signature_updater from . import exceptions @@ -180,7 +182,8 @@ def main(): try: OUTPUT_LOGGER = '' start_time = time.time() - parser = argparse.ArgumentParser(description=__version__.__summary__) + project_metadata = metadata.metadata('slack-watchman') + parser = argparse.ArgumentParser(description="Monitoring and enumerating Slack for exposed secrets") required = parser.add_argument_group('required arguments') required.add_argument('--timeframe', '-t', choices=['d', 'w', 'm', 'a'], dest='time', @@ -189,7 +192,7 @@ def main(): parser.add_argument('--output', '-o', choices=['json', 'stdout'], dest='logging_type', help='Where to send results') parser.add_argument('--version', '-v', action='version', - version=f'Slack Watchman: {__version__.__version__}') + version=f'Slack Watchman: {project_metadata.get("version")}') parser.add_argument('--all', '-a', dest='everything', action='store_true', help='Find secrets and PII') parser.add_argument('--users', '-u', dest='users', action='store_true', @@ -255,8 +258,8 @@ def main(): workspace_information = workspace.create_from_dict(slack_con.get_workspace_info().get('team')) OUTPUT_LOGGER.log('SUCCESS', 'Slack Watchman started execution') - OUTPUT_LOGGER.log('INFO', f'Version: {__version__.__version__}') - OUTPUT_LOGGER.log('INFO', f'Created by: {__version__.__author__} - {__version__.__email__}') + OUTPUT_LOGGER.log('INFO', f'Version: {project_metadata.get("version")}') + OUTPUT_LOGGER.log('INFO', f'Created by: PaperMtn ') OUTPUT_LOGGER.log('INFO', f'Searching workspace: {workspace_information.name}') OUTPUT_LOGGER.log('INFO', f'Workspace URL: {workspace_information.url}') OUTPUT_LOGGER.log('INFO', 'Downloading signature file updates') diff --git a/src/slack_watchman/__version__.py b/src/slack_watchman/__version__.py deleted file mode 100644 index 5ed6c6f..0000000 --- a/src/slack_watchman/__version__.py +++ /dev/null @@ -1,35 +0,0 @@ -# Slack Watchman -# Copyright (C) 2023 PaperMtn -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -__all__ = [ - '__title__', - '__summary__', - '__uri__', - '__version__', - '__author__', - '__email__', - '__license__', -] - -__title__ = 'Slack Watchman' -__version__ = '4.0.2' -__summary__ = 'Monitoring and enumerating Slack for exposed secrets' -__author__ = 'PaperMtn' -__email__ = 'papermtn@protonmail.com' -__license__ = 'GPL-3.0' -__uri__ = 'https://github.com/PaperMtn/slack-watchman' -__copyright__ = f'2023 {__author__}' - From 13a9c3df3b58c43c50bbd1efcb142deabb829df5 Mon Sep 17 00:00:00 2001 From: PaperMtn Date: Mon, 2 Sep 2024 19:53:30 +0100 Subject: [PATCH 2/6] Migrate to Poetry build and dependency management --- .github/workflows/github_release.yml | 17 +++++++---------- .github/workflows/pythonpackage.yml | 17 +++++++---------- .github/workflows/pythonpublish.yml | 21 ++++++++------------- 3 files changed, 22 insertions(+), 33 deletions(-) diff --git a/.github/workflows/github_release.yml b/.github/workflows/github_release.yml index 14b2ef8..1245da2 100644 --- a/.github/workflows/github_release.yml +++ b/.github/workflows/github_release.yml @@ -1,15 +1,15 @@ -name: Create Release +name: Create GitHub Release on: push: - branches: [ master ] + branches: [ main, master ] jobs: build: runs-on: ubuntu-latest strategy: matrix: - python-version: [ '3.10' ] + python-version: [ '3.12' ] steps: - name: Checkout uses: actions/checkout@v3 @@ -19,20 +19,17 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - python -m pip install --upgrade pip - pip install flake8 - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + pip install flake8 poetry + poetry install - name: Lint with flake8 run: | # stop the build if there are Python syntax errors or undefined names flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - name: Test setup & install + - name: Install run: | - pip install build twine - python3 -m build - twine check dist/*.whl + poetry build python3 -m pip install dist/*.whl - name: Extract release notes id: extract-release-notes diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 77d0e39..9cdac40 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -5,9 +5,9 @@ name: Python package on: push: - branches: [ develop ] + branches: [ develop, feature/**, release/** ] pull_request: - branches: [ develop ] + branches: [ develop, feature/**, release/** ] jobs: build-ubuntu: @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ['3.10'] + python-version: ['3.12'] steps: - uses: actions/checkout@v2 @@ -25,9 +25,8 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - python -m pip install --upgrade pip - pip install flake8 - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + pip install flake8 poetry + poetry install - name: Lint with flake8 run: | # stop the build if there are Python syntax errors or undefined names @@ -36,11 +35,9 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Test setup & install run: | - pip install build twine - python3 -m build - twine check dist/*.whl + poetry build python3 -m pip install dist/*.whl - name: Test run run: | slack-watchman --version - slack-watchman --help + slack-watchman --help \ No newline at end of file diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml index 119e458..612e54d 100644 --- a/.github/workflows/pythonpublish.yml +++ b/.github/workflows/pythonpublish.yml @@ -1,11 +1,9 @@ -# This workflows will upload a Python Package using Twine when a release is created -# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries -name: Upload Python Package +name: Poetry Publish on: push: - branches: [ master ] + branches: [ main ] jobs: deploy: @@ -17,14 +15,11 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: '3.x' + python-version: '3.12' - name: Install dependencies run: | - python3 -m pip install --upgrade pip twine build - - name: Build and publish - env: - TWINE_USERNAME: ${{ '__token__' }} - TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} - run: | - python3 -m build - twine upload dist/* + pip install poetry + poetry install + poetry config pypi-token.pypi "${{ secrets.PYPI_TOKEN }}" + - name: Publish package + run: poetry publish --build \ No newline at end of file From 5b3bb3307cffa452ef7aba6a1d98c9813b1f2262 Mon Sep 17 00:00:00 2001 From: PaperMtn Date: Mon, 2 Sep 2024 20:00:43 +0100 Subject: [PATCH 3/6] Migrate to Poetry build and dependency management --- pyproject.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8cb0a05..9398292 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,9 +12,6 @@ classifiers = [ "Intended Audience :: Information Technology", "Topic :: Cybersecurity", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12" ] [tool.poetry.urls] From 87cd6c66aa0f87d041ba91447c80607235b702c3 Mon Sep 17 00:00:00 2001 From: PaperMtn Date: Tue, 3 Sep 2024 16:11:36 +0100 Subject: [PATCH 4/6] Refactor to download and read signatures into memory instead of storing on-disk --- CHANGELOG.md | 6 ++ src/slack_watchman/__init__.py | 33 +------- src/slack_watchman/models/signature.py | 43 +--------- src/slack_watchman/signature_downloader.py | 98 ++++++++++++++++++++++ src/slack_watchman/signature_updater.py | 82 ------------------ 5 files changed, 109 insertions(+), 153 deletions(-) create mode 100644 src/slack_watchman/signature_downloader.py delete mode 100644 src/slack_watchman/signature_updater.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 95faa02..f52cdcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## [4.1.0] - 2024-09-02 +### Changed +- Signatures are now downloaded, processes and stored in memory instead of writing to disk. This saves having to store them in files, and solves the issues when using Slack Watchman with read-only filesystems (raised in #51) +- Migrated to Poetry for dependency control and packaging + + ## [4.0.2] - 2023-06-14 ### Added - Added notification for an invalid cookie being passed (Fixes #47) diff --git a/src/slack_watchman/__init__.py b/src/slack_watchman/__init__.py index c9ce494..d6301e0 100644 --- a/src/slack_watchman/__init__.py +++ b/src/slack_watchman/__init__.py @@ -7,13 +7,10 @@ from importlib import metadata import yaml -from pathlib import Path -from typing import List from . import sw_logger -# from . import __version__ from . import slack_wrapper as slack -from . import signature_updater +from . import signature_downloader from . import exceptions from .models import ( signature, @@ -23,31 +20,9 @@ conversation ) -SIGNATURES_PATH = (Path(__file__).parents[2] / 'watchman-signatures').resolve() OUTPUT_LOGGER: sw_logger.JSONLogger -def load_signatures() -> List[signature.Signature]: - """ Load signatures from YAML files - Returns: - List containing loaded definitions as Signatures objects - """ - - loaded_signatures = [] - try: - for root, dirs, files in os.walk(SIGNATURES_PATH): - for sig_file in files: - sig_path = (Path(root) / sig_file).resolve() - if sig_path.name.endswith('.yaml'): - loaded_def = signature.load_from_yaml(sig_path) - for sig in loaded_def: - if sig.status == 'enabled' and 'slack_std' in sig.watchman_apps: - loaded_signatures.append(sig) - return loaded_signatures - except Exception as e: - raise e - - def validate_conf(path: str, cookie: bool) -> bool: """ Check the file slack_watchman.conf exists @@ -262,10 +237,8 @@ def main(): OUTPUT_LOGGER.log('INFO', f'Created by: PaperMtn ') OUTPUT_LOGGER.log('INFO', f'Searching workspace: {workspace_information.name}') OUTPUT_LOGGER.log('INFO', f'Workspace URL: {workspace_information.url}') - OUTPUT_LOGGER.log('INFO', 'Downloading signature file updates') - signature_updater.SignatureUpdater(OUTPUT_LOGGER).update_signatures() - OUTPUT_LOGGER.log('INFO', 'Importing signatures...') - signature_list = load_signatures() + OUTPUT_LOGGER.log('INFO', 'Downloading and importing signatures...') + signature_list = signature_downloader.SignatureDownloader(OUTPUT_LOGGER).download_signatures() OUTPUT_LOGGER.log('SUCCESS', f'{len(signature_list)} signatures loaded') if cookie: OUTPUT_LOGGER.log('SUCCESS', 'Successfully authenticated using cookie') diff --git a/src/slack_watchman/models/signature.py b/src/slack_watchman/models/signature.py index f5d1425..c5164c3 100644 --- a/src/slack_watchman/models/signature.py +++ b/src/slack_watchman/models/signature.py @@ -1,16 +1,14 @@ -import pathlib -import yaml from dataclasses import dataclass from typing import List -@dataclass(slots=True) +@dataclass(frozen=True, slots=True) class TestCases: match_cases: List[str] fail_cases: List[str] -@dataclass(slots=True) +@dataclass(frozen=True, slots=True) class Signature: """ Class that handles loaded signature objects. Signatures define what to search for in Slack and where to search for it. @@ -30,40 +28,3 @@ class Signature: test_cases: TestCases search_strings: str patterns: List[str] - - -def load_from_yaml(sig_path: pathlib.PosixPath) -> List[Signature]: - """Load YAML file and return a Signature object - Args: - sig_path: Path of YAML file - Returns: - Signature object with fields populated from the YAML - signature file - """ - - with open(sig_path) as yaml_file: - yaml_import = yaml.safe_load(yaml_file) - - output = [] - for sig in yaml_import.get('signatures'): - if 'slack_std' in sig.get('watchman_apps'): - output.append(Signature( - name=sig.get('name'), - status=sig.get('status'), - author=sig.get('author'), - date=sig.get('date'), - version=sig.get('version'), - description=sig.get('description'), - severity=sig.get('severity'), - watchman_apps=sig.get('watchman_apps'), - category=sig.get('watchman_apps').get('slack_std').get('category'), - scope=sig.get('watchman_apps').get('slack_std').get('scope'), - file_types=sig.get('watchman_apps').get('slack_std').get('file_types'), - test_cases=TestCases( - match_cases=sig.get('test_cases').get('match_cases'), - fail_cases=sig.get('test_cases').get('fail_cases') - ), - search_strings=sig.get('watchman_apps').get('slack_std').get('search_strings'), - patterns=sig.get('patterns'))) - - return output diff --git a/src/slack_watchman/signature_downloader.py b/src/slack_watchman/signature_downloader.py new file mode 100644 index 0000000..5255d0f --- /dev/null +++ b/src/slack_watchman/signature_downloader.py @@ -0,0 +1,98 @@ +import io +import os +import sys +import traceback +import zipfile +from urllib.request import urlopen +from typing import List + +import yaml + +from sw_logger import JSONLogger, StdoutLogger +from models.signature import Signature, TestCases + +SIGNATURE_URL = 'https://github.com/PaperMtn/watchman-signatures/archive/main.zip' + + +class SignatureDownloader: + def __init__(self, logger: JSONLogger or StdoutLogger): + """ Initializes a SignatureDownloader object. + + Args: + logger (JSONLogger or StdoutLogger): The logger object to use for logging. + Returns: + None + """ + self.logger = logger + + def download_signatures(self) -> List[Signature]: + """ Download signatures from GitHub repository + + Returns: + List of downloaded Signature objects + """ + + try: + response = urlopen(SIGNATURE_URL) + signatures_zip_file = zipfile.ZipFile(io.BytesIO(response.read())) + signature_files = {} + signature_objects = [] + for file_path in signatures_zip_file.namelist(): + if file_path.endswith('/'): + continue + + signature_name = os.path.basename(file_path) + self.logger.log('DEBUG', f'Processing {file_path} ...') + + with signatures_zip_file.open(file_path) as source: + signature_files[signature_name] = source.read() + + if file_path.endswith('.yaml'): + signature_objects.append(self._process_signature(signature_files[signature_name])) + self.logger.log('SUCCESS', f'Downloaded signature file: {signature_name}') + else: + self.logger.log('DEBUG', f'Skipping unrecognized file: {file_path}') + + return [item for sublist in signature_objects for item in sublist] + + except Exception as e: + self.logger.log('CRITICAL', f'Error while processing the signature' + f' files from the download package: {e}') + self.logger.log('DEBUG', traceback.format_exc()) + sys.exit(1) + + def _process_signature(self, signature_data: bytes) -> List[Signature]: + """ Process a signature data bytes object into a list of Signature objects. + + This function takes a bytes object containing signature data, parses it into a dictionary, + and then creates a list of Signature objects based on the parsed data. + + Args: + signature_data (bytes): A bytes object containing signature data. + Returns: + List[Signature]: A list of Signature objects created from the parsed signature data. + """ + + signature_dict = yaml.safe_load(io.StringIO(signature_data.decode('utf-8'))) + output = [] + for sig in signature_dict.get('signatures'): + if 'slack_std' in sig.get('watchman_apps') and sig.get('status') == 'enabled': + output.append(Signature( + name=sig.get('name'), + status=sig.get('status'), + author=sig.get('author'), + date=sig.get('date'), + version=sig.get('version'), + description=sig.get('description'), + severity=sig.get('severity'), + watchman_apps=sig.get('watchman_apps'), + category=sig.get('watchman_apps').get('slack_std').get('category'), + scope=sig.get('watchman_apps').get('slack_std').get('scope'), + file_types=sig.get('watchman_apps').get('slack_std').get('file_types'), + test_cases=TestCases( + match_cases=sig.get('test_cases').get('match_cases'), + fail_cases=sig.get('test_cases').get('fail_cases') + ), + search_strings=sig.get('watchman_apps').get('slack_std').get('search_strings'), + patterns=sig.get('patterns'))) + return output diff --git a/src/slack_watchman/signature_updater.py b/src/slack_watchman/signature_updater.py deleted file mode 100644 index fdd6ddb..0000000 --- a/src/slack_watchman/signature_updater.py +++ /dev/null @@ -1,82 +0,0 @@ -import io -import os -import zipfile -import shutil -import sys -from datetime import datetime -from pathlib import Path -from urllib.request import urlopen - -from . import sw_logger - -SIGNATURE_URL = 'https://github.com/PaperMtn/watchman-signatures/archive/main.zip' - - -class SignatureUpdater(object): - def __init__(self, logger: sw_logger.JSONLogger): - self.application_path = str((Path(__file__).parents[2]).resolve()) - self.logger = logger - - def update_signatures(self): - - response = urlopen(SIGNATURE_URL) - - try: - sig_dir = os.path.join(self.application_path, 'watchman-signatures/') - for sub_directory in [ - '', - 'config_files', - 'competitive', - 'compliance', - 'tokens_and_credentials' - ]: - full_path = os.path.join(sig_dir, sub_directory) - if not os.path.exists(full_path): - os.makedirs(full_path) - except Exception as e: - self.logger.log('CRITICAL', 'Error while creating the signature-base directories') - sys.exit(1) - - try: - signatures_zip_file = zipfile.ZipFile(io.BytesIO(response.read())) - for file_path in signatures_zip_file.namelist(): - signature_name = os.path.basename(file_path) - if file_path.endswith('/'): - continue - - self.logger.log('DEBUG', f'Extracting {file_path} ...') - if '/competitive/' in file_path and file_path.endswith('.yaml'): - target_file = os.path.join(sig_dir, 'competitive', signature_name) - elif '/compliance/' in file_path and file_path.endswith('.yaml'): - target_file = os.path.join(sig_dir, 'compliance', signature_name) - elif '/config_files/' in file_path and file_path.endswith('.yaml'): - target_file = os.path.join(sig_dir, 'config_files', signature_name) - elif file_path.endswith('.yaml'): - target_file = os.path.join(sig_dir, 'tokens_and_credentials', signature_name) - elif file_path.endswith('.yaml'): - target_file = os.path.join(sig_dir, 'misc', signature_name) - else: - continue - - if os.path.exists(target_file): - existing_modified_date = datetime.utcfromtimestamp(os.path.getmtime(target_file)) - if datetime(*signatures_zip_file.getinfo(file_path).date_time) > existing_modified_date: - self.logger.log('SUCCESS', f'Signature updated to newest version: {signature_name}') - source = signatures_zip_file.open(file_path) - target = open(target_file, 'wb') - with source, target: - shutil.copyfileobj(source, target) - target.close() - source.close() - else: - self.logger.log('SUCCESS', f'New signature file: {signature_name}') - source = signatures_zip_file.open(file_path) - target = open(target_file, 'wb') - with source, target: - shutil.copyfileobj(source, target) - target.close() - source.close() - - except Exception as e: - self.logger.log('CRITICAL', f'Error while extracting the signature files from the download package {e}') - sys.exit(1) From fb6d02f2638ec04dd7afdc6d3aee4dad2c10ef8c Mon Sep 17 00:00:00 2001 From: PaperMtn Date: Tue, 3 Sep 2024 16:13:51 +0100 Subject: [PATCH 5/6] CHANGELOG.md update --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f52cdcf..96a3198 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,12 @@ ## [4.1.0] - 2024-09-02 ### Changed -- Signatures are now downloaded, processes and stored in memory instead of writing to disk. This saves having to store them in files, and solves the issues when using Slack Watchman with read-only filesystems (raised in #51) +- Signatures are now downloaded, processes and stored in memory instead of writing to disk. This saves having to store them in files, and solves the issues when using Slack Watchman with read-only filesystems (raised in [#51](https://github.com/PaperMtn/watchman-signatures/issues/51)) - Migrated to Poetry for dependency control and packaging ## [4.0.2] - 2023-06-14 ### Added -- Added notification for an invalid cookie being passed (Fixes #47) +- Added notification for an invalid cookie being passed (Fixes [#47](https://github.com/PaperMtn/watchman-signatures/issues/47)) ### Fixed - JSON output for User and Workspace information was malformed, this has now been fixed @@ -17,7 +17,7 @@ ## [4.0.0] - 2023-05-03 This major version release brings multiple updates to Slack Watchman in usability, functionality and behind the scenes improvements. -**Note**: While efforts have been made to make sure there is some backwards compatibility, this release may have some breaking changes on previous versions. Make sure to look at the removed secion +**Note**: While efforts have been made to make sure there is some backwards compatibility, this release may have some breaking changes on previous versions. Make sure to look at the removed section ### Added - Support for centralised signatures from the [Watchman Signatures repository](https://github.com/PaperMtn/watchman-signatures) From 36640cd774c55d70c821caaa79556128f7668567 Mon Sep 17 00:00:00 2001 From: PaperMtn Date: Tue, 3 Sep 2024 16:23:57 +0100 Subject: [PATCH 6/6] Fix imports --- src/slack_watchman/__init__.py | 24 ++++++++++++---------- src/slack_watchman/models/post.py | 3 +-- src/slack_watchman/signature_downloader.py | 4 ++-- src/slack_watchman/slack_wrapper.py | 5 ++--- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/slack_watchman/__init__.py b/src/slack_watchman/__init__.py index d6301e0..03ea149 100644 --- a/src/slack_watchman/__init__.py +++ b/src/slack_watchman/__init__.py @@ -8,11 +8,13 @@ import yaml -from . import sw_logger -from . import slack_wrapper as slack -from . import signature_downloader -from . import exceptions -from .models import ( +from slack_watchman import ( + sw_logger, + signature_downloader, + exceptions, + slack_wrapper +) +from slack_watchman.models import ( signature, user, workspace, @@ -83,7 +85,7 @@ def validate_conf(path: str, cookie: bool) -> bool: raise exceptions.MissingEnvVarError('SLACK_WATCHMAN_URL') -def search(slack_connection: slack.SlackAPI, +def search(slack_connection: slack_wrapper.SlackAPI, loaded_signature: signature.Signature, timeframe: int or str, scope: str, @@ -102,7 +104,7 @@ def search(slack_connection: slack.SlackAPI, if scope == 'messages': OUTPUT_LOGGER.log('INFO', f'Searching for posts containing {loaded_signature.name}') - messages = slack.find_messages( + messages = slack_wrapper.find_messages( slack_connection, OUTPUT_LOGGER, loaded_signature, @@ -119,7 +121,7 @@ def search(slack_connection: slack.SlackAPI, notify_type='result') if scope == 'files': OUTPUT_LOGGER.log('INFO', f'Searching for posts containing {loaded_signature.name}') - files = slack.find_files( + files = slack_wrapper.find_files( slack_connection, OUTPUT_LOGGER, loaded_signature, @@ -224,7 +226,7 @@ def main(): conf_path = f'{os.path.expanduser("~")}/watchman.conf' validate_conf(conf_path, cookie) - slack_con = slack.initiate_slack_connection(cookie) + slack_con = slack_wrapper.initiate_slack_connection(cookie) auth_data = slack_con.get_auth_test() calling_user = user.create_from_dict( @@ -251,7 +253,7 @@ def main(): if users: OUTPUT_LOGGER.log('INFO', 'Enumerating users...') - user_list = slack.get_users(slack_con, verbose) + user_list = slack_wrapper.get_users(slack_con, verbose) OUTPUT_LOGGER.log('SUCCESS', f'{len(user_list)} users discovered') OUTPUT_LOGGER.log('INFO', 'Writing to csv') sw_logger.export_csv('slack_users', user_list) @@ -261,7 +263,7 @@ def main(): if channels: OUTPUT_LOGGER.log('INFO', 'Enumerating channels...') - channel_list = slack.get_channels(slack_con, verbose) + channel_list = slack_wrapper.get_channels(slack_con, verbose) OUTPUT_LOGGER.log('SUCCESS', f'{len(channel_list)} channels discovered') OUTPUT_LOGGER.log('INFO', 'Writing to csv') sw_logger.export_csv('slack_channels', channel_list) diff --git a/src/slack_watchman/models/post.py b/src/slack_watchman/models/post.py index cc40cc4..5cf6653 100644 --- a/src/slack_watchman/models/post.py +++ b/src/slack_watchman/models/post.py @@ -2,8 +2,7 @@ from dataclasses import dataclass from typing import List, Dict -from . import conversation -from . import user +from slack_watchman.models import conversation, user def _convert_timestamp(timestamp: str or int) -> str or None: diff --git a/src/slack_watchman/signature_downloader.py b/src/slack_watchman/signature_downloader.py index 5255d0f..e77f973 100644 --- a/src/slack_watchman/signature_downloader.py +++ b/src/slack_watchman/signature_downloader.py @@ -8,8 +8,8 @@ import yaml -from sw_logger import JSONLogger, StdoutLogger -from models.signature import Signature, TestCases +from slack_watchman.sw_logger import JSONLogger, StdoutLogger +from slack_watchman.models.signature import Signature, TestCases SIGNATURE_URL = 'https://github.com/PaperMtn/watchman-signatures/archive/main.zip' diff --git a/src/slack_watchman/slack_wrapper.py b/src/slack_watchman/slack_wrapper.py index 8df1ae6..aba564d 100644 --- a/src/slack_watchman/slack_wrapper.py +++ b/src/slack_watchman/slack_wrapper.py @@ -14,9 +14,8 @@ from urllib3.util import Retry from requests.adapters import HTTPAdapter -from . import sw_logger -from . import exceptions -from .models import ( +from slack_watchman import sw_logger, exceptions +from slack_watchman.models import ( signature, user, post,