Security for DevOps Python¶
Overview¶
Apply secure coding defaults to automation: secrets handling, input validation, hashing/TLS basics, and dependency scanning habits that catch leaked tokens and vulnerable packages.
Ops scripts often hold the keys to production. Treat every CLI as a privileged program: validate inputs, never log secrets, pin and scan dependencies, prefer cloud IAM over static keys.
Complete Production Engineering and Configuration/Secrets first. Diagrams use Excalidraw only.
This is a core tutorial in Module 25 · Security of the REBASH Academy Python for Cloud & DevOps Engineers series — written for Cloud, DevOps, Platform, and SRE engineers.
Prerequisites¶
Required¶
Learning Objectives¶
By the end of this tutorial, you will be able to:
- List secret-management rules for CLIs and CI
- Hash data correctly (password vs integrity)
- Validate and sanitise paths/args
- Explain TLS verification for HTTP clients
- Run a simple secrets-scan pattern on a tree
- Outline dependency scanning in CI
Architecture¶
This topic’s control points and relationships are shown below.
Theory¶
What it is¶
Security for DevOps Python is the set of habits that keep automation from becoming an attack path: how you store secrets, verify Transport Layer Security (TLS), hash artefacts, avoid injection via subprocess, and trust your dependency supply chain. It is not a cryptography course — it is operational hygiene for scripts that hold cloud keys, talk to clusters, and run in Continuous Integration (CI).
Why it matters¶
A leaked token in git history or a log line can open every account the bot can touch. shell=True with untrusted input is a classic remote execution bug. Typosquat packages on the Python Package Index (PyPI) have targeted DevOps tooling specifically. Treating security as “someone else’s job” means your inventory script becomes the breach.
How it works¶
Secrets live in the environment, a secret manager, or CI secret stores — never in the repo. Prefer short-lived credentials from instance roles or OpenID Connect (OIDC) federation. Redact tokens in logs and exception messages; avoid placing secrets on the command line (shell history and process lists). Integrity uses hashlib for file digests; password storage needs a dedicated key-derivation function (argon2/bcrypt), not raw SHA. In transit, verify TLS certificates. At rest, use platform Key Management Service (KMS), age, or SOPS for encrypted files. Supply chain: pin dependencies, review lockfile diffs, and run pip audit / OSV scanners in CI.
Key concepts and comparisons¶
| Goal | Tooling |
|---|---|
| File integrity | hashlib.sha256 |
| Password storage | argon2 / bcrypt — not raw SHA |
| In transit | TLS with verification |
| At rest | KMS / age / SOPS |
| Authz for APIs | Least-privilege IAM / RBAC tokens |
| Practice | Do | Avoid |
|---|---|---|
| Secrets | Env / manager / CI | Git, Docker layers, argv |
| Subprocess | Argument lists | shell=True + user input |
| Paths | Confine under a root | Open any absolute path from input |
| Auth missing | Fail closed | Silent anonymous “success” |
Common pitfalls¶
- Printing
os.environor full HTTP headers in debug mode. - Disabling TLS verify “temporarily” and shipping it.
- Committing
.envor kubeconfig with tokens. - Installing packages by approximate name (typosquatting).
- Granting admin cloud roles to a CI job that only needs
describe/list.
Hands-on Lab¶
Focus: practise the core workflow for Security for DevOps Python
mkdir -p ~/rebash-python/module-25
cd ~/rebash-python/module-25
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
Step 1 – Hash a file for integrity¶
cd ~/rebash-python/module-25
source .venv/bin/activate
echo 'payload' > artefact.txt
python - <<'PY'
import hashlib
from pathlib import Path
data = Path("artefact.txt").read_bytes()
print(hashlib.sha256(data).hexdigest())
PY
Step 2 – Tiny secrets scanner¶
mkdir -p sample_repo
cat > sample_repo/leak.env << 'EOF'
# pretend bad commit
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
EOF
cat > scan_secrets.py << 'EOF'
#!/usr/bin/env python3
from __future__ import annotations
import re
import sys
from pathlib import Path
PATTERNS = [
re.compile(r"AWS_SECRET_ACCESS_KEY\s*=\s*\S+"),
re.compile(r"AKIA[0-9A-Z]{16}"),
re.compile(r"BEGIN (RSA |OPENSSH )?PRIVATE KEY"),
]
def main() -> int:
root = Path(sys.argv[1] if len(sys.argv) > 1 else ".")
findings = 0
for path in root.rglob("*"):
if not path.is_file():
continue
if any(part.startswith(".venv") for part in path.parts):
continue
try:
text = path.read_text(encoding="utf-8", errors="ignore")
except OSError:
continue
for pat in PATTERNS:
if pat.search(text):
print(f"finding path={path} pattern={pat.pattern}")
findings += 1
break
return 1 if findings else 0
if __name__ == "__main__":
raise SystemExit(main())
EOF
python scan_secrets.py sample_repo; echo exit=$?
Step 3 – TLS verify reminder¶
python - <<'PY'
import urllib.request
# Default context verifies certificates — do not disable in production
print("use requests/httpx defaults; never verify=False for prod APIs")
PY
Step 4 – Dependency audit (optional)¶
Validation¶
- Lab commands run under
~/rebash-python/module-25/ - You can explain each Theory section in your own words
- You used modern tooling where it applies to this topic
- You can describe one production failure mode for this topic
Code Walkthrough¶
Production practice for Security for DevOps Python always combines:
- Inspect before you change (status, plan, logs, dry-run)
- Prefer reversible, documented changes (Git, IaC, drop-ins, version pins)
- Capture evidence (command output, pipeline logs) for handovers
- Prefer current tools and APIs over legacy shortcuts
- Least privilege — escalate credentials only when required
Keep runbooks short enough to follow under pressure. Automate checks; keep humans for judgement.
Security Considerations¶
- Treat credentials and tokens for python as privileged — never commit them
- Prefer short-lived auth (OIDC, roles, SSO) over long-lived keys
- Validate blast radius before apply/deploy/delete operations
- Restrict who can approve production changes
- Collect audit logs; limit who can read sensitive traces
Common Mistakes¶
Printing os.environ or full HTTP headers in debug mode.
Validate assumptions against the Theory section and official docs before changing production.
Disabling TLS verify “temporarily” and shipping it.
Lab shortcuts (open security groups, admin roles, skip approvals) must not ship unchanged.
Changing production without a rollback path
Always know how to revert (previous artefact, prior release, state rollback, DNS failback).
Best Practices¶
- Encode Security for DevOps Python changes as code and review them in pull requests
- Pin versions (images, modules, actions, provider plugins)
- Separate environments with clear promotion gates
- Alert on symptoms with runbooks attached
- Destroy lab resources; tag everything with owner and expiry where possible
Troubleshooting¶
| Symptom | Likely cause | What to do |
|---|---|---|
| Secret in CI logs | Debug print | Redact; scrub history |
| False positives | Broad regex | Tune; allow-list test fixtures |
| Audit noise | Transitive CVEs | Pin/upgrade; risk-accept with ticket |
Summary¶
- Secrets out of git/logs/argv
- Validate inputs; verify TLS
- Scan code and dependencies in CI
- Lab: Secrets Scanner
Interview Questions¶
- How does Security for DevOps Python show up when operating Cloud or production platforms?
- What would you check first if this area misbehaves in production?
- Which modern tools or APIs replace older equivalents here?
- What security control should accompany this capability?
- How would you automate verification of this topic in CI?
Sample answer — question 2
Start with blast radius and recent changes, gather evidence (logs, status, plan/diff), then fix forward with a known rollback path — not guesswork.