added files

This commit is contained in:
Your Name
2026-08-26 02:02:24 +05:30
parent 58ee8a276a
commit 3419cfba0c
200 changed files with 22132 additions and 0 deletions
+262
View File
@@ -0,0 +1,262 @@
# SECURITY.md
<!-- Auto-generated by /m-docs:security-init. Edit freely — re-running preserves your changes. -->
> **Scope:** devops-lib is a Jenkins Shared Library, not a deployable web service. It has no HTTP endpoints of its own. This document covers the security properties of the library's CI/CD execution: how secrets are handled, what trust boundaries exist, what security rules new code must follow, and known gaps.
---
## Authentication
devops-lib has no user-facing HTTP endpoints and performs no JWT or session validation. Authentication is enforced at two points:
### Build trigger gate
`vars/eksCICD.groovy:1226` validates that every Jenkins build is triggered by an authorized caller:
- `ringmaster-bot` — Ringmaster's automated trigger
- `turbo-turtle` — Turbo-Turtle's CI callback trigger
- `allowedUsers` — a hardcoded list of DevOps engineer email addresses for emergency access
Unauthorized triggers are hard-rejected before any pipeline logic runs.
### Outbound credential injection
All outbound API calls use Jenkins' `withCredentials` binding — credentials are never hardcoded in source. Jenkins masks bound variables in console output automatically. Key credential IDs:
| Credential ID | Used for | Scope |
|---|---|---|
| `cicd-github-app` | Cloning `Meesho/whitelists`, `devops-argo-config`, `devops-helm-charts` | All builds |
| `svc-devops-meesho` | GitHub API, JFrog Artifactory | Build + deploy |
| `ringmaster-token` | Ringmaster callback API | Notify stage |
| `argocd-{bu}-prd-creds` / `argocd-dev-creds` | ArgoCD CLI login | Deploy stage |
| `vault-prd-token` / `vault-dev-token` | Vault secret fetch | Node builds only |
| `sonar-token-prod` / `sonar-token-{bu}-dev` | SonarQube analysis | Build stages |
---
## Trust Boundaries
### Build trigger trust boundary
| Layer | What happens | Where | Confidence |
|---|---|---|---|
| Ringmaster / Turbo-Turtle | Validates human approval, triggers Jenkins build | Upstream (Ringmaster infra) | docs-referenced |
| devops-lib `eksCICD` | Validates trigger source against `allowedUsers` list | `vars/eksCICD.groovy:12` | code-confirmed |
| Jenkins pipeline | Executes build stages with injected credentials | Jenkins agents (GKE pods) | code-confirmed |
**Trust assumption:** devops-lib assumes that any build triggered by `ringmaster-bot` or `turbo-turtle` has already been approved by the Ringmaster/Turbo-Turtle authorization flow. It does NOT re-validate the approval — it trusts the trigger identity.
### Supply chain trust boundary (CRITICAL)
`devops-lib@main` is loaded via `@Library('devops-lib@main')` by every Meesho microservice on every build. **A malicious or buggy merge to `main` is an immediate supply chain attack on all 100+ consumer services' CI/CD pipelines.**
- Whoever can merge to `devops-lib@main` controls the full CI/CD path for all Meesho microservices
- Branch protection rules for `main` are enforced at the GitHub repository level (not visible in this repo's source)
- No `.github/CODEOWNERS` file is present in the repository
<!-- TODO: Confirm that devops-lib's main branch has required PR reviews and no direct push access for non-DevOps-leads. This is the highest-risk trust boundary in the library. -->
### Whitelist repo trust boundary
Policy exceptions (sonar skip, multizone, AppConfig, CAC) are fetched from `Meesho/whitelists` at build time via `cicd-github-app` credential. If `Meesho/whitelists` is compromised or the `cicd-github-app` credential is stolen, an attacker could:
- Add any service to `skip-sonar-whitelist` to bypass quality gates
- Add a service to `multizone-enabled-repos` to block its deployments
- Remove a service from `ValidateCacConfig` to bypass config validation
### Jenkins agent trust boundary
Build stages execute in GKE pods (see `resources/org/meesho/prd-pod.yaml`). Secrets injected via `withCredentials` exist in the pod's process environment for the duration of the `withCredentials` block and are cleared afterward. `env.VAULT_TOKEN` is temporarily set during Vault secret fetch and immediately cleared:
```groovy
// buildNode.groovy:548-553
env.VAULT_TOKEN = "${TOKEN}"
sh(script:"${vault_cmd}")
env.VAULT_TOKEN = 'empty' // ← cleared immediately after use
```
**Note:** Assigning to `env.*` persists the value in Jenkins pipeline serialized state for the duration of that block — it is not fully memory-isolated like a `withCredentials` binding.
### Process / runtime boundaries
| Boundary | Inside (trusted) | Outside | Crossing mechanism |
|---|---|---|---|
| `withCredentials` block | Jenkins credential binding (secret) | Pipeline Groovy scope | Automatic unset on block exit |
| Jenkins agent pod | Build process, injected creds | Other pods, external network | K8s network policy, GKE service account |
| `set +x` shell guard | ArgoCD password in shell arg | Jenkins console log | `set +x` before credential use in `deployArgoCD.groovy:493` |
| DinD container | Docker daemon | Build container | TCP socket (`dind-prd-svc`) — not Unix socket (avoids privilege escalation) |
---
## Entry Points
devops-lib has no HTTP entry points. It is invoked as a Jenkins Shared Library.
### Build trigger (sole entry point)
| Trigger | Who sends it | Auth check |
|---|---|---|
| Ringmaster-initiated build | `ringmaster-bot` Jenkins user | `allowedUsers` gate in `eksCICD.groovy` |
| Turbo-Turtle-initiated build | `turbo-turtle` Jenkins user | `allowedUsers` gate in `eksCICD.groovy` |
| DevOps engineer direct trigger | Email in `allowedUsers` list | `allowedUsers` gate |
| Unauthorized user | Any other Jenkins user | Hard-rejected — pipeline aborts immediately |
### Outbound calls (not entry points, but relevant to trust)
All outbound calls are made FROM Jenkins agents TO external services. See [docs/downstreams.md](downstreams.md) for the full inventory.
Security additions to downstreams.md:
| Service | Protocol | Data sent | Risk | Notes |
|---|---|---|---|---|
| ArgoCD | HTTPS + gRPC | App names, image tags | Low | `set +x` guards password in shell |
| Ringmaster | HTTPS | Build result, image tag, repo name, team | Low | Auth via `ringmaster-token` credential |
| Turbo-Turtle | **HTTP** (plain) | Build result, image tag, repo name | Low — accepted risk | Internal VPC only, not reachable externally |
| Deployment Tracker | **HTTP** (plain) | Repo name, deploy timestamp, tag | Low — accepted risk | Internal VPC only, legacy endpoint |
| Security scanner | **HTTP** to `172.31.5.29:63232` | Repo name, branch | Low — accepted risk | Internal scanner, hardcoded IP |
| SonarQube | HTTPS | Source code analysis | Low | Token injected via `withCredentials` |
| Vault | HTTPS | Vault path (not secrets) | Low | Token cleared immediately after fetch |
| GitHub | HTTPS | Git operations | Low | `cicd-github-app` credential |
---
## Authorization
### Policy enforcement model
devops-lib enforces policy through two mechanisms:
1. **Whitelist-controlled gates**`constructParam.groovy` checks `Meesho/whitelists` at runtime for per-repo exceptions. No service can grant itself a bypass; all exceptions require a PR to `Meesho/whitelists` reviewed by DevOps.
2. **Library-level enforcement**`deployArgoCD.groovy` enforces canary for Tier-1 services, `eksCICD.groovy` enforces the trigger gate. These cannot be overridden by service config.
### allowedUsers list
The bypass list at `vars/eksCICD.groovy:12` contains hardcoded engineer email addresses. This list has no expiry mechanism — emails remain valid until manually removed.
<!-- TODO: Confirm that the allowedUsers list is audited periodically to remove email addresses of engineers who have left the organization. -->
---
## Data Classification
devops-lib handles no end-user PII. All data is build metadata:
### Non-PII (safe to log and pass to external services)
| Data | Where it appears | Notes |
|---|---|---|
| `repo_name` | All stages, Ringmaster callback | GitHub org slug — not sensitive |
| `build_tool` | Build stages | Language identifier |
| `cicd_environment` | All stages | prd / stg / int / ftr |
| `TAG` (image tag) | Deploy stages, Slack notifications | `<branch>-<git-sha>` — not sensitive |
| `notify_channel` | Notify stage | Slack channel name |
| `team` / `bu` | Build stages, node pool selection | Org metadata |
| `deployment_order` | ArgoCD deploy | App names in devops-argo-config |
| Build result / duration | Slack, Ringmaster, Turbo-Turtle | Build observability |
### Sensitive (not PII, but must be handled with care)
| Data | Where it exists | Handling |
|---|---|---|
| Jenkins credential values | `withCredentials` blocks | Never logged, masked in console |
| Vault secret paths | `buildNode.groovy:536-537` | Path logged (not value); value only in `sh` subprocess |
| `ARGO_USERNAME` / `ARGO_PASSWORD` | `deployArgoCD.groovy:490-494` | `set +x` guard prevents echo in logs |
| `GITHUB_TOKEN` | Git clone operations | Via `gitUsernamePassword` binding — not logged |
---
## Data Lifecycle & Erasure
No end-user data stored. Build artifacts:
**Known:**
- Jenkins build logs: retained per Jenkins job configuration (managed by Jenkins admins, not devops-lib)
- Docker images in GAR/ECR: no TTL configured in devops-lib — lifecycle managed by GAR cleanup policies outside this library
- Deployment history in Ringmaster: managed by Ringmaster service
**Unknown:** Retention policy for build logs and deployment records is not configurable from devops-lib.
<!-- TODO: Confirm Jenkins build log retention policy with the infrastructure team. -->
---
## Data Storage & Encryption
### At rest
devops-lib has no persistent storage. It reads from GitHub, Jenkins credentials store, and Vault; it writes to GitHub repos (argo-config, helm-charts) and pushes Docker images to GAR/ECR.
| Store | What is stored | Managed by |
|---|---|---|
| Jenkins credentials store | All CI/CD credentials (tokens, passwords) | Jenkins admins |
| GAR / ECR | Docker images | GCP / AWS infra |
| devops-helm-charts / devops-argo-config | Helm values, ArgoCD manifests | devops-lib writes; git is the store |
### In transit
- All GitHub API calls: HTTPS ✓
- ArgoCD CLI: HTTPS + gRPC ✓
- SonarQube, Vault, Ringmaster API: HTTPS ✓
- Turbo-Turtle, Deployment Tracker, security scanner: **plain HTTP** — accepted risk (internal VPC, not reachable externally)
### Secrets management
All secrets are injected at runtime from Jenkins credentials store via `withCredentials`. No secrets in source code, config files, or environment variables baked into the library. Credentials are identified by their Jenkins credential ID (e.g. `ringmaster-token`, `vault-prd-token`) — the actual values are never stored in this repository.
---
## Input Validation
devops-lib takes inputs from two sources:
### Service `config.yaml` (primary input)
Read by `getYamlParameter.getParam()`. Fields are used directly without schema validation — devops-lib trusts the config.yaml from the consumer service's own repository (cloned via authenticated git). Malformed configs produce runtime errors, not silent misbehaviour.
`buTeamMapping.groovy` validates `bu` and `team` fields against a known mapping and throws on invalid values.
### What's NOT validated
- **`repo_name`** in config.yaml: used in ArgoCD app names, Slack messages, and Vault paths. Not sanitized against shell injection — passed directly into `sh()` scripts. Risk is mitigated because `repo_name` comes from the service's own config.yaml in its own GitHub repo (already authenticated).
- **`notify_channel`**: passed directly to Slack API — no format validation. A malformed channel name produces a Slack API error, not a security issue.
- **`deployment_order` app names**: passed to `argocd app sync` — no format validation. An invalid app name produces an ArgoCD error.
---
## Security Headers & CORS
Not applicable — devops-lib has no HTTP server and serves no responses.
---
## Security Rules for New Code
These rules apply to anyone adding code to devops-lib:
**Credentials:** All secrets must be injected via `withCredentials` — never assign a credential value to a variable outside a `withCredentials` block, never interpolate credentials into log statements, and never store them in `env.*` variables beyond the immediate operation that needs them.
**Shell commands with credentials:** Use `set +x` immediately before any `sh()` that includes a credential variable as an argument (as done in `deployArgoCD.groovy:493`). Without `set +x`, Jenkins echoes the full shell command including the credential value to the build log.
**Policy enforcement:** Never add inline conditionals for repo-level policy exceptions. All exceptions must go through `Meesho/whitelists` — see [ADR-0003](adr/0003-policy-exceptions-in-separate-whitelist-repo.md).
**Supply chain hygiene:** Any change to `vars/eksCICD.groovy` or `src/com/meesho/utilities/constructParam.groovy` affects every Meesho microservice build. These files require extra scrutiny — treat them as Tier-1 code.
**DinD image:** The Docker-in-Docker image must come from the internal GAR registry (`asia-southeast1-docker.pkg.dev/meesho-devops-admin-0622/admin/devops/docker:28-dind`). Never use `docker:N-dind` from Docker Hub — it is not security-scanned and will be blocked by network policy. (See `docs/tribal-knowledge.md` TK#14.)
The following security rules are already enforced in CLAUDE.md NEVER DO and are not repeated here:
- **Never hard-code AWS/GCP account IDs, vault tokens, or credentials** — all secrets are passed via Jenkins credentials (`withCredentials`) or injected through `constructParam.run()`. Credentials IDs are defined in `constructParam.groovy`.
- **Never change the string `"ringmaster-bot"`** without coordinating with the Ringmaster team — it is the sole signal that routes callbacks to Ringmaster vs Turbo-Turtle.
---
## Security Debt Tracker
| ID | Gap | Severity | Source | Ticket |
|---|---|---|---|---|
| SEC-DL-001 | `allowedUsers` list in `eksCICD.groovy` contains engineer email addresses with no expiry — stale access risk if engineers leave the org | Low | Code-discovered | — |
| SEC-DL-002 | No `.github/CODEOWNERS` visible in repo — supply chain protection for `main` branch depends entirely on GitHub repo settings not auditable from source | Medium | Code-discovered | — |
| SEC-DL-003 | Security scanner endpoint hardcoded as `172.31.5.29:63232` (plain HTTP, no auth) — if IP changes, scanner silently stops running | Low | Code-discovered | — |
| SEC-DL-004 | `env.VAULT_TOKEN` temporarily assigned in `buildNode.groovy:550` — token exists in Jenkins pipeline serialized state during Vault fetch block (cleared immediately after) | Low | Code-discovered | — |
| SEC-DL-005 | Turbo-Turtle and Deployment Tracker callbacks over plain HTTP | Low | Code-discovered | — |
---
## Past Security Incidents
No known security incidents documented in code, wiki, or Jira at time of generation.
---
<!-- security-init: generated-at=2026-05-12T00:00:00Z base-sha=1495ffb862641ed7220b0cbce5c021e7487f2a1d -->