|
Some checks failed
Deploy / deploy (push) Has been cancelled
Bumps the minor-and-patch group with 3 updates: [constructs](https://github.com/aws/constructs), [@aws-sdk/client-ssm](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/clients/client-ssm) and [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk). Updates `constructs` from 10.6.0 to 10.7.1 - [Release notes](https://github.com/aws/constructs/releases) - [Commits](https://github.com/aws/constructs/compare/v10.6.0...v10.7.1) Updates `@aws-sdk/client-ssm` from 3.1086.0 to 3.1091.0 - [Release notes](https://github.com/aws/aws-sdk-js-v3/releases) - [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/clients/client-ssm/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.1091.0/clients/client-ssm) Updates `aws-cdk` from 2.1130.0 to 2.1132.0 - [Release notes](https://github.com/aws/aws-cdk-cli/releases) - [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1132.0/packages/aws-cdk) --- updated-dependencies: - dependency-name: constructs dependency-version: 10.7.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: minor-and-patch - dependency-name: "@aws-sdk/client-ssm" dependency-version: 3.1091.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minor-and-patch - dependency-name: aws-cdk dependency-version: 2.1132.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: minor-and-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|---|---|---|
| .github | ||
| .security-review | ||
| bin | ||
| lambda | ||
| lib | ||
| .gitignore | ||
| cdk.context.json | ||
| cdk.json | ||
| door-unlock-plan.md | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| RUNBOOK-token-rotation.md | ||
| tsconfig.json | ||
| yealinkT54W-door-unlock-with-sp.ph.xml | ||
| yealinkT54W-door-unlock.ph.xml | ||
| yealinkT58W-door-unlock.ph.xml | ||
Sea Haven Door Unlock API
AWS Lambda middleware that allows Yealink desk phones to unlock the front door and manage lockdown profiles via LenelS2 Elements.
Yealink T54W/T58W → HTTPS GET (?token=) → API Gateway (token authorizer) → Lambda → LenelS2 Elements API
Architecture
- API Gateway (HTTP API) —
GET /unlock,GET /lockdown,GET /lockdown/statuswith throttling (5 burst / 2 sustained req/sec) - Token authorizer Lambda — a REQUEST-type Lambda authorizer validates the
?token=query-string value (the same shared secret the phones already send) against the/seahaven/door-unlock/auth-tokenSSM parameter, so unauthenticated callers are rejected at the gateway (401/403) before any handler runs. Identity source is$request.querystring.token; results are cached 5 minutes. Fail-closed. The handlers also re-validate the token as defense-in-depth. - Unlock Lambda — validates a shared auth token, calls the Elements
TemporaryUnlockcommand - Lockdown Lambda — toggles lockdown profiles (start/stop) and checks status, returns Yealink XML TextScreen responses
- Lockdown Poller Lambda — VPC-connected, polls Elements API every 15 seconds for lockdown status (runs 4x per 1-minute EventBridge schedule)
- SSM Parameter Store — stores the Elements API key, auth token, door ID, and phone IPs
- Secrets Manager — stores the Yealink phone admin password
- Custom Domain —
doorunlock.seahaven.comvia Route 53 + ACM wildcard cert - CloudWatch alarms — one error alarm per Lambda (unlock, lockdown, authorizer, poller); each fires on
Errors > 0and notifies the cross-stacksite-alertsSNS topic (ALARM state only)
Infrastructure (CDK)
All infrastructure is defined as code with the AWS CDK v2 (TypeScript); aws-cdk-lib is pinned to 2.261.0. The whole system is a single CloudFormation stack.
Layout
bin/app.ts # CDK app entry point
lib/door-unlock-stack.ts # DoorUnlockStack — all resource definitions
lambda/
├── unlock/unlock-handler.ts # Unlock Lambda
├── lockdown/lockdown-handler.ts # Lockdown Lambda
├── poller/lockdown-poller.ts # Lockdown Poller Lambda
└── authorizer/authorizer-handler.ts # Token authorizer Lambda
cdk.json # CDK config (app command, watch, context flags)
bin/app.ts
Instantiates DoorUnlockStack with an explicit stackName of seahaven-door-unlock-api, pinned to account 328440206208 / us-east-1.
lib/door-unlock-stack.ts
Defines every resource the stack owns:
- The four Lambda functions (Node 24.x, arm64, 60-day log retention), bundled from TypeScript with esbuild
- The HTTP API (
door-unlock-api), itsGET /unlock,GET /lockdown, andGET /lockdown/statusroutes, throttling, and JSON access logging - The
HttpLambdaAuthorizertoken authorizer (identity source$request.querystring.token, 5-minute result cache) - The EventBridge rule that invokes the poller once a minute, plus the poller's VPC config and security group (imported VPC/subnets, egress to the Elements API and phone LAN)
- The custom domain, ACM certificate import, and Route 53 A record for
doorunlock.seahaven.com - Imports of the SSM parameters, the phone-password secret, and the
site-alertsSNS topic, with the correspondinggrantReadIAM permissions - The four per-Lambda CloudWatch error alarms
cdk.json
CDK configuration committed to the repo. The app command runs npx tsx bin/app.ts, so the TypeScript entry point executes directly via tsx (no separate compile step). It also carries the watch include/exclude globs and the CDK feature-flag context.
Commands
npx cdk synth # synthesize the CloudFormation template
npx cdk diff # diff against the deployed stack
npx cdk deploy # deploy (see Manual Deployment below)
The same commands are also exposed as npm scripts (npm run synth, npm run diff, npm run deploy).
Documentation
The canonical map of Sea Haven's AWS infrastructure lives in Confluence. This project's seahaven-door-unlock-api stack is represented there as a Mermaid subgraph.
- AWS Architecture Map (Confluence, IT space, page 1540098)
Lockdown Profiles
Two lockdown profiles are configured:
| Profile | Elements ID | Line Key |
|---|---|---|
| Bohemia - Whole Building | 4b4a3e6b-c903-4cce-8cd6-288612bf0542 |
3 |
| Ronkonkoma - Whole Building | ff9876bc-c54f-472e-aef9-d2bffd4b7cf7 |
4 |
Pressing the line key toggles the lockdown on/off and displays the current status on the phone screen.
Known limitation: Line key LED color does not currently change to reflect lockdown status. The T58W's XML Browser key type (17) does not support persistent LED color changes via Push XML or Execute commands — LED commands are transient and immediately overridden by the phone's key type management.
SSM Parameters
| Parameter | Type | Description |
|---|---|---|
/seahaven/door-unlock/elements-api-key |
SecureString | LenelS2 Elements API key |
/seahaven/door-unlock/auth-token |
SecureString | Shared secret embedded in the Yealink DSS key URL |
/seahaven/door-unlock/door-id |
String | Elements device ID for the front door reader |
/seahaven/door-unlock/phone-ips |
String | Comma-separated phone IPs for lockdown poller |
Secrets Manager
| Secret | Description |
|---|---|
door-unlock-api/phone-password |
Yealink phone admin password for Push XML |
CI/CD
GitHub Actions, using the Sea Haven reusable workflows:
.github/workflows/ci.yaml— on pull requests tomain, runs theci-typescript-cdkreusable workflow (build, lint, synth)..github/workflows/deploy.yaml— on push tomain, runs thecd-cdkreusable workflow which assumes thegithubdeploy-seahaven-door-unlock-apiOIDC role (AWS_DEPLOY_ROLE_ARNrepo secret) and runscdk deploy.
The legacy CodePipeline/CodeBuild deploy path has been fully decommissioned.
Manual Deployment
npm install
npx cdk deploy
Phone Configuration
Configure DSS keys on the Yealink T54W/T58W (via phone web UI or 3CX):
-
Key 2 — Unlock Door
- Type: URL
- Value:
https://doorunlock.seahaven.com/unlock?token=<auth-token>
-
Keys 3-4 — Lockdown Toggle
- Type: XML Browser (17)
- Value:
https://doorunlock.seahaven.com/lockdown?token=<auth-token>&profile=bohemia|ronkonkoma
3CX Provisioning Templates
Custom 3CX templates are included with door unlock and lockdown URLs hardcoded.
| Template | Model | Key 2 | Keys 3-4 | Display |
|---|---|---|---|---|
yealinkT54W-door-unlock.ph.xml |
T54W | Unlock Door | Managed by 3CX BLF | Dim after 5 min, never sleep |
yealinkT54W-door-unlock-with-sp.ph.xml |
T54W | Unlock Door | Shared Parking SP1-3 | Dim after 5 min, never sleep |
yealinkT58W-door-unlock.ph.xml |
T58W | Unlock Door | Lockdown Toggle (Bohemia/Ronkonkoma) | Default T58W display settings |