
# keenauth_attack_protection

The `keenauth_attack_protection` resource manages the attack-protection settings of the environment: brute force, suspicious-IP throttling, credential stuffing and attack mode, bot protection, breached passwords, sign-up protection, SMS fraud protection and the risk policy.

## One object per environment

The attack-protection object exists once per environment and always exists. Declare the resource at most once per provider configuration. Creating the resource reads the current object and writes only what your configuration changes. Destroying it only removes it from state; the environment keeps its protection settings, so a `destroy` never loosens security silently.

## Only what you write is managed

An attribute or group you leave out keeps its current value. Removing an attribute from the configuration keeps its last value. The state holds the **effective** values, which are the defaults, security floors and plan gates the API applied, so a downgraded plan shows up as a change in the next `plan`. Lists such as `suspicious_ip_throttling.allowlist` and `sms_protection.allowed_countries` are sets, so their order does not matter.

```terraform
resource "keenauth_attack_protection" "this" {
  brute_force = {
    max_failures = 10
    lock_minutes = 30
  }

  suspicious_ip_throttling = {
    allowlist = ["203.0.113.0/24"]
  }

  sms_protection = {
    allowed_countries = ["DE", "TR"]
    daily_cap         = 500
  }

  risk_policy = {
    mode                = "enforce"
    challenge_threshold = 5
    block_threshold     = 8
  }
}
```

## Groups

| Attribute | What it controls |
|---|---|
| `brute_force` | Per-user lock after failed sign-ins: mode, failures before a lock, counting window, lock duration, user e-mail. |
| `suspicious_ip_throttling` | Per-IP limits for failed sign-ins and sign-ups, and the CIDR allowlist that is exempt. |
| `credential_stuffing` | Credential stuffing detection mode and attack mode (automatic start, duration). |
| `bot_protection` | Bot challenge mode (`off`, `risk_based`, `always`) and provider. |
| `breached_password` | What happens when a breached password is used at sign-up, on password change and at sign-in. |
| `signup_protection` | Disposable e-mail, `+` sub-addresses and the sign-ups per device in 30 days. |
| `sms_protection` | Countries SMS may go to, daily cap and the conversion breaker. |
| `risk_policy` | Risk mode, challenge and block thresholds, new-device notification. |

## Security floors and plan gates

- Values below a security floor (more than 100 failed attempts before a lock, a lock shorter than 5 minutes, more than 20 sign-ups per IP per hour) are rejected at plan time. The blocking choices of `breached_password.on_signup` and `on_password_change` are floors too.
- `risk_policy.block_threshold` must be greater than `risk_policy.challenge_threshold`.
- `risk_policy.mode = "enforce"` needs the Startup plan or above; the API answers `403 plan_feature_unavailable` otherwise.
- `block_threshold` and `daily_cap` are `null` in state while off. Once you set them, the configuration cannot switch them off again; use the dashboard or the management API for that.
- Allowlist entries are canonical network addresses such as `203.0.113.0/24`. IPv4 prefixes broader than /8 and IPv6 prefixes broader than /32 are rejected.

## Safe changes

- An update sends only the changed fields as a JSON merge patch with `If-Match`. If someone changed the object after the plan was made, the API answers `412` and nothing changes. Run `plan` again.
- A change made in the dashboard shows up in the next `plan` as drift, and `apply` reverts it for the attributes you manage.
- Active lockouts and attack mode are operations, not configuration: use the dashboard or the management API (`/v1/attack-protection/lockouts` and `/v1/attack-protection/attack-mode`) for them.

## Import

```shell
tofu import keenauth_attack_protection.this attack-protection
```
