diff --git a/config b/config index 099c48a..c87059b 160000 --- a/config +++ b/config @@ -1 +1 @@ -Subproject commit 099c48acfad1cc0f4a6f09cbf0e691604f9d2f74 +Subproject commit c87059bbe4d1478e6319e02c2eda35a68f369beb diff --git a/config.go b/config.go index e78ac9c..61f544f 100644 --- a/config.go +++ b/config.go @@ -7,12 +7,13 @@ import ( ) type platform struct { - Domain domainConfig `json:"domain"` - Firewall firewallConfig `json:"firewall"` - Instance instanceConfig `json:"instance"` - Region string `json:"region"` - Tags []string `json:"tags"` - Volumes []volumeConfig `json:"volumes"` + Domain domainConfig `json:"domain"` + Firewall firewallConfig `json:"firewall"` + Instance instanceConfig `json:"instance"` + Region string `json:"region"` + Tags []string `json:"tags"` + Volumes []volumeConfig `json:"volumes"` + StackScript stackScriptConfig `json:"stackScript"` } type domainConfig struct { @@ -62,6 +63,14 @@ type volumeConfig struct { Size int32 `json:"size"` } +type stackScriptConfig struct { + Label string `json:"label"` + Description string `json:"description"` + Public bool `json:"public"` + SharedGroupGid int32 `json:"sharedGroupGid"` + AuthorizedKey string `json:"authorizedKey"` +} + func newConfig(path string) (*platform, error) { f, err := os.Open(path) if err != nil { diff --git a/main.go b/main.go index 0bb9dd6..0a77fdf 100644 --- a/main.go +++ b/main.go @@ -2,8 +2,10 @@ package main import ( "fmt" + "bytes" "os" "strconv" + "text/template" "github.com/pulumi/pulumi-linode/sdk/v3/go/linode" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" @@ -23,6 +25,10 @@ func infra(ctx *pulumi.Context) error { if err != nil { return fmt.Errorf("unable to load the platform configuration; %w", err) } + + if err := stackscript(ctx, p); err != nil { + return fmt.Errorf("unable to manage the StackScript; %w", err) + } instanceDetails, err := instance(ctx, p); if err != nil { @@ -193,6 +199,46 @@ func instance(ctx *pulumi.Context, cfg *platform) (instanceOutput, error) { return output, nil } +func stackscript(ctx *pulumi.Context, cfg *platform) error { + script, err := stackscriptText(cfg) + if err != nil { + return err + } + + args := linode.StackScriptArgs{ + Label: pulumi.String(cfg.StackScript.Label), + Description: pulumi.String(cfg.StackScript.Description), + Script: pulumi.String(script), + IsPublic: pulumi.Bool(cfg.StackScript.Public), + Images: pulumi.StringArray{ + pulumi.String("linode/alpine3.17"), + pulumi.String("linode/alpine3.16"), + }, + } + + _, err = linode.NewStackScript(ctx, cfg.StackScript.Label, &args) + if err != nil { + return fmt.Errorf("unable to update StackScript; %w", err) + } + + return nil +} + +func stackscriptText(cfg *platform) (string, error) { + tmpl, err := template.New("stackscript.gotmpl").ParseFiles("./templates/stackscript.gotmpl") + if err != nil { + return "", fmt.Errorf("unable to get the StackScript template; %w", err) + } + + var b bytes.Buffer + + if err := tmpl.Execute(&b, cfg); err != nil { + return "", err + } + + return b.String(), nil +} + func readme(ctx *pulumi.Context) error { data, err := os.ReadFile("./README.md") if err != nil { diff --git a/templates/stackscript.gotmpl b/templates/stackscript.gotmpl new file mode 100644 index 0000000..08c40de --- /dev/null +++ b/templates/stackscript.gotmpl @@ -0,0 +1,46 @@ +#!/bin/sh + +set -e + +# Upgrade system and install required packages +apk update +apk upgrade + +apk add \ + curl \ + docker \ + openntpd \ + openssh \ + shadow \ + tzdata + +groupadd -g {{ .StackScript.SharedGroupGid }} shared-flow +groupadd -g 1001 flow +useradd -s /bin/bash -g 1001 -u 1001 -m -G docker,shared-flow flow + +mkdir /home/flow/.ssh +chmod 0700 /home/flow/.ssh +chown flow:flow /home/flow/.ssh +touch /home/flow/.ssh/authorized_keys +chown flow:flow /home/flow/.ssh/authorized_keys +chmod 0600 /home/flow/.ssh/authorized_keys +echo "{{ .StackScript.AuthorizedKey }}" | tee /home/flow/.ssh/authorized_keys + +# TODO: Mount volume and edit /etc/fstab + +# TODO: SSH Hardening (backup original config) +# Port 3142 +# PermitRootLogin no +# PasswordAuthentication no +# PermitEmptyPasswords no +# AllowTcpForwarding no +# GatewayPorts no +# X11Forwarding no + +# Set the timezone and local time +mkdir -p /etc/zoneinfo/Europe +chmod -R 0755 /etc/zoneinfo +cp /usr/share/zoneinfo/Europe/London /etc/zoneinfo/Europe/ +ln -fs /etc/zoneinfo/Europe/London /etc/localtime +echo "Europe/London" > /etc/timezone +apk del tzdata