diff --git a/.github/workflows/python-app.yml b/.github/workflows/python-app.yml index 2e8690d..b90d369 100644 --- a/.github/workflows/python-app.yml +++ b/.github/workflows/python-app.yml @@ -1,6 +1,3 @@ -# This workflow will install Python dependencies, run tests and lint with a single version of Python -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - name: Python application on: @@ -13,27 +10,19 @@ permissions: contents: read jobs: - build: - + test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - name: Set up Python 3.10 - uses: actions/setup-python@v3 + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v6 with: - python-version: "3.10" + enable-cache: true + - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install flake8 pytest - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi - - 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 + run: uv sync + - name: Test with pytest - run: | - pytest + run: uv run pytest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..2f1cbf8 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,49 @@ +name: Release + +on: + push: + branches: [ master ] + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Install uv + uses: astral-sh/setup-uv@v6 + with: + enable-cache: true + + - name: Read version from pyproject.toml + id: version + run: | + VERSION=$(grep '^version' pyproject.toml | head -1 | sed 's/version = "\(.*\)"/\1/') + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Check if tag already exists + id: tag_check + run: | + if git rev-parse "refs/tags/${{ steps.version.outputs.version }}" >/dev/null 2>&1; then + echo "exists=true" >> "$GITHUB_OUTPUT" + else + echo "exists=false" >> "$GITHUB_OUTPUT" + fi + + - name: Create tag and release + if: steps.tag_check.outputs.exists == 'false' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + VERSION="${{ steps.version.outputs.version }}" + git tag "$VERSION" + git push origin "$VERSION" + gh release create "$VERSION" \ + --title "Release $VERSION" \ + --generate-notes diff --git a/.gitignore b/.gitignore index da2f28d..0b72a6c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,107 +1,30 @@ -# Byte-compiled / optimized / DLL files +# custom +cloud-enum-output + +# MacOS +.DS_Store + +# Python __pycache__/ *.py[cod] *$py.class - -# C extensions *.so - -# Distribution / packaging .Python build/ -develop-eggs/ dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ *.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# PyInstaller -# Usually these files are written by a python script from a template -# before PyInstaller builds the exe, so as to inject date/other infos into it. -*.manifest -*.spec - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ +.pytest_cache/ .coverage .coverage.* -.cache -nosetests.xml coverage.xml -*.cover +htmlcov/ +.tox/ +.nox/ .hypothesis/ -.pytest_cache/ - -# Translations -*.mo -*.pot - -# Django stuff: -*.log -local_settings.py -db.sqlite3 - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy - -# Sphinx documentation -docs/_build/ - -# PyBuilder -target/ - -# Jupyter Notebook -.ipynb_checkpoints - -# pyenv -.python-version - -# celery beat schedule file -celerybeat-schedule - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site -# mypy -.mypy_cache/ +# uv +.venv/ +uv.lock # vim swap files *.swp diff --git a/README.md b/README.md index e1cf54f..f548862 100644 --- a/README.md +++ b/README.md @@ -46,10 +46,10 @@ See it in action in [Codingo](https://github.com/codingo)'s video demo [here](ht ## Usage ### Setup -Several non-standard libaries are required to support threaded HTTP requests and dns lookups. You'll need to install the requirements as follows: +This project uses [uv](https://github.com/astral-sh/uv) for dependency management. Install uv, then run: ```sh -pip3 install -r ./requirements.txt +uv sync ``` ### Running @@ -62,13 +62,13 @@ Keywords are mutated automatically using strings from `enum_tools/fuzz.txt` or a Let's say you were researching "somecompany" whose website is "somecompany.io" that makes a product called "blockchaindoohickey". You could run the tool like this: ```sh -./cloud_enum.py -k somecompany -k somecompany.io -k blockchaindoohickey +uv run cloud_enum -k somecompany -k somecompany.io -k blockchaindoohickey ``` HTTP scraping and DNS lookups use 5 threads each by default. You can try increasing this, but eventually the cloud providers will rate limit you. Here is an example to increase to 10. ```sh -./cloud_enum.py -k keyword -t 10 +uv run cloud_enum -k keyword -t 10 ``` **IMPORTANT**: Some resources (Azure Containers, GCP Functions) are discovered per-region. To save time scanning, there is a "REGIONS" variable defined in `cloudenum/azure_regions.py and cloudenum/gcp_regions.py` that is set by default to use only 1 region. You may want to look at these files and edit them to be relevant to your own work. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..34cd28a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,26 @@ +[project] +name = "cloud_enum" +version = "0.8" +description = "Multi-cloud OSINT tool. Enumerate public resources in AWS, Azure, and Google Cloud." +requires-python = ">=3.10" +dependencies = [ + "dnspython>=2.8.0", + "requests>=2.34.2", + "requests-futures>=1.0.2", +] + +[project.scripts] +cloud_enum = "cloud_enum:main" + +[dependency-groups] +dev = [ + "pytest", +] + +[tool.setuptools] +py-modules = ["cloud_enum"] +packages = ["enum_tools"] + +[build-system] +requires = ["setuptools>=61"] +build-backend = "setuptools.build_meta" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 77b97fb..0000000 --- a/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -dnspython -requests -requests_futures diff --git a/setup.py b/setup.py deleted file mode 100644 index b48da54..0000000 --- a/setup.py +++ /dev/null @@ -1,26 +0,0 @@ -from setuptools import setup - -setup( - name='cloud_enum', - description='Multi-cloud OSINT tool. Enumerate public resources in AWS, Azure, and Google Cloud.', - author='initstring', - url='https://github.com/initstring/cloud_enum', - license='MIT', - packages=[ - 'enum_tools' - ], - py_modules=[ - 'cloud_enum' - ], - install_requires=[ - 'dnspython', - 'requests', - 'requests_futures' - ], - python_requires='>=3.0.0', - entry_points={ - 'console_scripts': [ - 'cloud_enum = cloud_enum:main' - ] - } -)