# Terraform и GitOps

← [Раздел](README.md) · [Главная](../README.md)

## Цель

Понять **Infrastructure as Code (IaC)** на примере Terraform и **GitOps** для деплоя — как описывать инфраструктуру кодом и проверять её на security **до** apply.

## Предварительно

- [CI/CD pipeline](ci-cd-pipeline.md)

## Время

**8–10 часов**

---

## Infrastructure as Code

**Раньше:** админ кликает в UI cloud → «snowflake servers», нет истории.

**IaC:** инфраструктура в **файлах** (`.tf`), версионируется в Git, review + plan + apply.

| Плюс | Для SecOps |
|------|------------|
| Reproducibility | Audit trail |
| Review in MR | tfsec до merge |
| Drift detection | Compliance |
| Modules | Secure baselines |

---

## Terraform workflow

```bash
terraform init      # провайдеры, backend
terraform fmt       # форматирование
terraform validate  # синтаксис
terraform plan      # что изменится (dry-run)
terraform apply     # применить
```

**Plan** — ваш главный друг: «создаст public S3 bucket?» → stop.

---

## Минимальный пример (учебный)

```hcl
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "eu-central-1"
}

resource "aws_s3_bucket" "logs" {
  bucket = "example-logs-lab-UNIQUE_SUFFIX"
}

resource "aws_s3_bucket_public_access_block" "logs" {
  bucket = aws_s3_bucket.logs.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}
```

**Public access block** — must-have для S3 security.

---

## State

**Terraform state** — mapping ресурсов ↔ реальность.

| Хранение | Риск |
|----------|------|
| Local `terraform.tfstate` | Потеря, secrets in state |
| Remote S3 + DynamoDB lock | Team standard |

State может содержать **чувствительные** attributes — encrypt, restrict IAM.

---

## Modules и DRY

```hcl
module "vpc" {
  source = "./modules/vpc"
  cidr   = "10.0.0.0/16"
}
```

**Secure module** — один раз hardened VPC, команды переиспользуют.

---

## IaC security scanning

| Tool | Что ищет |
|------|----------|
| Checkov | Misconfig (SG 0.0.0.0/0) |
| tfsec | AWS/Azure/GCP rules |
| KICS | Multi-IaC |

В CI:

```yaml
terraform_plan:
  script:
    - terraform plan -out=plan.tfplan
    - terraform show -json plan.tfplan > plan.json
    - checkov -f plan.json
```

---

## GitOps

**GitOps** — **Git = source of truth** для **desired state** кластера/infra.

```
Developer → MR → merge main → Argo CD / Flux sync → K8s matches Git
```

| Push-based (classic CI) | Pull-based (GitOps) |
|-------------------------|---------------------|
| CI kubectl apply | Agent in cluster pulls |
| CI needs cluster creds | Credentials in cluster |
| Drift manual | Auto reconcile or alert |

---

## Argo CD (концепт)

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web
spec:
  source:
    repoURL: https://gitlab.example.com/infra.git
    path: k8s/web
    targetRevision: main
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
```

**selfHeal** — откат ручных `kubectl edit` (осторожно в debug).

---

## Policy as Code

| Engine | Где |
|--------|-----|
| OPA / Gatekeeper | K8s admission |
| Sentinel | Terraform Cloud |
| Kyverno | K8s native policies |

Пример: «запретить LoadBalancer type Service в namespace dev».

---

## Drift и compliance

**Drift** — реальность ≠ Git. Причины: ручные изменения, compromised creds.

**Решение:** periodic `terraform plan` (no changes expected), GitOps diff alerts.

---

## Практика

1. Установите Terraform, init empty dir.
2. Опишите **локальный** resource `null_resource` или free tier S3 (lab account).
3. `plan` → `apply` → `destroy`.
4. Запустите `checkov -d .` на `.tf` файлах.

---

## Самопроверка

1. Зачем `terraform plan` перед apply?
2. Почему state file чувствителен?
3. Чем GitOps отличается от «CI делает kubectl apply»?
4. Назовите один IaC scanner.

---

## Дальше

→ [04 — Фундамент безопасности](../04-fundament-bezopasnosti/README.md)
