import { SSMClient, GetParameterCommand, } from "@aws-sdk/client-ssm"; const ssm = new SSMClient({}); let cachedAuthToken: string | undefined; let cachedApiKey: string | undefined; let cachedDoorId: string | undefined; let lastUnlockTime = 0; const COOLDOWN_MS = 5_000; async function getParameter(name: string, decrypt: boolean): Promise { const res = await ssm.send( new GetParameterCommand({ Name: name, WithDecryption: decrypt }) ); return res.Parameter!.Value!; } async function loadSecrets() { const [authToken, apiKey, doorId] = await Promise.all([ cachedAuthToken ?? getParameter(process.env.AUTH_TOKEN_PARAM!, true), cachedApiKey ?? getParameter(process.env.ELEMENTS_API_KEY_PARAM!, true), cachedDoorId ?? getParameter(process.env.DOOR_ID_PARAM!, false), ]); cachedAuthToken = authToken; cachedApiKey = apiKey; cachedDoorId = doorId; return { authToken, apiKey, doorId }; } export async function handler(event: { queryStringParameters?: Record; requestContext?: { http?: { sourceIp?: string } }; }) { const sourceIp = event.requestContext?.http?.sourceIp ?? "unknown"; const token = event.queryStringParameters?.token; if (!token) { console.log(JSON.stringify({ action: "unlock_attempt", status: "rejected", reason: "missing_token", sourceIp })); return { statusCode: 403, body: JSON.stringify({ error: "Forbidden" }) }; } let secrets; try { secrets = await loadSecrets(); } catch (err) { console.error(JSON.stringify({ action: "unlock_attempt", status: "error", reason: "ssm_failure", sourceIp, error: String(err) })); return { statusCode: 500, body: JSON.stringify({ error: "Internal error" }) }; } if (token !== secrets.authToken) { console.log(JSON.stringify({ action: "unlock_attempt", status: "rejected", reason: "invalid_token", sourceIp })); return { statusCode: 403, body: JSON.stringify({ error: "Forbidden" }) }; } const now = Date.now(); if (now - lastUnlockTime < COOLDOWN_MS) { console.log(JSON.stringify({ action: "unlock_attempt", status: "cooldown", sourceIp })); return { statusCode: 429, body: JSON.stringify({ message: "Cooldown active, try again shortly" }) }; } const url = `https://api.elementssecure.com/v1/devices/${secrets.doorId}/commands/TemporaryUnlock/execute`; try { const response = await fetch(url, { method: "POST", headers: { "api-key": secrets.apiKey, "Content-Type": "application/json", }, body: JSON.stringify({}), }); if (!response.ok) { const body = await response.text(); console.error(JSON.stringify({ action: "unlock_attempt", status: "elements_error", statusCode: response.status, body, sourceIp })); return { statusCode: 502, body: JSON.stringify({ error: "Door system error" }) }; } lastUnlockTime = now; console.log(JSON.stringify({ action: "unlock_attempt", status: "success", sourceIp })); return { statusCode: 200, body: JSON.stringify({ message: "Door unlocked" }) }; } catch (err) { console.error(JSON.stringify({ action: "unlock_attempt", status: "error", reason: "elements_unreachable", sourceIp, error: String(err) })); return { statusCode: 502, body: JSON.stringify({ error: "Door system unreachable" }) }; } }