# IPSec Frontend API

## Endpoints

| Method | Path | Description |
|--------|------|-------------|
| POST | `/ipsec-frontend` | Create an IPSec frontend endpoint |
| GET | `/ipsec-frontend?id=<id>` | Get status of a specific endpoint |
| GET | `/ipsec-frontend` | List all IPSec frontend endpoints |
| DELETE | `/ipsec-frontend?id=<id>` | Destroy an IPSec frontend endpoint |

## HTTP Status Codes

| Code | Meaning |
|------|---------|
| 200 | Operation succeeded |
| 202 | Stack is locked by another process (retry with backoff) |
| 400 | Malformed request (missing required fields) |
| 404 | Stack not found |
| 409 | Duplicate — stack already exists |
| 500 | Internal error (Pulumi/AWS failure) |

---

## POST `/ipsec-frontend` — Create

### Request Body

```json
{
  "id": "cust-a-site-1",
  "peer_public_ip": "52.53.142.84",
  "peer_cidr": "172.31.0.0/16",
  "psk_secret_arn": "arn:aws:secretsmanager:us-east-1:123456789012:secret:vpn-psk-abc123"
}
```

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `id` | string | yes | Unique identifier for the endpoint site. Becomes the Pulumi stack name (lowercased). |
| `peer_public_ip` | string | yes | Customer's IPSec peer public IP address. |
| `peer_cidr` | string | yes | Customer's private CIDR block (e.g. `"172.31.0.0/16"`). Used for security group rules, TGW routes, and subnet routes. |
| `psk_secret_arn` | string | no | ARN of a Secrets Manager secret containing the VPN pre-shared key. If omitted, AWS auto-generates tunnel PSKs. |

### Response Body (200)

```json
{
  "projectName": "mop-ipsec-frontend-staging",
  "stackName": "cust-a-site-1",
  "environment": "staging",
  "lastUpdate": "2026-04-22T15:30:00Z",
  "resources": 18,
  "stackStatus": "IPSEC_FRONTEND_CREATED",
  "message": "Resources successfully created for ipsec frontend stack: cust-a-site-1",
  "nlbPrivateIp": "10.1.5.10",
  "nlbDnsName": "ipsec-fe-cust-a-site-1-nlb-abc123.elb.us-east-1.amazonaws.com",
  "nlbArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/net/ipsec-fe-cust-a-site-1-nlb/abc123",
  "tgwId": "tgw-0abc123def456",
  "vpnConnectionId": "vpn-0abc123def456",
  "subnetId": "subnet-0abc123def456",
  "peerCidr": "172.31.0.0/16"
}
```

---

## GET `/ipsec-frontend?id=<id>` — Get Status

### Query Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `id` | string | yes | The endpoint identifier. |

### Response Body (200)

```json
{
  "projectName": "mop-ipsec-frontend-staging",
  "stackName": "cust-a-site-1",
  "environment": "staging",
  "lastUpdate": "2026-04-22T15:30:00Z",
  "resources": 18,
  "stackStatus": "IPSEC_FRONTEND_CREATED",
  "message": "ipsec frontend stack cust-a-site-1 has been successfully retrieved",
  "nlbPrivateIp": "10.1.5.10",
  "nlbDnsName": "ipsec-fe-cust-a-site-1-nlb-abc123.elb.us-east-1.amazonaws.com",
  "nlbArn": "arn:aws:elasticloadbalancing:us-east-1:123456789012:loadbalancer/net/ipsec-fe-cust-a-site-1-nlb/abc123",
  "tgwId": "tgw-0abc123def456",
  "vpnConnectionId": "vpn-0abc123def456",
  "subnetId": "subnet-0abc123def456",
  "peerCidr": "172.31.0.0/16"
}
```

---

## GET `/ipsec-frontend` — List All

### Response Body (200)

```json
{
  "message": "Returned 2 ipsec frontend stack(s)",
  "stacks": [
    {
      "name": "cust-a-site-1",
      "lastUpdate": "2026-04-22T15:30:00Z",
      "updateInProgress": false,
      "resources": 18
    },
    {
      "name": "cust-b-site-1",
      "lastUpdate": "2026-04-21T10:00:00Z",
      "updateInProgress": false,
      "resources": 18
    }
  ]
}
```

---

## DELETE `/ipsec-frontend?id=<id>` — Destroy

### Query Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `id` | string | yes | The endpoint identifier. |

### Response Body (200)

```json
{
  "projectName": "mop-ipsec-frontend-staging",
  "stackName": "cust-a-site-1",
  "environment": "staging",
  "lastUpdate": "2026-04-22T16:00:00Z",
  "resources": 0,
  "stackStatus": "DELETED",
  "message": "ipsec frontend stack cust-a-site-1 has been successfully deleted and its resources destroyed",
  "nlbPrivateIp": "",
  "nlbDnsName": "",
  "nlbArn": "",
  "tgwId": "",
  "vpnConnectionId": "",
  "subnetId": "",
  "peerCidr": ""
}
```

---

## Response Fields Reference

| Field | Type | Description |
|-------|------|-------------|
| `projectName` | string | Pulumi project name (e.g. `mop-ipsec-frontend-staging`) |
| `stackName` | string | Pulumi stack name (lowercased `id`) |
| `environment` | string | Deployment environment (`sandbox`, `staging`, `production`) |
| `lastUpdate` | string | Timestamp of the last stack update |
| `resources` | int | Number of AWS resources managed by the stack |
| `stackStatus` | string | One of: `IPSEC_FRONTEND_CREATED`, `DUPLICATE`, `LOCKED`, `DELETING`, `DELETED`, `NOT_FOUND`, `UNKNOWN` |
| `message` | string | Human-readable status or error description |
| `nlbPrivateIp` | string | Pinned private IPv4 address of the internal NLB |
| `nlbDnsName` | string | DNS name of the internal NLB |
| `nlbArn` | string | ARN of the internal NLB |
| `tgwId` | string | Transit Gateway ID (from shared infrastructure) |
| `vpnConnectionId` | string | AWS VPN Connection ID for this endpoint |
| `subnetId` | string | Subnet ID where the NLB and tasks run |
| `peerCidr` | string | Customer's private CIDR block |
