feat: syslog-server under IaC (INFRA-12)

CDK stack for the EC2 syslog collector (rsyslog 514 -> CloudWatch agent ->
unifi-syslog), mirroring the file-share/forgejo pattern. Recreated from the
captured console config; EIP 184.72.154.32 imported + re-associated so the
UniFi forwarding target is unchanged. Deployed + verified 2026-06-09.

Note: deploy role can assume cdk-hnb659fds-* (account-admin via CDK
bootstrap) — same exposure as every org CDK deploy role; per-app qualifier
is a known org-wide follow-up.
This commit is contained in:
Adam Moussa 2026-06-09 13:51:17 -04:00
commit a8276b44fd
12 changed files with 961 additions and 0 deletions

10
.github/workflows/ci.yaml vendored Normal file
View file

@ -0,0 +1,10 @@
name: CI
on:
pull_request:
branches: [main]
jobs:
ci:
uses: Sea-Haven-Industries/.github/.github/workflows/ci-typescript-cdk.yaml@main
with:
node-version: "24"

View file

@ -0,0 +1,6 @@
name: Dependency Review
on:
pull_request:
jobs:
review:
uses: Sea-Haven-Industries/.github/.github/workflows/callable-dependency-review.yaml@main

20
.github/workflows/deploy.yaml vendored Normal file
View file

@ -0,0 +1,20 @@
name: Deploy
on:
push:
branches: [main]
permissions:
id-token: write
contents: read
concurrency:
group: deploy
cancel-in-progress: false
jobs:
deploy:
uses: Sea-Haven-Industries/.github/.github/workflows/cd-cdk.yaml@main
with:
node-version: "24"
secrets:
deploy-role-arn: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}

6
.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
node_modules/
cdk.out/
*.js
*.d.ts
*.js.map
.env

57
README.md Normal file
View file

@ -0,0 +1,57 @@
# syslog-server
CDK stack for the **syslog-server** EC2 collector: receives remote syslog
(UDP/TCP 514) from the office UniFi fleet over its Elastic IP and ships it to
the `unifi-syslog` CloudWatch Logs group via the CloudWatch agent.
Brought under IaC for **INFRA-12** (AWS audit L-6). Previously a console/CLI
instance with no drift detection.
## Architecture
```
office UniFi devices ──syslog/514──▶ EIP 184.72.154.32 ──▶ EC2 (rsyslog)
│
/var/log/remote/<host>/*.log
│
CloudWatch agent ──▶ unifi-syslog (90d)
│
Syslog-NoIncomingLogs alarm ──▶ site-alerts
```
| Resource | Value |
|---|---|
| Instance | `syslog-server`, t4g.nano, Amazon Linux 2023 (arm64), 30 GiB encrypted gp3 |
| Subnet | `subnet-0eea820effe1b3ae5` (public, us-east-1a, `vpc-0d3d4b67bd0cf8a68`) |
| Elastic IP | `184.72.154.32` (`eipalloc-006bdefc9802f3285`) — **unmanaged**, re-associated by ID |
| Security group | `syslog-server` — 514 tcp/udp + 22 from office IPs + VPC/VPN CIDRs; 2055/2056 udp reserved (netflow/sflow) |
| IAM role | `syslog-server-role` — `AmazonSSMManagedInstanceCore` + `CloudWatchAgentServerPolicy` |
| Log group | `unifi-syslog` (90-day retention) — created/retained by the CW agent, **not** a CFN resource (holds history; see stack comment) |
| Alarm | `Syslog-NoIncomingLogs` — `IncomingLogEvents` Sum < 1 over 2×1-day, ALARM-only → `site-alerts` |
## Access
SSM Session Manager (no key pair). SSH 22 is open from office/VPC for
break-glass only.
## Deploy
CI/CD via the org reusable workflows (`ci-typescript-cdk.yaml`,
`cd-cdk.yaml`); merges to `main` deploy through the `githubdeploy-syslog-server`
OIDC role. No Docker assets, so a local `cdk deploy` is also safe.
```
npm ci
npm run diff
npm run deploy
```
## Notes
- **EIP is unmanaged.** CloudFormation associates it but never releases it, so
the public forwarding target survives any instance replacement.
- **AMI is pinned in `cdk.context.json`** (`cachedInContext`). An AL2023 AMI
change forces instance replacement — refresh deliberately with
`cdk context --reset <ami key> && cdk synth`.
- To widen device coverage of the forwarded syslog feed, see **INFRA-11**
(UniFi controller remote-logging config).

11
bin/app.ts Normal file
View file

@ -0,0 +1,11 @@
#!/usr/bin/env node
import "source-map-support/register";
import * as cdk from "aws-cdk-lib";
import { SyslogServerStack } from "../lib/syslog-server-stack";
const app = new cdk.App();
new SyslogServerStack(app, "syslog-server", {
stackName: "syslog-server",
env: { account: "328440206208", region: "us-east-1" },
});

48
cdk.context.json Normal file
View file

@ -0,0 +1,48 @@
{
"vpc-provider:account=328440206208:filter.vpc-id=vpc-0d3d4b67bd0cf8a68:region=us-east-1:returnAsymmetricSubnets=true": {
"vpcId": "vpc-0d3d4b67bd0cf8a68",
"vpcCidrBlock": "10.20.0.0/16",
"ownerAccountId": "328440206208",
"availabilityZones": [],
"vpnGatewayId": "vgw-073737d44762dffc2",
"subnetGroups": [
{
"name": "Private",
"type": "Private",
"subnets": [
{
"subnetId": "subnet-04e38c507e96f1926",
"cidr": "10.20.30.0/24",
"availabilityZone": "us-east-1a",
"routeTableId": "rtb-06a2f56f492b9b4de"
},
{
"subnetId": "subnet-0a0b4fc6f296dfba5",
"cidr": "10.20.40.0/24",
"availabilityZone": "us-east-1b",
"routeTableId": "rtb-01e152fe5cabca7d6"
}
]
},
{
"name": "Public",
"type": "Public",
"subnets": [
{
"subnetId": "subnet-0eea820effe1b3ae5",
"cidr": "10.20.10.0/24",
"availabilityZone": "us-east-1a",
"routeTableId": "rtb-0f2232493a5c43fe8"
},
{
"subnetId": "subnet-0012f5895182c1580",
"cidr": "10.20.20.0/24",
"availabilityZone": "us-east-1b",
"routeTableId": "rtb-0f2232493a5c43fe8"
}
]
}
]
},
"ssm:account=328440206208:parameterName=/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-arm64:region=us-east-1": "ami-02c114835b4e7739f"
}

21
cdk.json Normal file
View file

@ -0,0 +1,21 @@
{
"app": "npx ts-node bin/app.ts",
"watch": {
"include": ["**"],
"exclude": [
"README.md",
"cdk*.json",
"**/*.d.ts",
"**/*.js",
"tsconfig.json",
"package*.json",
"node_modules",
"cdk.out"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/core:target-partitions": ["aws"]
}
}

202
lib/syslog-server-stack.ts Normal file
View file

@ -0,0 +1,202 @@
import * as cdk from "aws-cdk-lib";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as iam from "aws-cdk-lib/aws-iam";
import * as cloudwatch from "aws-cdk-lib/aws-cloudwatch";
import * as cwactions from "aws-cdk-lib/aws-cloudwatch-actions";
import * as sns from "aws-cdk-lib/aws-sns";
import { Construct } from "constructs";
/**
* syslog-server — EC2 collector that receives remote syslog (UDP/TCP 514) from
* the office UniFi fleet over the EIP and ships it to the `unifi-syslog`
* CloudWatch Logs group via the CloudWatch agent.
*
* Brought under IaC for INFRA-12 (AWS audit L-6). Recreated to mirror the
* file-share/forgejo CDK pattern; the existing EIP (184.72.154.32) is imported
* by allocation ID and re-associated so the forwarding target is unchanged.
*
* The `unifi-syslog` log group is intentionally NOT a CloudFormation resource:
* it holds 90 days of history and is created/retained by the CloudWatch agent
* per the user-data config below (log_group_name + retention_in_days). Managing
* it as a CFN resource would either collide with the live group on create or
* risk deleting the history on a future replacement. The agent owns it; this
* stack owns the instance that runs the agent.
*/
export class SyslogServerStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const vpc = ec2.Vpc.fromLookup(this, "SeaHavenVpc", {
vpcId: "vpc-0d3d4b67bd0cf8a68",
});
// Public subnet (IGW route present) — the instance must be internet-facing
// so the office gateways can forward syslog to the EIP.
const publicSubnet = ec2.Subnet.fromSubnetAttributes(this, "PublicSubnet", {
subnetId: "subnet-0eea820effe1b3ae5",
availabilityZone: "us-east-1a",
});
// Office public IPs that forward syslog (see reference_office_ips).
const OFFICE_1 = "47.21.61.4/32";
const OFFICE_2 = "96.250.164.146/32";
const sg = new ec2.SecurityGroup(this, "SecurityGroup", {
vpc,
securityGroupName: "syslog-server",
description: "Syslog collector - rsyslog 514 from office + VPC",
allowAllOutbound: true,
});
// Remote syslog (UDP + TCP 514) from the office public IPs and the internal
// VPC / VPN CIDRs.
for (const proto of [ec2.Port.tcp(514), ec2.Port.udp(514)]) {
sg.addIngressRule(ec2.Peer.ipv4(OFFICE_1), proto, "syslog from office-1");
sg.addIngressRule(ec2.Peer.ipv4(OFFICE_2), proto, "syslog from office-2");
sg.addIngressRule(ec2.Peer.ipv4("10.10.0.0/16"), proto, "syslog from office VPN");
sg.addIngressRule(ec2.Peer.ipv4("10.20.0.0/16"), proto, "syslog from VPC");
sg.addIngressRule(ec2.Peer.ipv4("10.30.0.0/16"), proto, "syslog from VPN pool");
}
// SSH (SSM is the primary access path; 22 kept for break-glass from office/VPC).
sg.addIngressRule(ec2.Peer.ipv4(OFFICE_1), ec2.Port.tcp(22), "SSH from office-1");
sg.addIngressRule(ec2.Peer.ipv4(OFFICE_2), ec2.Port.tcp(22), "SSH from office-2");
sg.addIngressRule(ec2.Peer.ipv4("10.10.0.0/16"), ec2.Port.tcp(22), "SSH from office VPN");
sg.addIngressRule(ec2.Peer.ipv4("10.20.0.0/16"), ec2.Port.tcp(22), "SSH from VPC");
// NetFlow / sFlow ingress reserved from the office IPs. No collector is
// configured in user-data yet; kept to preserve the prior capability.
for (const port of [ec2.Port.udp(2055), ec2.Port.udp(2056)]) {
sg.addIngressRule(ec2.Peer.ipv4(OFFICE_1), port, "netflow/sflow from office-1");
sg.addIngressRule(ec2.Peer.ipv4(OFFICE_2), port, "netflow/sflow from office-2");
}
const role = new iam.Role(this, "InstanceRole", {
roleName: "syslog-server-role",
assumedBy: new iam.ServicePrincipal("ec2.amazonaws.com"),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMManagedInstanceCore"),
iam.ManagedPolicy.fromAwsManagedPolicyName("CloudWatchAgentServerPolicy"),
],
});
const userData = ec2.UserData.forLinux();
userData.addCommands(
"set -euxo pipefail",
"",
"# ── rsyslog: listen on UDP/TCP 514 ──",
"dnf install -y rsyslog",
"cat > /etc/rsyslog.d/10-listen.conf <<'EOF'",
'module(load="imudp")',
'input(type="imudp" port="514")',
'module(load="imtcp")',
'input(type="imtcp" port="514")',
"EOF",
"",
"# ── Write remote syslog to /var/log/remote/<host>/<program>.log ──",
"cat > /etc/rsyslog.d/20-remote.conf <<'EOF'",
'template(name="RemoteHost" type="string" string="/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log")',
"if $fromhost-ip != '127.0.0.1' then {",
' action(type="omfile" dynaFile="RemoteHost" createDirs="on")',
" stop",
"}",
"EOF",
"",
"mkdir -p /var/log/remote",
"systemctl enable rsyslog",
"systemctl restart rsyslog",
"",
"# ── CloudWatch agent: ship /var/log/remote/**/*.log to unifi-syslog ──",
"dnf install -y amazon-cloudwatch-agent",
"cat > /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json <<'EOF'",
"{",
' "logs": {',
' "logs_collected": {',
' "files": {',
' "collect_list": [',
" {",
' "file_path": "/var/log/remote/**/*.log",',
' "log_group_name": "unifi-syslog",',
' "log_stream_name": "{hostname}/{file_name}",',
' "retention_in_days": 90',
" }",
" ]",
" }",
" }",
" }",
"}",
"EOF",
"",
"/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \\",
" -a fetch-config -m ec2 \\",
" -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json -s",
"systemctl enable amazon-cloudwatch-agent",
);
const instance = new ec2.Instance(this, "Instance", {
instanceName: "syslog-server",
vpc,
vpcSubnets: { subnets: [publicSubnet] },
instanceType: ec2.InstanceType.of(ec2.InstanceClass.T4G, ec2.InstanceSize.NANO),
machineImage: ec2.MachineImage.latestAmazonLinux2023({
cpuType: ec2.AmazonLinuxCpuType.ARM_64,
// Cache the resolved AMI in cdk.context.json so deploys don't implicitly
// pick up new AL2023 releases (AMI change forces instance replacement).
// Refresh deliberately: cdk context --reset <ami key> && cdk synth
cachedInContext: true,
}),
securityGroup: sg,
role,
userData,
blockDevices: [
{
deviceName: "/dev/xvda",
volume: ec2.BlockDeviceVolume.ebs(30, {
volumeType: ec2.EbsDeviceVolumeType.GP3,
encrypted: true,
}),
},
],
});
// Re-associate the existing Elastic IP (184.72.154.32) so the UniFi fleet's
// forwarding target is unchanged. The allocation is UNMANAGED (referenced by
// ID) — CloudFormation can associate it but never release it.
new ec2.CfnEIPAssociation(this, "EipAssociation", {
allocationId: "eipalloc-006bdefc9802f3285",
instanceId: instance.instanceId,
});
// ALARM-only "no incoming logs" alarm to the shared site-alerts topic
// (alias/seahaven-alarm-topics CMK). Mirrors the prior standalone alarm:
// IncomingLogEvents (Sum) < 1 over two 1-day periods. 2-day window tolerates
// quiet weekends; treatMissingData=breaching catches a dead pipeline.
const alarmTopic = sns.Topic.fromTopicArn(
this, "SiteAlerts", "arn:aws:sns:us-east-1:328440206208:site-alerts",
);
const noLogsAlarm = new cloudwatch.Alarm(this, "NoIncomingLogsAlarm", {
alarmName: "Syslog-NoIncomingLogs",
alarmDescription:
"No log events delivered to unifi-syslog for 2 days — syslog pipeline may be down.",
metric: new cloudwatch.Metric({
namespace: "AWS/Logs",
metricName: "IncomingLogEvents",
dimensionsMap: { LogGroupName: "unifi-syslog" },
statistic: "Sum",
period: cdk.Duration.days(1),
}),
threshold: 1,
comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN_THRESHOLD,
evaluationPeriods: 2,
treatMissingData: cloudwatch.TreatMissingData.BREACHING,
});
noLogsAlarm.addAlarmAction(new cwactions.SnsAction(alarmTopic));
new cdk.CfnOutput(this, "InstanceId", { value: instance.instanceId });
new cdk.CfnOutput(this, "PublicIp", {
value: "184.72.154.32",
description: "Elastic IP — UniFi remote-syslog forwarding target",
});
}
}

532
package-lock.json generated Normal file
View file

@ -0,0 +1,532 @@
{
"name": "syslog-server",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "syslog-server",
"version": "1.0.0",
"dependencies": {
"aws-cdk-lib": "2.257.0",
"constructs": "^10.0.0"
},
"bin": {
"app": "bin/app.js"
},
"devDependencies": {
"@types/node": "^22.0.0",
"aws-cdk": "^2.252.0",
"source-map-support": "^0.5.21",
"typescript": "~5.7.0"
}
},
"node_modules/@aws-cdk/asset-awscli-v1": {
"version": "2.2.273",
"resolved": "https://registry.npmjs.org/@aws-cdk/asset-awscli-v1/-/asset-awscli-v1-2.2.273.tgz",
"integrity": "sha512-X57HYUtHt9BQrlrzUNcMyRsDUCoakYNnY6qh5lNwRCHPtQoTfXmuISkfLk0AjLkcbS5lw1LLTQFiQhTDXfiTvg==",
"license": "Apache-2.0"
},
"node_modules/@aws-cdk/asset-node-proxy-agent-v6": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@aws-cdk/asset-node-proxy-agent-v6/-/asset-node-proxy-agent-v6-2.1.2.tgz",
"integrity": "sha512-pDiuqH+qY3zM9lhhLjbKJ1tnKOHzQ2V4Wr/3qsxyKeKAkuPMI/BVGvZG1PbrikUw949cGVTfVEt4ETKKYnrj0Q==",
"license": "Apache-2.0"
},
"node_modules/@aws-cdk/cloud-assembly-schema": {
"version": "53.28.0",
"resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-53.28.0.tgz",
"integrity": "sha512-pZS+9bLGv2tCqcgxfA0WD3XjcqT3yE4ICvKeJEicw6aTdCxBl8FQ/AUsorY/6f2JrMS3kUQgvhXxA30MWcji0A==",
"bundleDependencies": [
"jsonschema",
"semver"
],
"license": "Apache-2.0",
"dependencies": {
"jsonschema": "^1.5.0",
"semver": "^7.8.0"
},
"engines": {
"node": ">= 18.0.0"
}
},
"node_modules/@aws-cdk/cloud-assembly-schema/node_modules/jsonschema": {
"version": "1.5.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/@aws-cdk/cloud-assembly-schema/node_modules/semver": {
"version": "7.8.0",
"inBundle": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@types/node": {
"version": "22.19.20",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.20.tgz",
"integrity": "sha512-6tELRwSDYWW9EdZhbeZmYGZ1/7Djkt+Ah3/ScEYT9cDord7UJzasR/4D3VONg9tQI5CDp+/CZC1AXj2pCFOvpw==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/aws-cdk": {
"version": "2.1126.0",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1126.0.tgz",
"integrity": "sha512-uNoocb3vCPiAT3j9+SwL6pn/VVggHWBsgC2XpxyhNvYQYt6cE9BM/149GWwtdcwnLrPjnwW1+CV/5nSSh5dV+w==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"cdk": "bin/cdk"
},
"engines": {
"node": ">= 18.0.0"
}
},
"node_modules/aws-cdk-lib": {
"version": "2.257.0",
"resolved": "https://registry.npmjs.org/aws-cdk-lib/-/aws-cdk-lib-2.257.0.tgz",
"integrity": "sha512-GoHfWklrBJcMwLtDlY64pvaT7cD2KyDXC8sik89DR6jHl6nQsBtYTKSJCM+C/k4jgXaecbv8myNX75FySejq0A==",
"bundleDependencies": [
"@balena/dockerignore",
"@aws-cdk/cloud-assembly-api",
"case",
"fs-extra",
"ignore",
"jsonschema",
"minimatch",
"punycode",
"semver",
"table",
"yaml",
"mime-types"
],
"license": "Apache-2.0",
"dependencies": {
"@aws-cdk/asset-awscli-v1": "2.2.273",
"@aws-cdk/asset-node-proxy-agent-v6": "^2.1.1",
"@aws-cdk/cloud-assembly-api": "^2.2.4",
"@aws-cdk/cloud-assembly-schema": "^53.25.0",
"@balena/dockerignore": "^1.0.2",
"case": "1.6.3",
"fs-extra": "^11.3.3",
"ignore": "^5.3.2",
"jsonschema": "^1.5.0",
"mime-types": "^2.1.35",
"minimatch": "^10.2.3",
"punycode": "^2.3.1",
"semver": "^7.7.4",
"table": "^6.9.0",
"yaml": "1.10.3"
},
"engines": {
"node": ">= 20.0.0"
},
"peerDependencies": {
"constructs": "^10.5.0"
}
},
"node_modules/aws-cdk-lib/node_modules/@aws-cdk/cloud-assembly-api": {
"version": "2.2.4",
"inBundle": true,
"license": "Apache-2.0",
"dependencies": {
"jsonschema": "^1.5.0",
"semver": "^7.8.0"
},
"engines": {
"node": ">= 18.0.0"
},
"peerDependencies": {
"@aws-cdk/cloud-assembly-schema": ">=53.25.0"
}
},
"node_modules/aws-cdk-lib/node_modules/@aws-cdk/cloud-assembly-api/node_modules/semver": {
"version": "7.8.0",
"inBundle": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/aws-cdk-lib/node_modules/@balena/dockerignore": {
"version": "1.0.2",
"inBundle": true,
"license": "Apache-2.0"
},
"node_modules/aws-cdk-lib/node_modules/ajv": {
"version": "8.18.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/aws-cdk-lib/node_modules/ansi-regex": {
"version": "5.0.1",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/aws-cdk-lib/node_modules/ansi-styles": {
"version": "4.3.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/aws-cdk-lib/node_modules/astral-regex": {
"version": "2.0.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/aws-cdk-lib/node_modules/balanced-match": {
"version": "4.0.4",
"inBundle": true,
"license": "MIT",
"engines": {
"node": "18 || 20 || >=22"
}
},
"node_modules/aws-cdk-lib/node_modules/brace-expansion": {
"version": "5.0.5",
"inBundle": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^4.0.2"
},
"engines": {
"node": "18 || 20 || >=22"
}
},
"node_modules/aws-cdk-lib/node_modules/case": {
"version": "1.6.3",
"inBundle": true,
"license": "(MIT OR GPL-3.0-or-later)",
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/aws-cdk-lib/node_modules/color-convert": {
"version": "2.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/aws-cdk-lib/node_modules/color-name": {
"version": "1.1.4",
"inBundle": true,
"license": "MIT"
},
"node_modules/aws-cdk-lib/node_modules/emoji-regex": {
"version": "8.0.0",
"inBundle": true,
"license": "MIT"
},
"node_modules/aws-cdk-lib/node_modules/fast-deep-equal": {
"version": "3.1.3",
"inBundle": true,
"license": "MIT"
},
"node_modules/aws-cdk-lib/node_modules/fast-uri": {
"version": "3.1.2",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"inBundle": true,
"license": "BSD-3-Clause"
},
"node_modules/aws-cdk-lib/node_modules/fs-extra": {
"version": "11.3.3",
"inBundle": true,
"license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
"node": ">=14.14"
}
},
"node_modules/aws-cdk-lib/node_modules/graceful-fs": {
"version": "4.2.11",
"inBundle": true,
"license": "ISC"
},
"node_modules/aws-cdk-lib/node_modules/ignore": {
"version": "5.3.2",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/aws-cdk-lib/node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/aws-cdk-lib/node_modules/json-schema-traverse": {
"version": "1.0.0",
"inBundle": true,
"license": "MIT"
},
"node_modules/aws-cdk-lib/node_modules/jsonfile": {
"version": "6.2.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"universalify": "^2.0.0"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/aws-cdk-lib/node_modules/jsonschema": {
"version": "1.5.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/aws-cdk-lib/node_modules/lodash.truncate": {
"version": "4.4.2",
"inBundle": true,
"license": "MIT"
},
"node_modules/aws-cdk-lib/node_modules/mime-db": {
"version": "1.52.0",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/aws-cdk-lib/node_modules/mime-types": {
"version": "2.1.35",
"inBundle": true,
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/aws-cdk-lib/node_modules/minimatch": {
"version": "10.2.5",
"inBundle": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"brace-expansion": "^5.0.5"
},
"engines": {
"node": "18 || 20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/aws-cdk-lib/node_modules/punycode": {
"version": "2.3.1",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/aws-cdk-lib/node_modules/require-from-string": {
"version": "2.0.2",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/aws-cdk-lib/node_modules/semver": {
"version": "7.7.4",
"inBundle": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/aws-cdk-lib/node_modules/slice-ansi": {
"version": "4.0.0",
"inBundle": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"astral-regex": "^2.0.0",
"is-fullwidth-code-point": "^3.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
}
},
"node_modules/aws-cdk-lib/node_modules/string-width": {
"version": "4.2.3",
"inBundle": true,
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/aws-cdk-lib/node_modules/strip-ansi": {
"version": "6.0.1",
"inBundle": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/aws-cdk-lib/node_modules/table": {
"version": "6.9.0",
"inBundle": true,
"license": "BSD-3-Clause",
"dependencies": {
"ajv": "^8.0.1",
"lodash.truncate": "^4.4.2",
"slice-ansi": "^4.0.0",
"string-width": "^4.2.3",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/aws-cdk-lib/node_modules/universalify": {
"version": "2.0.1",
"inBundle": true,
"license": "MIT",
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/aws-cdk-lib/node_modules/yaml": {
"version": "1.10.3",
"inBundle": true,
"license": "ISC",
"engines": {
"node": ">= 6"
}
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true,
"license": "MIT"
},
"node_modules/constructs": {
"version": "10.6.0",
"resolved": "https://registry.npmjs.org/constructs/-/constructs-10.6.0.tgz",
"integrity": "sha512-TxHOnBO5zMo/G76ykzGF/wMpEHu257TbWiIxP9K0Yv/+t70UzgBQiTqjkAsWOPC6jW91DzJI0+ehQV6xDRNBuQ==",
"license": "Apache-2.0"
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true,
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/typescript": {
"version": "5.7.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"dev": true,
"license": "MIT"
}
}
}

24
package.json Normal file
View file

@ -0,0 +1,24 @@
{
"name": "syslog-server",
"version": "1.0.0",
"bin": {
"app": "bin/app.js"
},
"scripts": {
"build": "tsc",
"cdk": "cdk",
"synth": "cdk synth",
"deploy": "cdk deploy",
"diff": "cdk diff"
},
"devDependencies": {
"@types/node": "^22.0.0",
"aws-cdk": "^2.252.0",
"source-map-support": "^0.5.21",
"typescript": "~5.7.0"
},
"dependencies": {
"aws-cdk-lib": "2.257.0",
"constructs": "^10.0.0"
}
}

24
tsconfig.json Normal file
View file

@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "commonjs",
"lib": ["ES2022"],
"types": ["node"],
"declaration": true,
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"inlineSourceMap": true,
"inlineSources": true,
"strictPropertyInitialization": false,
"outDir": "./cdk.out",
"rootDir": ".",
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"esModuleInterop": true
},
"exclude": ["node_modules", "cdk.out"]
}