From b58cc9fe03eff097dc7a80fcd8c5e7eec8046cfc Mon Sep 17 00:00:00 2001 From: meleksabit Date: Thu, 29 Aug 2024 02:19:45 +0300 Subject: [PATCH 01/35] add devsecops_pipeline.py --- devsecops_pipeline.py | 64 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 devsecops_pipeline.py diff --git a/devsecops_pipeline.py b/devsecops_pipeline.py new file mode 100644 index 0000000..045a782 --- /dev/null +++ b/devsecops_pipeline.py @@ -0,0 +1,64 @@ +import os +import subprocess +import sys + +# Helper function to run shell commands +def run_command(command, cwd=None): + result = subprocess.run(command, shell=True, cwd=cwd, text=True, capture_output=True) + if result.returncode != 0: + print(f"Error: Command '{command}' failed with exit code {result.returncode}") + print(result.stdout) + print(result.stderr) + sys.exit(result.returncode) + return result.stdout + +# Static Code Analysis and Code Coverage (using SonarQube) +def run_sonarqube_analysis(path): + print("Running SonarQube for static code analysis and code coverage...") + run_command(f"sonar-scanner -Dsonar.projectBaseDir={path}") + +# Dependency Checking (using Safety) +def run_safety(): + print("Running Safety for dependency checking...") + run_command("safety check --full-report") + +# Secret Scanning (using TruffleHog) +def run_trufflehog(path): + print("Running TruffleHog for secret scanning...") + run_command(f"trufflehog {path}") + +# Infrastructure as Code Scanning (using Terraform and Snyk) +def run_terraform_scan(path): + print("Running Snyk for Terraform IaC scanning...") + run_command(f"snyk iac test {path}") + +# Code Coverage and Linting (using Pylint) +def run_pylint(path): + print("Running Pylint for code linting...") + run_command(f"pylint {path}") + +# Main function to orchestrate the DevSecOps pipeline +def main(): + project_path = os.getcwd() + + # Static Analysis and Code Coverage with SonarQube + run_sonarqube_analysis(project_path) + + # Dependency Checking + run_safety() + + # Secret Scanning + run_trufflehog(project_path) + + # Terraform IaC Scanning + terraform_path = os.path.join(project_path, 'terraform') + if os.path.exists(terraform_path): + run_terraform_scan(terraform_path) + + # Linting + run_pylint(project_path) + + print("DevSecOps pipeline completed successfully!") + +if __name__ == "__main__": + main() From 8c039b1b89b344a308ad062fe1ecce6ee2ccaf2d Mon Sep 17 00:00:00 2001 From: meleksabit Date: Thu, 29 Aug 2024 03:42:33 +0300 Subject: [PATCH 02/35] add devsecops-pipeline workflow --- .github/workflows/devsecops-pipeline.yml | 30 ++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/devsecops-pipeline.yml diff --git a/.github/workflows/devsecops-pipeline.yml b/.github/workflows/devsecops-pipeline.yml new file mode 100644 index 0000000..c8dd3ac --- /dev/null +++ b/.github/workflows/devsecops-pipeline.yml @@ -0,0 +1,30 @@ +name: DevSecOps Pipeline + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + security-checks: + runs-on: ubuntu-latest + + steps: + - name: Checkout Code + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + + - name: Install Dependencies + run: | + python -m pip install --upgrade pip + pip install safety truffleHog sonar-scanner + + - name: Run DevSecOps Pipeline + run: python devsecops_pipeline.py From d3e5daffd2a45a75875b9364638c80375c425ffb Mon Sep 17 00:00:00 2001 From: meleksabit Date: Thu, 29 Aug 2024 03:51:51 +0300 Subject: [PATCH 03/35] replace sonarqube with bandit --- .github/workflows/devsecops-pipeline.yml | 2 +- devsecops_pipeline.py | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/devsecops-pipeline.yml b/.github/workflows/devsecops-pipeline.yml index c8dd3ac..6d1d69a 100644 --- a/.github/workflows/devsecops-pipeline.yml +++ b/.github/workflows/devsecops-pipeline.yml @@ -24,7 +24,7 @@ jobs: - name: Install Dependencies run: | python -m pip install --upgrade pip - pip install safety truffleHog sonar-scanner + pip install bandit safety truffleHog pylint - name: Run DevSecOps Pipeline run: python devsecops_pipeline.py diff --git a/devsecops_pipeline.py b/devsecops_pipeline.py index 045a782..d12a21c 100644 --- a/devsecops_pipeline.py +++ b/devsecops_pipeline.py @@ -12,10 +12,10 @@ def run_command(command, cwd=None): sys.exit(result.returncode) return result.stdout -# Static Code Analysis and Code Coverage (using SonarQube) -def run_sonarqube_analysis(path): - print("Running SonarQube for static code analysis and code coverage...") - run_command(f"sonar-scanner -Dsonar.projectBaseDir={path}") +# Static Code Analysis (using Bandit) +def run_bandit(path): + print("Running Bandit for static code analysis...") + run_command(f"bandit -r {path}") # Dependency Checking (using Safety) def run_safety(): @@ -41,8 +41,8 @@ def run_pylint(path): def main(): project_path = os.getcwd() - # Static Analysis and Code Coverage with SonarQube - run_sonarqube_analysis(project_path) + # Static Analysis + run_bandit(project_path) # Dependency Checking run_safety() @@ -54,7 +54,7 @@ def main(): terraform_path = os.path.join(project_path, 'terraform') if os.path.exists(terraform_path): run_terraform_scan(terraform_path) - + # Linting run_pylint(project_path) From bfc3f90ac7bf7fa5211525536ddf52fc8390f1c9 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Fri, 6 Sep 2024 02:30:59 +0300 Subject: [PATCH 04/35] edit cron job --- .github/workflows/codeql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 4688f97..e8c440e 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -17,7 +17,7 @@ on: pull_request: branches: [ "main" ] schedule: - - cron: '39 23 * * 1' + - cron: '33 23 * * 1' jobs: analyze: From 80ec32ca2267b8fcc0e178a8e4c2968a51043a20 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Sun, 8 Sep 2024 03:08:46 +0300 Subject: [PATCH 05/35] add comment for the cron job --- .github/workflows/codeql.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index e8c440e..cddd97a 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -17,7 +17,7 @@ on: pull_request: branches: [ "main" ] schedule: - - cron: '33 23 * * 1' + - cron: '33 23 * * 1' # CodeQL will run every Monday at 23:33 UTC jobs: analyze: From b57b3ca35c57658ec6c051091ed02e009bf2f552 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Wed, 11 Sep 2024 16:51:31 +0300 Subject: [PATCH 06/35] add Git Guardian workflow --- .github/workflows/gitguardian.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/gitguardian.yml diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml new file mode 100644 index 0000000..13696eb --- /dev/null +++ b/.github/workflows/gitguardian.yml @@ -0,0 +1,23 @@ +name: GitGuardian Scan + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + ggshield: + name: GitGuardian Secret Detection + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Run GitGuardian ggshield + uses: GitGuardian/ggshield-action@v1 + with: + api-key: ${{ secrets.GITGUARDIAN_API_KEY }} From 0e76968b353db66d604c8857f515661d44905a1b Mon Sep 17 00:00:00 2001 From: meleksabit Date: Wed, 11 Sep 2024 17:01:09 +0300 Subject: [PATCH 07/35] edit Git Guardian workflow --- .github/workflows/gitguardian.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index 13696eb..be38e87 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -2,7 +2,7 @@ name: GitGuardian Scan on: push: - branches: + branches: - main pull_request: branches: @@ -10,14 +10,15 @@ on: jobs: ggshield: - name: GitGuardian Secret Detection + name: GitGuardian Scan runs-on: ubuntu-latest - steps: - name: Checkout code uses: actions/checkout@v3 - - name: Run GitGuardian ggshield + - name: Run GitGuardian ggshield scan uses: GitGuardian/ggshield-action@v1 with: - api-key: ${{ secrets.GITGUARDIAN_API_KEY }} + args: scan path --exit-zero . + env: + GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} From b96d528921912a79b52cab6340786a55e235c2ea Mon Sep 17 00:00:00 2001 From: meleksabit Date: Wed, 11 Sep 2024 17:08:07 +0300 Subject: [PATCH 08/35] edit Git Guardian workflow --- .github/workflows/gitguardian.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index be38e87..fdae2bb 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -2,7 +2,7 @@ name: GitGuardian Scan on: push: - branches: + branches: - main pull_request: branches: @@ -19,6 +19,6 @@ jobs: - name: Run GitGuardian ggshield scan uses: GitGuardian/ggshield-action@v1 with: - args: scan path --exit-zero . + args: secret scan path --exit-zero . env: GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} From da6d3fde5d1436e78e30d732e35d63a79738e34a Mon Sep 17 00:00:00 2001 From: meleksabit Date: Wed, 11 Sep 2024 17:10:09 +0300 Subject: [PATCH 09/35] edit Git Guardian workflow --- .github/workflows/gitguardian.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index fdae2bb..ec8a9b5 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -19,6 +19,6 @@ jobs: - name: Run GitGuardian ggshield scan uses: GitGuardian/ggshield-action@v1 with: - args: secret scan path --exit-zero . + args: ggshield secret scan path --exit-zero . env: GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} From e436b3fac85786f43e2567a6086c6567082dce73 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Wed, 11 Sep 2024 17:12:14 +0300 Subject: [PATCH 10/35] edit Git Guardian workflow --- .github/workflows/gitguardian.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index ec8a9b5..6d45a70 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -19,6 +19,6 @@ jobs: - name: Run GitGuardian ggshield scan uses: GitGuardian/ggshield-action@v1 with: - args: ggshield secret scan path --exit-zero . + args: ggshield secret scan -h env: GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} From caf63b1091835da3421ad6a9b3d6cc3bb4516cca Mon Sep 17 00:00:00 2001 From: meleksabit Date: Wed, 11 Sep 2024 17:15:16 +0300 Subject: [PATCH 11/35] edit Git Guardian workflow --- .github/workflows/gitguardian.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index 6d45a70..37b542a 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -19,6 +19,6 @@ jobs: - name: Run GitGuardian ggshield scan uses: GitGuardian/ggshield-action@v1 with: - args: ggshield secret scan -h + args: path --exit-zero . env: GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} From 54081f3be62bfbcb2f5e7c12a8eb2799b9c408a5 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Wed, 11 Sep 2024 17:20:26 +0300 Subject: [PATCH 12/35] edit Git Guardian workflow --- .github/workflows/gitguardian.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index 37b542a..264a1f3 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -19,6 +19,6 @@ jobs: - name: Run GitGuardian ggshield scan uses: GitGuardian/ggshield-action@v1 with: - args: path --exit-zero . + args: path --exit-zero / env: GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} From 6a283a0e02a4bdf234042997ba138e4d8393e72e Mon Sep 17 00:00:00 2001 From: meleksabit Date: Wed, 11 Sep 2024 17:28:43 +0300 Subject: [PATCH 13/35] edit Git Guardian workflow --- .github/workflows/gitguardian.yml | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index 264a1f3..c578c55 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -1,24 +1,22 @@ -name: GitGuardian Scan +name: GitGuardian scan -on: - push: - branches: - - main - pull_request: - branches: - - main +on: [push, pull_request] jobs: - ggshield: - name: GitGuardian Scan + scanning: + name: GitGuardian scan runs-on: ubuntu-latest steps: - - name: Checkout code + - name: Checkout uses: actions/checkout@v3 - - - name: Run GitGuardian ggshield scan - uses: GitGuardian/ggshield-action@v1 with: - args: path --exit-zero / + fetch-depth: 0 # fetch all history so multiple commits can be scanned + - name: GitGuardian scan + uses: GitGuardian/ggshield/actions/secret@v1.30.1 env: + GITHUB_PUSH_BEFORE_SHA: ${{ github.event.before }} + GITHUB_PUSH_BASE_SHA: ${{ github.event.base }} + GITHUB_PULL_BASE_SHA: ${{ github.event.pull_request.base.sha }} + GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} + \ No newline at end of file From 1392fd14e8e01a32780601d6571dfcd4a4666b07 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Wed, 11 Sep 2024 17:33:19 +0300 Subject: [PATCH 14/35] edit Git Guardian workflow --- .github/workflows/gitguardian.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index c578c55..268fcf7 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -12,11 +12,10 @@ jobs: with: fetch-depth: 0 # fetch all history so multiple commits can be scanned - name: GitGuardian scan - uses: GitGuardian/ggshield/actions/secret@v1.30.1 + uses: GitGuardian/ggshield/actions/secret@v1.31.1 env: GITHUB_PUSH_BEFORE_SHA: ${{ github.event.before }} GITHUB_PUSH_BASE_SHA: ${{ github.event.base }} GITHUB_PULL_BASE_SHA: ${{ github.event.pull_request.base.sha }} GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }} - \ No newline at end of file From 7b1f5a0144ded3747b59688bc788d2b4db043972 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Wed, 11 Sep 2024 17:35:08 +0300 Subject: [PATCH 15/35] edit Git Guardian workflow --- .github/workflows/gitguardian.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gitguardian.yml b/.github/workflows/gitguardian.yml index 268fcf7..4133189 100644 --- a/.github/workflows/gitguardian.yml +++ b/.github/workflows/gitguardian.yml @@ -12,7 +12,7 @@ jobs: with: fetch-depth: 0 # fetch all history so multiple commits can be scanned - name: GitGuardian scan - uses: GitGuardian/ggshield/actions/secret@v1.31.1 + uses: GitGuardian/ggshield/actions/secret@v1.31.0 env: GITHUB_PUSH_BEFORE_SHA: ${{ github.event.before }} GITHUB_PUSH_BASE_SHA: ${{ github.event.base }} From b047d2fc8a5846e891b182c813d22bf4c3aa0c43 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Sat, 14 Sep 2024 22:31:39 +0300 Subject: [PATCH 16/35] edit README file --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bd4cc3d..b83edb5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +# $\color{Cerulean}{Python\}$ $\color{Goldenrod}{Examples\}$ [![CodeQL](https://github.com/meleksabit/My-Python-Examples/actions/workflows/codeql.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/codeql.yml) [![Bandit](https://github.com/meleksabit/My-Python-Examples/actions/workflows/bandit.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/bandit.yml) [![DevSecOps Pipeline](https://github.com/meleksabit/My-Python-Examples/actions/workflows/devsecops-pipeline.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/devsecops-pipeline.yml) From aa79a35629c7e4c3d285e34ac530298bbe528732 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Thu, 26 Sep 2024 14:53:40 +0300 Subject: [PATCH 17/35] edit DevSecOps pipeline --- .github/workflows/devsecops-pipeline.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/devsecops-pipeline.yml b/.github/workflows/devsecops-pipeline.yml index 6d1d69a..60a17ec 100644 --- a/.github/workflows/devsecops-pipeline.yml +++ b/.github/workflows/devsecops-pipeline.yml @@ -14,10 +14,10 @@ jobs: steps: - name: Checkout Code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: '3.x' From 0bf5315a158f9443e24543c059c3673bec01a571 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Mon, 7 Oct 2024 03:43:40 +0300 Subject: [PATCH 18/35] edit release badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 69af1b6..6b94149 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![CodeQL](https://github.com/meleksabit/My-Python-Examples/actions/workflows/codeql.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/codeql.yml) [![Bandit](https://github.com/meleksabit/My-Python-Examples/actions/workflows/bandit.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/bandit.yml) [![DevSecOps Pipeline](https://github.com/meleksabit/My-Python-Examples/actions/workflows/devsecops-pipeline.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/devsecops-pipeline.yml) -![GitHub Release](https://img.shields.io/github/v/release/meleksabit/My-Python-Examples) +[![GitHub Release](https://img.shields.io/github/v/release/meleksabit/My-Python-Examples)](https://github.com/meleksabit/My-Python-Examples/releases) # 🏎️Tesla Example: ![Python](https://user-images.githubusercontent.com/32045473/153525858-85772918-62df-4f29-9316-ccc946eb5eab.png) ![Python2](https://user-images.githubusercontent.com/32045473/153525899-d11d6922-075d-416e-b88a-1c14d4f62815.png) From a297c87a5ba5721d6ce33cbad025f81f072f755c Mon Sep 17 00:00:00 2001 From: meleksabit Date: Tue, 8 Oct 2024 03:55:29 +0300 Subject: [PATCH 19/35] add .gitignore file --- .gitignore | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c6f9a44..544d019 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,114 @@ -.vscode/settings.json +# Byte-compiled / optimized / DLL files +__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/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# Jupyter Notebook +.ipynb_checkpoints + +# PyCharm +.idea/ + +# VSCode +.vscode/ + +# MacOS specific files +.DS_Store + +# Windows specific files +Thumbs.db +ehthumbs.db +Desktop.ini + +# Virtual environments +venv/ +ENV/ +env/ +.venv/ +env.bak/ +env.bak.tar.gz + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ From 73401cd91f525863ae8209671836ff1a34706365 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Mon, 18 Nov 2024 01:17:07 +0200 Subject: [PATCH 20/35] add PR Title Linter --- .github/workflows/pr-title-linter.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/pr-title-linter.yml diff --git a/.github/workflows/pr-title-linter.yml b/.github/workflows/pr-title-linter.yml new file mode 100644 index 0000000..df5cab1 --- /dev/null +++ b/.github/workflows/pr-title-linter.yml @@ -0,0 +1,25 @@ +name: PR Title Check + +on: + pull_request: + types: [opened, edited] + +jobs: + lint-pr-title: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Check PR Title + uses: actions/github-script@v7.0.1 + with: + script: | + const title = context.payload.pull_request.title; + const regex = /^(feat|fix|chore|docs|style|refactor|perf|test): .+/; + if (!regex.test(title)) { + core.setFailed(`Invalid PR title: "${title}". Titles must match the pattern "type: description" (e.g., "feat: Add new feature").`); + } else { + console.log(`PR title "${title}" is valid.`); + } From e95ba0b03f0f4256dcc838caeeafda785488a34b Mon Sep 17 00:00:00 2001 From: meleksabit Date: Mon, 18 Nov 2024 01:20:21 +0200 Subject: [PATCH 21/35] add status badge for PR Linter --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 6b94149..24b26ac 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,7 @@ [![GitGuardian scan](https://github.com/meleksabit/My-Python-Examples/actions/workflows/gitguardian.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/gitguardian.yml) [![CodeQL](https://github.com/meleksabit/My-Python-Examples/actions/workflows/codeql.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/codeql.yml) [![Bandit](https://github.com/meleksabit/My-Python-Examples/actions/workflows/bandit.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/bandit.yml) -[![DevSecOps Pipeline](https://github.com/meleksabit/My-Python-Examples/actions/workflows/devsecops-pipeline.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/devsecops-pipeline.yml) -[![GitHub Release](https://img.shields.io/github/v/release/meleksabit/My-Python-Examples)](https://github.com/meleksabit/My-Python-Examples/releases) +[![DevSecOps Pipeline](https://github.com/meleksabit/My-Python-Examples/actions/workflows/devsecops-pipeline.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/devsecops-pipeline.yml) [![PR Title Check](https://github.com/meleksabit/My-Python-Examples/actions/workflows/pr-title-linter.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/pr-title-linter.yml) [![GitHub Release](https://img.shields.io/github/v/release/meleksabit/My-Python-Examples)](https://github.com/meleksabit/My-Python-Examples/releases) # 🏎️Tesla Example: ![Python](https://user-images.githubusercontent.com/32045473/153525858-85772918-62df-4f29-9316-ccc946eb5eab.png) ![Python2](https://user-images.githubusercontent.com/32045473/153525899-d11d6922-075d-416e-b88a-1c14d4f62815.png) From 0f06241d6d19556e9a4027ac31b196eaaeaa8b07 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Thu, 28 Nov 2024 23:31:50 +0200 Subject: [PATCH 22/35] add SonarCloud implementation --- .github/workflows/sonarcloud.yml | 30 ++++++++++++++++++++++++++++++ sonar-project.properties | 10 ++++++++++ 2 files changed, 40 insertions(+) create mode 100644 .github/workflows/sonarcloud.yml create mode 100644 sonar-project.properties diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml new file mode 100644 index 0000000..122d834 --- /dev/null +++ b/.github/workflows/sonarcloud.yml @@ -0,0 +1,30 @@ +name: SonarCloud Analysis + +on: + # Trigger analysis when pushing to your main branches, and when creating a pull request. + push: + branches: + - main + - dev + pull_request: + types: [opened, synchronize, reopened] + +jobs: + sonar-scan: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + java-package: 'jdk' + + - name: SonarCloud Scan + uses: sonarsource/sonarcloud-github-action@v3 # Ex: v2.1.0, See the latest version at https://github.com/marketplace/actions/sonarcloud-scan + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..7a319aa --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,10 @@ +# Required project settings +sonar.organization=meleksabit +sonar.projectKey=meleksabit_My-BASH-Examples +sonar.projectName=My-BASH-Examples +sonar.host.url=https://sonarcloud.io + +# Optional configuration +sonar.sources=. +sonar.language=python # (or your project's primary language) +sonar.sourceEncoding=UTF-8 From bfe67f2f302af27b9316d6b3b222b8a70ec03216 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Thu, 28 Nov 2024 23:34:30 +0200 Subject: [PATCH 23/35] edit sonar-project.properties --- sonar-project.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonar-project.properties b/sonar-project.properties index 7a319aa..b97a7fc 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,7 +1,7 @@ # Required project settings sonar.organization=meleksabit -sonar.projectKey=meleksabit_My-BASH-Examples -sonar.projectName=My-BASH-Examples +sonar.projectKey=meleksabit_My-Python-Examples +sonar.projectName=My-Python-Examples sonar.host.url=https://sonarcloud.io # Optional configuration From eadc76df3bb3595c98efe1861a6852ad33206fc5 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Thu, 28 Nov 2024 23:37:20 +0200 Subject: [PATCH 24/35] add SonarCloud badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 24b26ac..5abb749 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # $\color{Cerulean}{Python\}$ $\color{Goldenrod}{Examples\}$ -[![GitGuardian scan](https://github.com/meleksabit/My-Python-Examples/actions/workflows/gitguardian.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/gitguardian.yml) +[![SonarCloud Analysis](https://github.com/meleksabit/My-Python-Examples/actions/workflows/sonarcloud.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/sonarcloud.yml) [![GitGuardian scan](https://github.com/meleksabit/My-Python-Examples/actions/workflows/gitguardian.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/gitguardian.yml) [![CodeQL](https://github.com/meleksabit/My-Python-Examples/actions/workflows/codeql.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/codeql.yml) [![Bandit](https://github.com/meleksabit/My-Python-Examples/actions/workflows/bandit.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/bandit.yml) [![DevSecOps Pipeline](https://github.com/meleksabit/My-Python-Examples/actions/workflows/devsecops-pipeline.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/devsecops-pipeline.yml) [![PR Title Check](https://github.com/meleksabit/My-Python-Examples/actions/workflows/pr-title-linter.yml/badge.svg)](https://github.com/meleksabit/My-Python-Examples/actions/workflows/pr-title-linter.yml) [![GitHub Release](https://img.shields.io/github/v/release/meleksabit/My-Python-Examples)](https://github.com/meleksabit/My-Python-Examples/releases) From 144bce5e695456d71cd47b1c50aaa86ae9da50fb Mon Sep 17 00:00:00 2001 From: meleksabit Date: Fri, 29 Nov 2024 00:33:47 +0200 Subject: [PATCH 25/35] address suggestions from SonarCloud --- Tesla.py | 4 ++-- find_duplicates.py | 7 ++----- performance_decorator.py | 13 ++++++------- strong_passgen_for_prod.py | 40 ++++++++++++++++++-------------------- 4 files changed, 29 insertions(+), 35 deletions(-) diff --git a/Tesla.py b/Tesla.py index 7dedeef..7e856a0 100644 --- a/Tesla.py +++ b/Tesla.py @@ -1,5 +1,5 @@ # Parameters and Arguments example -def checkDriverAge(age=0): +def check_driver_age(age=0): if int(age) < 18: print("Sorry, you are too young to drive this car. Powering off 😟") elif int(age) > 18: @@ -8,4 +8,4 @@ def checkDriverAge(age=0): print("Congratulations on your first year of driving. Enjoy the ride! 🚀") -checkDriverAge() +check_driver_age() diff --git a/find_duplicates.py b/find_duplicates.py index b441a87..e36c8f6 100644 --- a/find_duplicates.py +++ b/find_duplicates.py @@ -1,10 +1,7 @@ # Shows the duplicate strings my_list = ['a', 'b', 'c', 'd', 'd', 'm', 'm', 'n', 'o', 'z', 'z'] - duplicates = [] for value in my_list: - if my_list.count(value) > 1: - if value not in duplicates: - duplicates.append(value) - + if my_list.count(value) > 1 and value not in duplicates: + duplicates.append(value) print(duplicates) diff --git a/performance_decorator.py b/performance_decorator.py index d97d5c4..1f654de 100644 --- a/performance_decorator.py +++ b/performance_decorator.py @@ -1,21 +1,20 @@ -# Performance decorator from time import time - +# Decorator to measure performance def performance(fn): def wrapper(*args, **kwargs): t1 = time() result = fn(*args, **kwargs) t2 = time() - print(f'took {t2-t1} seconds') + print(f'took {t2 - t1} seconds') return result return wrapper - @performance def long_time(): - for i in range(10000000): - i*5 - + """Benchmarking function to test performance.""" + for _ in range(10_000_000): + pass # Empty loop for benchmarking the decorator +# Execute the benchmark long_time() diff --git a/strong_passgen_for_prod.py b/strong_passgen_for_prod.py index a70e405..7a772ef 100644 --- a/strong_passgen_for_prod.py +++ b/strong_passgen_for_prod.py @@ -1,42 +1,36 @@ -# import modules import string import random -# store all characters in lists +# Store all characters in lists s1 = list(string.ascii_lowercase) s2 = list(string.ascii_uppercase) s3 = list(string.digits) s4 = list(string.punctuation) -# Ask user about the number of characters -user_input = input("How many characters do you want in your password? ") - -# check this input is it number? is it more than 8? +# Prompt the user for the number of characters in the password while True: try: + user_input = input("How many characters do you want in your password? ") characters_number = int(user_input) if characters_number < 8: - print("Your password must be at least 8 characters long") - user_input = input("Please, Enter your number again: ") + print("Your password must be at least 8 characters long.") else: break - except: - print("Please, Enter a number") - user_input = input("Please, Enter your number again: ") + except ValueError: # Catch invalid inputs that cannot be converted to an integer + print("Invalid input. Please enter a valid number.") -# shuffle all lists +# Shuffle all character lists random.shuffle(s1) random.shuffle(s2) random.shuffle(s3) random.shuffle(s4) -# calculate 30% & 20% of number of characters -part1 = round(characters_number * (30 / 100)) -part2 = round(characters_number * (20 / 100)) +# Calculate portions of the password +part1 = round(characters_number * 0.3) # 30% lowercase and uppercase letters +part2 = round(characters_number * 0.2) # 20% digits and punctuation -# generation of the password (60% letters and 40% digits & punctuations) +# Generate the password components result = [] - for x in range(part1): result.append(s1[x]) result.append(s2[x]) @@ -45,9 +39,13 @@ result.append(s3[x]) result.append(s4[x]) -# shuffle the result -random.shuffle(result) +# Ensure the result has the exact number of characters requested +while len(result) < characters_number: + result.append(random.choice(s1 + s2 + s3 + s4)) -# join the result +# Shuffle the final password and join into a string +random.shuffle(result) password = "".join(result) -print("Strong Password: ", password) + +# Output the generated password +print("Strong Password:", password) From d86fb9ed5e25d585187204a79b14961c32e088fe Mon Sep 17 00:00:00 2001 From: meleksabit Date: Fri, 29 Nov 2024 00:50:18 +0200 Subject: [PATCH 26/35] add secrets module in strong_passgen_for_prod.py --- strong_passgen_for_prod.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/strong_passgen_for_prod.py b/strong_passgen_for_prod.py index 7a772ef..e7da3b3 100644 --- a/strong_passgen_for_prod.py +++ b/strong_passgen_for_prod.py @@ -1,5 +1,5 @@ import string -import random +import secrets # Store all characters in lists s1 = list(string.ascii_lowercase) @@ -19,11 +19,11 @@ except ValueError: # Catch invalid inputs that cannot be converted to an integer print("Invalid input. Please enter a valid number.") -# Shuffle all character lists -random.shuffle(s1) -random.shuffle(s2) -random.shuffle(s3) -random.shuffle(s4) +# Shuffle all character lists securely +s1 = secrets.SystemRandom().sample(s1, len(s1)) +s2 = secrets.SystemRandom().sample(s2, len(s2)) +s3 = secrets.SystemRandom().sample(s3, len(s3)) +s4 = secrets.SystemRandom().sample(s4, len(s4)) # Calculate portions of the password part1 = round(characters_number * 0.3) # 30% lowercase and uppercase letters @@ -32,19 +32,19 @@ # Generate the password components result = [] for x in range(part1): - result.append(s1[x]) - result.append(s2[x]) + result.append(secrets.choice(s1)) + result.append(secrets.choice(s2)) for x in range(part2): - result.append(s3[x]) - result.append(s4[x]) + result.append(secrets.choice(s3)) + result.append(secrets.choice(s4)) # Ensure the result has the exact number of characters requested while len(result) < characters_number: - result.append(random.choice(s1 + s2 + s3 + s4)) + result.append(secrets.choice(s1 + s2 + s3 + s4)) -# Shuffle the final password and join into a string -random.shuffle(result) +# Shuffle the final password securely and join into a string +secrets.SystemRandom().shuffle(result) password = "".join(result) # Output the generated password From fb607b96b49d72c1cd63aff86973810f3379e7a0 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Fri, 29 Nov 2024 01:02:21 +0200 Subject: [PATCH 27/35] edit strong_passgen_for_prod.py --- strong_passgen_for_prod.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/strong_passgen_for_prod.py b/strong_passgen_for_prod.py index e7da3b3..8e36cca 100644 --- a/strong_passgen_for_prod.py +++ b/strong_passgen_for_prod.py @@ -19,7 +19,8 @@ except ValueError: # Catch invalid inputs that cannot be converted to an integer print("Invalid input. Please enter a valid number.") -# Shuffle all character lists securely +# Using secrets.SystemRandom().sample() ensures cryptographically secure shuffling +# This is necessary for secure password generation as it avoids predictable patterns s1 = secrets.SystemRandom().sample(s1, len(s1)) s2 = secrets.SystemRandom().sample(s2, len(s2)) s3 = secrets.SystemRandom().sample(s3, len(s3)) From 22ee82d59dd48691e507d39c3a2cc1861d7c4090 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Fri, 29 Nov 2024 01:13:44 +0200 Subject: [PATCH 28/35] edit strong_passgen_for_prod.py --- strong_passgen_for_prod.py | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/strong_passgen_for_prod.py b/strong_passgen_for_prod.py index 8e36cca..b33cf7e 100644 --- a/strong_passgen_for_prod.py +++ b/strong_passgen_for_prod.py @@ -1,4 +1,5 @@ import string +import random import secrets # Store all characters in lists @@ -7,20 +8,23 @@ s3 = list(string.digits) s4 = list(string.punctuation) -# Prompt the user for the number of characters in the password +# Ask user about the number of characters +user_input = input("How many characters do you want in your password? ") + +# Check if the input is a valid number and greater than or equal to 8 while True: try: - user_input = input("How many characters do you want in your password? ") characters_number = int(user_input) if characters_number < 8: print("Your password must be at least 8 characters long.") + user_input = input("Please, enter your number again: ") else: break - except ValueError: # Catch invalid inputs that cannot be converted to an integer + except ValueError: # Catch invalid inputs print("Invalid input. Please enter a valid number.") + user_input = input("Please, enter your number again: ") -# Using secrets.SystemRandom().sample() ensures cryptographically secure shuffling -# This is necessary for secure password generation as it avoids predictable patterns +# Securely shuffle all character lists s1 = secrets.SystemRandom().sample(s1, len(s1)) s2 = secrets.SystemRandom().sample(s2, len(s2)) s3 = secrets.SystemRandom().sample(s3, len(s3)) @@ -28,25 +32,29 @@ # Calculate portions of the password part1 = round(characters_number * 0.3) # 30% lowercase and uppercase letters -part2 = round(characters_number * 0.2) # 20% digits and punctuation +part2 = round(characters_number * 0.2) # 20% digits and punctuations -# Generate the password components +# Generate the password result = [] for x in range(part1): - result.append(secrets.choice(s1)) - result.append(secrets.choice(s2)) - + result.append(s1[x]) + result.append(s2[x]) for x in range(part2): - result.append(secrets.choice(s3)) - result.append(secrets.choice(s4)) + result.append(s3[x]) + result.append(s4[x]) # Ensure the result has the exact number of characters requested while len(result) < characters_number: result.append(secrets.choice(s1 + s2 + s3 + s4)) -# Shuffle the final password securely and join into a string +# Shuffle the final password securely secrets.SystemRandom().shuffle(result) + +# Join the result to form the password password = "".join(result) -# Output the generated password -print("Strong Password:", password) +# Mask the password except for the last 4 characters +masked_password = '*' * (len(password) - 4) + password[-4:] + +# Output the masked password +print("Generated password:", masked_password) From e2f3b4238657ea0eb5689636f58891b3ed9f0be6 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Fri, 29 Nov 2024 01:16:51 +0200 Subject: [PATCH 29/35] edit strong_passgen_for_prod.py --- strong_passgen_for_prod.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/strong_passgen_for_prod.py b/strong_passgen_for_prod.py index b33cf7e..bdd00f3 100644 --- a/strong_passgen_for_prod.py +++ b/strong_passgen_for_prod.py @@ -48,7 +48,7 @@ result.append(secrets.choice(s1 + s2 + s3 + s4)) # Shuffle the final password securely -secrets.SystemRandom().shuffle(result) +secrets.SystemRandom().shuffle(result) # Cryptographically secure shuffling # Join the result to form the password password = "".join(result) From 74c22cd0374719a2830c1e9acc40e4df7f270e7b Mon Sep 17 00:00:00 2001 From: meleksabit Date: Fri, 29 Nov 2024 01:27:27 +0200 Subject: [PATCH 30/35] edit strong_passgen_for_prod.py --- strong_passgen_for_prod.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/strong_passgen_for_prod.py b/strong_passgen_for_prod.py index bdd00f3..435c338 100644 --- a/strong_passgen_for_prod.py +++ b/strong_passgen_for_prod.py @@ -47,8 +47,8 @@ while len(result) < characters_number: result.append(secrets.choice(s1 + s2 + s3 + s4)) -# Shuffle the final password securely -secrets.SystemRandom().shuffle(result) # Cryptographically secure shuffling +# Securely shuffle the result using a cryptographically secure PRNG. +secrets.SystemRandom().shuffle(result) # Using SystemRandom ensures secure shuffling # Join the result to form the password password = "".join(result) From 560bfae0a370699696b01270704d2cabb57f01f8 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Fri, 29 Nov 2024 01:41:21 +0200 Subject: [PATCH 31/35] edit strong_passgen_for_prod.py --- strong_passgen_for_prod.py | 51 ++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/strong_passgen_for_prod.py b/strong_passgen_for_prod.py index 435c338..0c44d15 100644 --- a/strong_passgen_for_prod.py +++ b/strong_passgen_for_prod.py @@ -1,17 +1,20 @@ import string import random import secrets +from cryptography.fernet import Fernet -# Store all characters in lists +# Step 1: Generate a secure encryption key (you should store this securely, not hardcoded here) +key = Fernet.generate_key() +cipher_suite = Fernet(key) + +# Step 2: Define all character sets for password generation s1 = list(string.ascii_lowercase) s2 = list(string.ascii_uppercase) s3 = list(string.digits) s4 = list(string.punctuation) -# Ask user about the number of characters +# Step 3: Ask user for password length user_input = input("How many characters do you want in your password? ") - -# Check if the input is a valid number and greater than or equal to 8 while True: try: characters_number = int(user_input) @@ -20,41 +23,45 @@ user_input = input("Please, enter your number again: ") else: break - except ValueError: # Catch invalid inputs + except ValueError: print("Invalid input. Please enter a valid number.") user_input = input("Please, enter your number again: ") -# Securely shuffle all character lists -s1 = secrets.SystemRandom().sample(s1, len(s1)) -s2 = secrets.SystemRandom().sample(s2, len(s2)) -s3 = secrets.SystemRandom().sample(s3, len(s3)) -s4 = secrets.SystemRandom().sample(s4, len(s4)) +# Step 4: Shuffle the character lists securely using a cryptographically secure PRNG +secrets.SystemRandom().shuffle(s1) +secrets.SystemRandom().shuffle(s2) +secrets.SystemRandom().shuffle(s3) +secrets.SystemRandom().shuffle(s4) -# Calculate portions of the password -part1 = round(characters_number * 0.3) # 30% lowercase and uppercase letters -part2 = round(characters_number * 0.2) # 20% digits and punctuations +# Step 5: Calculate the portion of characters for each list +part1 = round(characters_number * 0.30) # 30% of characters from lowercase letters +part2 = round(characters_number * 0.20) # 20% of characters from digits and punctuation -# Generate the password +# Step 6: Generate the password by appending characters from each list result = [] for x in range(part1): result.append(s1[x]) result.append(s2[x]) + for x in range(part2): result.append(s3[x]) result.append(s4[x]) -# Ensure the result has the exact number of characters requested +# Step 7: Ensure the result has the exact number of characters requested while len(result) < characters_number: result.append(secrets.choice(s1 + s2 + s3 + s4)) -# Securely shuffle the result using a cryptographically secure PRNG. -secrets.SystemRandom().shuffle(result) # Using SystemRandom ensures secure shuffling +# Step 8: Shuffle the result to avoid patterns +secrets.SystemRandom().shuffle(result) -# Join the result to form the password +# Step 9: Join the result to form the password password = "".join(result) -# Mask the password except for the last 4 characters -masked_password = '*' * (len(password) - 4) + password[-4:] +# Step 10: Encrypt the password +encrypted_password = cipher_suite.encrypt(password.encode()) + +# Step 11: Store the encrypted password securely +with open("password_storage.txt", "wb") as file: + file.write(encrypted_password) -# Output the masked password -print("Generated password:", masked_password) +print("Your password has been securely generated and encrypted.") From e4dead0e0433ab20e3b57042bff310ef2303410a Mon Sep 17 00:00:00 2001 From: meleksabit Date: Fri, 29 Nov 2024 02:02:15 +0200 Subject: [PATCH 32/35] edit strong_passgen_for_prod.py --- strong_passgen_for_prod.py | 61 ++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 35 deletions(-) diff --git a/strong_passgen_for_prod.py b/strong_passgen_for_prod.py index 0c44d15..fad0d9b 100644 --- a/strong_passgen_for_prod.py +++ b/strong_passgen_for_prod.py @@ -1,10 +1,13 @@ import string -import random import secrets from cryptography.fernet import Fernet +import os -# Step 1: Generate a secure encryption key (you should store this securely, not hardcoded here) -key = Fernet.generate_key() +# Step 1: Generate or retrieve a secure encryption key +key = os.environ.get('FERNET_KEY') +if not key: + print("Encryption key is missing.") + exit(1) cipher_suite = Fernet(key) # Step 2: Define all character sets for password generation @@ -20,48 +23,36 @@ characters_number = int(user_input) if characters_number < 8: print("Your password must be at least 8 characters long.") - user_input = input("Please, enter your number again: ") + elif characters_number > 128: + print("Your password length is too large. Please enter a reasonable number.") else: break + user_input = input("Please, enter your number again: ") except ValueError: print("Invalid input. Please enter a valid number.") user_input = input("Please, enter your number again: ") -# Step 4: Shuffle the character lists securely using a cryptographically secure PRNG -secrets.SystemRandom().shuffle(s1) -secrets.SystemRandom().shuffle(s2) -secrets.SystemRandom().shuffle(s3) -secrets.SystemRandom().shuffle(s4) - -# Step 5: Calculate the portion of characters for each list -part1 = round(characters_number * 0.30) # 30% of characters from lowercase letters -part2 = round(characters_number * 0.20) # 20% of characters from digits and punctuation - -# Step 6: Generate the password by appending characters from each list -result = [] -for x in range(part1): - result.append(s1[x]) - result.append(s2[x]) +# Step 4: Securely shuffle the character lists using secrets.SystemRandom() +s1 = secrets.SystemRandom().sample(s1, len(s1)) # Securely shuffle lowercase letters +s2 = secrets.SystemRandom().sample(s2, len(s2)) # Securely shuffle uppercase letters +s3 = secrets.SystemRandom().sample(s3, len(s3)) # Securely shuffle digits +s4 = secrets.SystemRandom().sample(s4, len(s4)) # Securely shuffle punctuation -for x in range(part2): - result.append(s3[x]) - result.append(s4[x]) +# Step 5: Create the password +all_chars = s1 + s2 + s3 + s4 +result = [secrets.choice(all_chars) for _ in range(characters_number)] -# Step 7: Ensure the result has the exact number of characters requested -while len(result) < characters_number: - result.append(secrets.choice(s1 + s2 + s3 + s4)) - -# Step 8: Shuffle the result to avoid patterns +# Step 6: Shuffle the result secrets.SystemRandom().shuffle(result) -# Step 9: Join the result to form the password +# Step 7: Join and encrypt the password password = "".join(result) - -# Step 10: Encrypt the password encrypted_password = cipher_suite.encrypt(password.encode()) -# Step 11: Store the encrypted password securely -with open("password_storage.txt", "wb") as file: - file.write(encrypted_password) - -print("Your password has been securely generated and encrypted.") +# Step 8: Store the encrypted password +try: + with open("password_storage.txt", "wb") as file: + file.write(encrypted_password) + print("Your password has been securely generated and encrypted.") +except Exception as e: + print(f"Error saving the password: {e}") From 4a27c24818de0336f51179e00ddef04286218082 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Fri, 29 Nov 2024 02:18:19 +0200 Subject: [PATCH 33/35] edit strong_passgen_for_prod.py --- strong_passgen_for_prod.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/strong_passgen_for_prod.py b/strong_passgen_for_prod.py index fad0d9b..fc63e1f 100644 --- a/strong_passgen_for_prod.py +++ b/strong_passgen_for_prod.py @@ -42,8 +42,8 @@ all_chars = s1 + s2 + s3 + s4 result = [secrets.choice(all_chars) for _ in range(characters_number)] -# Step 6: Shuffle the result -secrets.SystemRandom().shuffle(result) +# Step 6: Secure final shuffle using SystemRandom().sample +result = secrets.SystemRandom().sample(result, len(result)) # Secure final shuffle # Step 7: Join and encrypt the password password = "".join(result) From b6b5b7042b195a080e162961e1fdb9aacd55e750 Mon Sep 17 00:00:00 2001 From: meleksabit Date: Fri, 29 Nov 2024 02:44:23 +0200 Subject: [PATCH 34/35] edit strong_passgen_for_prod.py --- strong_passgen_for_prod.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/strong_passgen_for_prod.py b/strong_passgen_for_prod.py index fc63e1f..1954a7b 100644 --- a/strong_passgen_for_prod.py +++ b/strong_passgen_for_prod.py @@ -33,23 +33,25 @@ user_input = input("Please, enter your number again: ") # Step 4: Securely shuffle the character lists using secrets.SystemRandom() +# secrets.SystemRandom().sample() is appropriate here, as it uses a CSPRNG s1 = secrets.SystemRandom().sample(s1, len(s1)) # Securely shuffle lowercase letters s2 = secrets.SystemRandom().sample(s2, len(s2)) # Securely shuffle uppercase letters s3 = secrets.SystemRandom().sample(s3, len(s3)) # Securely shuffle digits s4 = secrets.SystemRandom().sample(s4, len(s4)) # Securely shuffle punctuation -# Step 5: Create the password -all_chars = s1 + s2 + s3 + s4 -result = [secrets.choice(all_chars) for _ in range(characters_number)] +# Step 5: Create the password securely using secrets.choice, which uses CSPRNG +# Use secrets.choice for selecting individual characters randomly from each list +result = [secrets.choice(s1 + s2 + s3 + s4) for _ in range(characters_number)] -# Step 6: Secure final shuffle using SystemRandom().sample +# Step 6: Final secure shuffle using secrets.SystemRandom().sample() +# Using secrets.SystemRandom().sample ensures that the shuffle is cryptographically secure result = secrets.SystemRandom().sample(result, len(result)) # Secure final shuffle # Step 7: Join and encrypt the password password = "".join(result) encrypted_password = cipher_suite.encrypt(password.encode()) -# Step 8: Store the encrypted password +# Step 8: Store the encrypted password securely try: with open("password_storage.txt", "wb") as file: file.write(encrypted_password) From da0116dc6840d87412dc7209eb794097bd67ab6f Mon Sep 17 00:00:00 2001 From: meleksabit Date: Fri, 29 Nov 2024 23:43:36 +0200 Subject: [PATCH 35/35] edit crypto_passgen_for_prod.py script --- crypto_passgen_for_prod.py | 66 ++++++++++++++++++++++++++++++++++++++ strong_passgen_for_prod.py | 60 ---------------------------------- 2 files changed, 66 insertions(+), 60 deletions(-) create mode 100644 crypto_passgen_for_prod.py delete mode 100644 strong_passgen_for_prod.py diff --git a/crypto_passgen_for_prod.py b/crypto_passgen_for_prod.py new file mode 100644 index 0000000..9afde47 --- /dev/null +++ b/crypto_passgen_for_prod.py @@ -0,0 +1,66 @@ +import string +import secrets +from cryptography.fernet import Fernet +import os + +# Step 1: Generate or retrieve a secure encryption key +key = os.environ.get('FERNET_KEY') +if not key: + print("Encryption key is missing. Please set the 'FERNET_KEY' environment variable.") + exit(1) +cipher_suite = Fernet(key) + +# Step 2: Define all character sets for password generation +s1 = list(string.ascii_lowercase) # Lowercase letters +s2 = list(string.ascii_uppercase) # Uppercase letters +s3 = list(string.digits) # Digits +s4 = list(string.punctuation) # Special characters + +# Step 3: Ask user for password length +while True: + try: + characters_number = int(input("How many characters do you want in your password? ")) + if 8 <= characters_number <= 128: + break + print("Please choose a number between 8 and 128.") + except ValueError: + print("Invalid input. Please enter a valid number.") + +# Step 4: Securely shuffle the character lists using secrets.SystemRandom() +secure_random = secrets.SystemRandom() +s1 = secure_random.sample(s1, len(s1)) # Securely shuffle lowercase letters +s2 = secure_random.sample(s2, len(s2)) # Securely shuffle uppercase letters +s3 = secure_random.sample(s3, len(s3)) # Securely shuffle digits +s4 = secure_random.sample(s4, len(s4)) # Securely shuffle punctuation + +# Step 5: Create the password +# Ensure at least one character from each set is included +result = [ + secrets.choice(s1), + secrets.choice(s2), + secrets.choice(s3), + secrets.choice(s4) +] + +# Fill the remaining slots randomly +remaining_characters = characters_number - len(result) +result.extend(secrets.choice(s1 + s2 + s3 + s4) for _ in range(remaining_characters)) + +# Secure final shuffle +result = secure_random.sample(result, len(result)) + +# Step 6: Join and encrypt the password +password = "".join(result) +encrypted_password = cipher_suite.encrypt(password.encode()) + +# Step 7: Store the encrypted password securely +try: + with open("password_storage.txt", "wb") as file: + file.write(encrypted_password) + print("Your password has been securely generated and encrypted.") + print("The encrypted password has been saved in 'password_storage.txt'.") + print("Ensure your encryption key is securely stored to decrypt the password.") +except IOError as e: + print(f"File operation failed: {e}") +except Exception as e: + print(f"An unexpected error occurred: {e}") diff --git a/strong_passgen_for_prod.py b/strong_passgen_for_prod.py deleted file mode 100644 index 1954a7b..0000000 --- a/strong_passgen_for_prod.py +++ /dev/null @@ -1,60 +0,0 @@ -import string -import secrets -from cryptography.fernet import Fernet -import os - -# Step 1: Generate or retrieve a secure encryption key -key = os.environ.get('FERNET_KEY') -if not key: - print("Encryption key is missing.") - exit(1) -cipher_suite = Fernet(key) - -# Step 2: Define all character sets for password generation -s1 = list(string.ascii_lowercase) -s2 = list(string.ascii_uppercase) -s3 = list(string.digits) -s4 = list(string.punctuation) - -# Step 3: Ask user for password length -user_input = input("How many characters do you want in your password? ") -while True: - try: - characters_number = int(user_input) - if characters_number < 8: - print("Your password must be at least 8 characters long.") - elif characters_number > 128: - print("Your password length is too large. Please enter a reasonable number.") - else: - break - user_input = input("Please, enter your number again: ") - except ValueError: - print("Invalid input. Please enter a valid number.") - user_input = input("Please, enter your number again: ") - -# Step 4: Securely shuffle the character lists using secrets.SystemRandom() -# secrets.SystemRandom().sample() is appropriate here, as it uses a CSPRNG -s1 = secrets.SystemRandom().sample(s1, len(s1)) # Securely shuffle lowercase letters -s2 = secrets.SystemRandom().sample(s2, len(s2)) # Securely shuffle uppercase letters -s3 = secrets.SystemRandom().sample(s3, len(s3)) # Securely shuffle digits -s4 = secrets.SystemRandom().sample(s4, len(s4)) # Securely shuffle punctuation - -# Step 5: Create the password securely using secrets.choice, which uses CSPRNG -# Use secrets.choice for selecting individual characters randomly from each list -result = [secrets.choice(s1 + s2 + s3 + s4) for _ in range(characters_number)] - -# Step 6: Final secure shuffle using secrets.SystemRandom().sample() -# Using secrets.SystemRandom().sample ensures that the shuffle is cryptographically secure -result = secrets.SystemRandom().sample(result, len(result)) # Secure final shuffle - -# Step 7: Join and encrypt the password -password = "".join(result) -encrypted_password = cipher_suite.encrypt(password.encode()) - -# Step 8: Store the encrypted password securely -try: - with open("password_storage.txt", "wb") as file: - file.write(encrypted_password) - print("Your password has been securely generated and encrypted.") -except Exception as e: - print(f"Error saving the password: {e}")