Skip to content

Commit 63fd22c

Browse files
authored
pulumi: add aws-lambda-device-lookup-table (#28)
* pulumi: add aws-lambda-device-lookup-table * pulumi: update aws-lambda-device-lookup-table replicates similar changes from aws-lambda-device-lookup-table
1 parent bfdaefc commit 63fd22c

File tree

14 files changed

+4058
-242
lines changed

14 files changed

+4058
-242
lines changed

pulumi/aws/aws-lambda-device-approval-handler/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ This example creates the following:
77

88
## To use
99

10-
Follow the documentation to configure the Terraform providers:
10+
Follow the documentation to configure the Pulumi providers:
1111

1212
- [AWS](https://www.pulumi.com/registry/packages/aws/installation-configuration/)
1313

pulumi/aws/aws-lambda-device-approval-handler/handler.ts

+12-13
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";
22

33
export async function lambdaHandler(ev: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> {
44
// TODO: https://tailscale.com/kb/1213/webhooks#verifying-an-event-signature
5-
// console.log(`Received event: ${JSON.stringify(ev)}`); // TODO: add verbose logging flag?
5+
// console.log(`Received event: ${JSON.stringify(ev)}`);
66

77
let processedCount = 0;
88
let ignoredCount = 0;
99
let erroredCount = 0;
1010
try {
1111
let decodedBody = ev.body;
1212
if (ev.isBase64Encoded) {
13-
decodedBody = Buffer.from(ev.body!, 'base64').toString('utf8');
13+
decodedBody = Buffer.from(ev.body!, "base64").toString("utf8");
1414
}
1515
const tailnetEvents: TailnetEvent[] = JSON.parse(decodedBody!);
1616
const results: ProcessingResult[] = [];
@@ -56,7 +56,6 @@ function generateResponseBody(statusCode: number, ev: APIGatewayProxyEvent, proc
5656
statusCode: statusCode,
5757
body: JSON.stringify({
5858
message: (statusCode == 200 ? "ok" : "An error occurred."),
59-
// requestId: ev.requestContext.requestId, // TODO: This requestId doesn't match what's in the lambda logs.
6059
eventResults: {
6160
processed: processedCount,
6261
errored: erroredCount,
@@ -103,11 +102,11 @@ async function nodeNeedsApprovalHandler(event: TailnetEvent): Promise<Processing
103102
["windows", "macos", "linux"].includes(attributesResponseJson["attributes"]["node:os"])
104103
&& attributesResponseJson["attributes"]["node:tsReleaseTrack"] == "stable"
105104
) {
106-
// approve device
107-
await approveDevice(eventData);
105+
// authorize device
106+
await authorizeDevice(eventData);
108107
}
109108
else {
110-
console.log(`NOT approving device [${eventData.nodeID}:${eventData.deviceName}] with attributes [${JSON.stringify(attributesResponseJson)}]`);
109+
console.log(`NOT authorizing device [${eventData.nodeID}:${eventData.deviceName}] with attributes [${JSON.stringify(attributesResponseJson)}]`);
111110
}
112111

113112
return { event: event, result: "SUCCESS", } as ProcessingResult;
@@ -120,7 +119,7 @@ export const ENV_TAILSCALE_OAUTH_CLIENT_ID = "OAUTH_CLIENT_ID";
120119
export const ENV_TAILSCALE_OAUTH_CLIENT_SECRET = "OAUTH_CLIENT_SECRET";
121120
const TAILSCALE_CONTROL_URL = "https://login.tailscale.com";
122121

123-
// https://github.com/tailscale/tailscale/blob/main/publicapi/device.md#get-device-posture-attributes
122+
// https://tailscale.com/api#tag/devices/GET/device/{deviceId}/attributes
124123
async function getDeviceAttributes(event: TailnetEventDeviceData): Promise<Response> {
125124
console.log(`Getting device attributes [${event.nodeID}]`);
126125
const data = await makeAuthenticatedRequest("GET", `${TAILSCALE_CONTROL_URL}/api/v2/device/${event.nodeID}/attributes`);
@@ -130,7 +129,7 @@ async function getDeviceAttributes(event: TailnetEventDeviceData): Promise<Respo
130129
return data;
131130
}
132131

133-
// https://github.com/tailscale/tailscale/blob/main/publicapi/device.md#get-device
132+
// https://tailscale.com/api#tag/devices/GET/device/{deviceId}
134133
async function getDevice(event: TailnetEventDeviceData): Promise<Response> {
135134
console.log(`Getting device [${event.nodeID}]`);
136135
const data = await makeAuthenticatedRequest("GET", `${TAILSCALE_CONTROL_URL}/api/v2/device/${event.nodeID}`);
@@ -140,12 +139,12 @@ async function getDevice(event: TailnetEventDeviceData): Promise<Response> {
140139
return data;
141140
}
142141

143-
// https://github.com/tailscale/tailscale/blob/main/publicapi/device.md#authorize-device
144-
async function approveDevice(device: TailnetEventDeviceData) {
145-
console.log(`Approving device [${device.nodeID}:${device.deviceName}]`);
142+
// https://tailscale.com/api#tag/devices/POST/device/{deviceId}/authorized
143+
async function authorizeDevice(device: TailnetEventDeviceData) {
144+
console.log(`Authorizing device [${device.nodeID}:${device.deviceName}]`);
146145
const data = await makeAuthenticatedRequest("POST", `${TAILSCALE_CONTROL_URL}/api/v2/device/${device.nodeID}/authorized`, JSON.stringify({ "authorized": true }));
147146
if (!data.ok) {
148-
throw new Error(`Failed to approve device [${device.nodeID}:${device.deviceName}]`);
147+
throw new Error(`Failed to authorize device [${device.nodeID}:${device.deviceName}]`);
149148
}
150149
}
151150

@@ -185,7 +184,7 @@ const makeAuthenticatedRequest = async function (method: "GET" | "POST", url: st
185184
}
186185

187186
async function httpsRequest(url: string, options: any): Promise<Response> {
188-
// console.log(`Making HTTP request to [${url}] with options [${JSON.stringify(options)}]`); // TODO: add verbose logging flag?
187+
// console.log(`Making HTTP request to [${url}] with options [${JSON.stringify(options)}]`);
189188
return await fetch(url, options);
190189
}
191190

pulumi/aws/aws-lambda-device-approval-handler/handlerPulumi.ts

-21
This file was deleted.

pulumi/aws/aws-lambda-device-approval-handler/index.ts

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
import * as pulumi from "@pulumi/pulumi";
2+
import * as aws from "@pulumi/aws";
13
import * as apigateway from "@pulumi/aws-apigateway";
2-
import * as path from 'path';
3-
import * as handler from "./handlerPulumi";
4+
import * as path from "path";
5+
6+
import * as handler from "./handler";
47

58
const name = `example-${path.basename(process.cwd())}`;
9+
const pulumiConfig = new pulumi.Config();
610

711
const api = new apigateway.RestAPI(name, {
812
stageName: "tailscale-device-approval",
@@ -11,7 +15,18 @@ const api = new apigateway.RestAPI(name, {
1115
{
1216
path: "/",
1317
method: "POST",
14-
eventHandler: handler.getPulumiHandler(`${name}-fn`),
18+
eventHandler: new aws.lambda.CallbackFunction(`${name}-fn`, {
19+
environment: {
20+
variables: {
21+
[handler.ENV_TAILSCALE_OAUTH_CLIENT_ID]: pulumiConfig.require("tailscaleOauthClientId"),
22+
[handler.ENV_TAILSCALE_OAUTH_CLIENT_SECRET]: pulumiConfig.requireSecret("tailscaleOauthClientSecret"),
23+
},
24+
},
25+
runtime: "nodejs20.x",
26+
callback: async (ev: any, ctx) => {
27+
return handler.lambdaHandler(ev);
28+
},
29+
}),
1530
},
1631
],
1732
});

0 commit comments

Comments
 (0)