diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..13566b81
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/kittywitch.iml b/.idea/kittywitch.iml
new file mode 100644
index 00000000..5e764c4f
--- /dev/null
+++ b/.idea/kittywitch.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 00000000..3473b4e6
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..35eb1ddf
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Pulumi.mew.yaml b/Pulumi.mew.yaml
index d61fcb9b..3c707a12 100644
--- a/Pulumi.mew.yaml
+++ b/Pulumi.mew.yaml
@@ -1,6 +1,6 @@
config:
cloudflare:apiToken:
- secure: AAABACPPwldgPSVHPYdh4lQnYR+baaGsnQRwGw/qwNke8wuFnCTdZIqj6yXu0CCGaYBu0+66LTALNNl9mo9HXs/PMLmoOqLo
+ secure: AAABAFcufTX7tZZf2gcK6hML2tgovDEfcPAJcgjfYkV3GMS4Ilwzuco5p+hCpyj3vCm7cqm3tmdwOLlOFxGqKZGRj+ESXAzv
tailscale:apiKey:
secure: AAABAGc7s7XJ+voSUNcMmRuVwrUdx3kojn0fdEl6qpUy0WmhgHbk6cEz2/kGSEGhuLGwo3mzOGVTI+NVu6/Xz4PmE9FME++VfE8cz5DFjDrMJ4JdX0DR
tailscale:tailnet: inskip.me
diff --git a/config.yaml b/config.yaml
index fccebd0c..6880e924 100644
--- a/config.yaml
+++ b/config.yaml
@@ -6,6 +6,8 @@ zones:
flags: 0
tag: iodef
value: mailto:acme@inskip.me
+ - kind: cname
+ value: inskip-root.pages.dev
- kind: caa
flags: 0
tag: issue
diff --git a/darwin/distributed.nix b/darwin/distributed.nix
index 36b43168..73a306eb 100644
--- a/darwin/distributed.nix
+++ b/darwin/distributed.nix
@@ -1,5 +1,16 @@
-_: {
+{ pkgs, ... }: {
nix.envVars = {
"SSH_AUTH_SOCK" = "/Users/kat/.gnupg/S.gpg-agent.ssh";
};
+
+ launchd.daemons.start_nixos_native = {
+ serviceConfig.ProgramArguments = [
+ "/bin/sh" "-c"
+ "/bin/wait4path /nix/store && ${pkgs.writeScript "start_nixos_native" ''
+ /usr/bin/open "utm://start?name=NixOS Native"
+ ''}"
+ ];
+ serviceConfig.Label = "org.kittywitch.start_nixos_native";
+ serviceConfig.RunAtLoad = true;
+ };
}
diff --git a/flake.lock b/flake.lock
index ebb48eb1..800c0dda 100644
--- a/flake.lock
+++ b/flake.lock
@@ -24,11 +24,11 @@
"arcexprs": {
"flake": false,
"locked": {
- "lastModified": 1674878824,
- "narHash": "sha256-skuyKtydzGFtd2UQB2BZW2bMaUcS+fvHEEz+H4MNQ4g=",
+ "lastModified": 1675107003,
+ "narHash": "sha256-ao5OLwhC7+T3O2ixRrt76gIg9uZR3c17SJL3Wvx0EpQ=",
"owner": "arcnmx",
"repo": "nixexprs",
- "rev": "ab1bd348da95d6f33ad28992b5d8c636d2330cc9",
+ "rev": "5b7d1eb5e578da7ed36b2105f80f82f9ad11244d",
"type": "github"
},
"original": {
@@ -126,11 +126,11 @@
]
},
"locked": {
- "lastModified": 1674771519,
- "narHash": "sha256-U0W3S1nX6yEvLh3Vq70EORbmXecAKXfmEfCfaA4A+I8=",
+ "lastModified": 1675181178,
+ "narHash": "sha256-jymSUUjKoArptU7LJ1i4boysXptnpuETiUTenKgs2fM=",
"owner": "nix-community",
"repo": "home-manager",
- "rev": "bb4b25b302dbf0f527f190461b080b5262871756",
+ "rev": "69696fe53940562a047bf2ec675cc1dcd1bc09b3",
"type": "github"
},
"original": {
@@ -173,11 +173,11 @@
]
},
"locked": {
- "lastModified": 1674357402,
- "narHash": "sha256-oxOCYORXBh0KW4KEwKpzs2LThDdVmEwREV+SsP4CIpg=",
+ "lastModified": 1674962474,
+ "narHash": "sha256-qEXdgW5fnMSdQwP1zQYa0fVtI0f3G1f2qNRjUEherCs=",
"owner": "Mic92",
"repo": "nix-index-database",
- "rev": "e9e7c5c62965e7e656febb5ba578d53f751eb41f",
+ "rev": "a385f6192f5471c4cebeeb0d2e966b5ccf123df5",
"type": "github"
},
"original": {
@@ -188,11 +188,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1674641431,
- "narHash": "sha256-qfo19qVZBP4qn5M5gXc/h1MDgAtPA5VxJm9s8RUAkVk=",
+ "lastModified": 1675115703,
+ "narHash": "sha256-4zetAPSyY0D77x+Ww9QBe8RHn1akvIvHJ/kgg8kGDbk=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "9b97ad7b4330aacda9b2343396eb3df8a853b4fc",
+ "rev": "2caf4ef5005ecc68141ecb4aac271079f7371c44",
"type": "github"
},
"original": {
@@ -205,11 +205,11 @@
"pypi-deps-db": {
"flake": false,
"locked": {
- "lastModified": 1674855014,
- "narHash": "sha256-SMUq72uWWs+KAlcRB7UXzI1QHNTGiUTpQK2qj1evHXQ=",
+ "lastModified": 1675156620,
+ "narHash": "sha256-lmnsBYJz2Fgm0WFNUgSqskpwa0ffbFOr9YGDZpUXptk=",
"owner": "DavHau",
"repo": "pypi-deps-db",
- "rev": "a375715227007ca768d372b2b09bcb76f8f19d78",
+ "rev": "2e236bb32e6e3ef13cd56fc6d9aee8c89059a1ac",
"type": "github"
},
"original": {
diff --git a/iac/ca.go b/iac/ca.go
index 0e65ba5b..c5bad50a 100644
--- a/iac/ca.go
+++ b/iac/ca.go
@@ -1,40 +1,45 @@
package iac
-import(
- "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
- tls "github.com/pulumi/pulumi-tls/sdk/v4/go/tls"
+import (
+ tls "github.com/pulumi/pulumi-tls/sdk/v4/go/tls"
+ "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
-func GenerateTLSCA(ctx *pulumi.Context) (key *tls.PrivateKey, cert *tls.SelfSignedCert, err error) {
- key, err = tls.NewPrivateKey(ctx, "kat-root-ca-key", &tls.PrivateKeyArgs{
- Algorithm: pulumi.String("RSA"),
- RsaBits: pulumi.Int(4096),
- })
-
- if err != nil {
- return nil, nil, err
- }
-
- cert, err = tls.NewSelfSignedCert(ctx, "kat-root-ca-pem-cert", &tls.SelfSignedCertArgs{
- PrivateKeyPem: key.PrivateKeyPem,
- AllowedUses: goStringArrayToPulumiStringArray([]string{"digital_signature",
- "cert_signing",
- "crl_signing"}),
- IsCaCertificate: pulumi.Bool(true),
- ValidityPeriodHours: pulumi.Int(2562047),
- Subject: &tls.SelfSignedCertSubjectArgs{
- CommonName: pulumi.String("inskip.me"),
- Organization: pulumi.String("Kat Inskip"),
- },
- })
-
- if err != nil {
- return nil, nil, err
- }
-
- ctx.Export("tls_ca_pem_key", key.PrivateKeyPem)
- ctx.Export("tls_ca_os_key", key.PrivateKeyOpenssh)
- ctx.Export("tls_ca_cert", cert.CertPem)
-
- return key, cert, err
+type CertificateAuthority struct {
+ Key *tls.PrivateKey
+ Cert *tls.SelfSignedCert
+}
+
+func (ca *CertificateAuthority) handle(ctx *pulumi.Context) (err error) {
+ ca.Key, err = tls.NewPrivateKey(ctx, "ca-root", &tls.PrivateKeyArgs{
+ Algorithm: pulumi.String("RSA"),
+ RsaBits: pulumi.Int(4096),
+ })
+
+ if err != nil {
+ return err
+ }
+
+ ca.Cert, err = tls.NewSelfSignedCert(ctx, "ca-root", &tls.SelfSignedCertArgs{
+ PrivateKeyPem: ca.Key.PrivateKeyPem,
+ AllowedUses: goStringArrayToPulumiStringArray([]string{"digital_signature",
+ "cert_signing",
+ "crl_signing"}),
+ IsCaCertificate: pulumi.Bool(true),
+ ValidityPeriodHours: pulumi.Int(2562047),
+ Subject: &tls.SelfSignedCertSubjectArgs{
+ CommonName: pulumi.String("inskip.me"),
+ Organization: pulumi.String("Kat Inskip"),
+ },
+ })
+
+ if err != nil {
+ return err
+ }
+
+ ctx.Export("ca_pem_privkey", ca.Key.PrivateKeyPem)
+ ctx.Export("ca_os_privkey", ca.Key.PrivateKeyOpenssh)
+ ctx.Export("ca_pem_cert", ca.Cert.CertPem)
+
+ return err
}
diff --git a/iac/config.go b/iac/config.go
index 072bea85..0cd46194 100644
--- a/iac/config.go
+++ b/iac/config.go
@@ -1,5 +1,5 @@
package iac
type KatConfig struct {
- Zones map[string]Zone `yaml:"zones"`
+ Zones map[string]Zone `yaml:"zones"`
}
diff --git a/iac/device.go b/iac/device.go
new file mode 100644
index 00000000..ddf83fa1
--- /dev/null
+++ b/iac/device.go
@@ -0,0 +1,205 @@
+package iac
+
+import (
+ "crypto/rand"
+ "fmt"
+ "github.com/pulumi/pulumi-command/sdk/go/command/remote"
+ "github.com/pulumi/pulumi-tailscale/sdk/go/tailscale"
+ "github.com/pulumi/pulumi-tls/sdk/v4/go/tls"
+ "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
+ "golang.org/x/crypto/ssh"
+ "net"
+ "strings"
+ "time"
+)
+
+type Tailnet struct {
+ Devices []Device
+ Zone *Zone
+}
+
+func (t *Tailnet) handle(ctx *pulumi.Context, zone *Zone, CAKey *tls.PrivateKey, CACert *tls.SelfSignedCert) (err error) {
+ t.Zone = zone
+ tailnet, err := tailscale.GetDevices(ctx, &tailscale.GetDevicesArgs{}, nil)
+ if err != nil {
+ return err
+ }
+ for _, device := range tailnet.Devices {
+ device_ := Device{
+ Addresses: device.Addresses,
+ Id: device.Id,
+ Name: device.Name,
+ Tags: device.Tags,
+ User: device.User,
+ }
+ err = device_.handle(ctx, zone, CAKey, CACert)
+ if err != nil {
+ return err
+ }
+ t.Devices = append(t.Devices, device_)
+ }
+ return err
+}
+
+type Device struct {
+ Addresses []string
+ Id string
+ Name string
+ Hostname string
+ Tailskip string
+ Tags []string
+ User string
+ Files []*remote.Command
+ Context *pulumi.Context
+ Records []DNSRecord
+ PrivateKey *tls.PrivateKey
+ TLSCertRequest *tls.CertRequest
+ TLSCert *tls.LocallySignedCert
+ OSHCertificate pulumi.StringOutput
+}
+
+func (d *Device) handle(ctx *pulumi.Context, zone *Zone, CAKey *tls.PrivateKey, CACert *tls.SelfSignedCert) (err error) {
+ d.Context = ctx
+ d.Records = make([]DNSRecord, 0, 50)
+ d.Files = make([]*remote.Command, 0, 20)
+ d.Hostname = strings.Split(d.Name, ".")[0]
+ d.Tailskip = fmt.Sprintf("%s.inskip.me", d.Hostname)
+ if d.User != "kat@inskip.me" {
+ return nil
+ }
+ err = d.record(zone)
+ if err != nil {
+ return err
+ }
+ if d.Hostname != "koishi" {
+ return err
+ }
+ err = d.handleTLS(CAKey, CACert)
+ if err != nil {
+ return err
+ }
+ err = d.handleOSH(CAKey)
+ if err != nil {
+ return err
+ }
+ return err
+}
+
+func (d *Device) handleOSH(CAKey *tls.PrivateKey) (err error) {
+ d.OSHCertificate = CAKey.PrivateKeyOpenssh.ApplyT(func(CAPriv string) pulumi.StringOutput {
+ OSHCertificate_ := d.PrivateKey.PrivateKeyOpenssh.ApplyT(func(UserPriv string) pulumi.String {
+ CARSAPriv, err := PrivateKeyOpenSSHToRSAPrivateKey(CAPriv)
+ if err != nil {
+ panic(err)
+ }
+ signer, err := ssh.NewSignerFromKey(CARSAPriv)
+ if err != nil {
+ panic(err)
+ }
+ var cert ssh.Certificate
+ cert.Nonce = make([]byte, 32)
+ cert.CertType = 2
+ UserRSAPriv, err := PrivateKeyOpenSSHToRSAPrivateKey(UserPriv)
+ if err != nil {
+ panic(err)
+ }
+ cert.Key, err = ssh.NewPublicKey(UserRSAPriv.Public())
+ if err != nil {
+ panic(err)
+ }
+ cert.Serial = 0
+ cert.KeyId = d.Tailskip
+ cert.ValidPrincipals = []string{d.Tailskip}
+ cert.ValidAfter = 60
+ threeMonths, err := time.ParseDuration("730h")
+ if err != nil {
+ panic(err)
+ }
+ threeMonthsInSeconds := uint64(threeMonths.Seconds())
+ cert.ValidBefore = threeMonthsInSeconds
+ err = cert.SignCert(rand.Reader, signer)
+ return pulumi.String(string(ssh.MarshalAuthorizedKey(&cert)))
+ }).(pulumi.StringOutput)
+ return OSHCertificate_
+ }).(pulumi.StringOutput)
+ file, err := CreatePulumiFile(d.Context, fmt.Sprintf("%s-osh-cert", d.Hostname), d.Tailskip, d.OSHCertificate, []pulumi.Resource{d.PrivateKey, CAKey})
+ d.Files = append(d.Files, file)
+ return err
+}
+
+func (d *Device) record(zone *Zone) (err error) {
+ for _, address := range d.Addresses {
+ ip := net.ParseIP(address)
+ kind := A
+ if ip.To4() == nil {
+ kind = AAAA
+ }
+ record := DNSRecord{
+ Name: d.Hostname,
+ Kind: kind,
+ Value: ip.String(),
+ Ttl: 3600,
+ }
+ err = record.handle(d.Context, zone)
+ if err != nil {
+ return err
+ }
+ d.Records = append(d.Records, record)
+ }
+ return err
+}
+
+func (d *Device) handleTLS(CAKey *tls.PrivateKey, CACert *tls.SelfSignedCert) (err error) {
+ PrivateKeyDepends := []pulumi.Resource{CAKey, CACert}
+ d.PrivateKey, err = tls.NewPrivateKey(d.Context, fmt.Sprintf("%s-key", d.Hostname), &tls.PrivateKeyArgs{
+ Algorithm: pulumi.String("RSA"),
+ RsaBits: pulumi.Int(4096),
+ }, pulumi.DependsOn(PrivateKeyDepends))
+ if err != nil {
+ return err
+ }
+ PrivateKeyDepends = append(PrivateKeyDepends, d.PrivateKey)
+ file, err := CreatePulumiFile(d.Context, fmt.Sprintf("%s-pem-pk", d.Hostname), d.Tailskip, d.PrivateKey.PrivateKeyPem, PrivateKeyDepends)
+ if err != nil {
+ return err
+ }
+ d.Files = append(d.Files, file)
+ file, err = CreatePulumiFile(d.Context, fmt.Sprintf("%s-osh-pk", d.Hostname), d.Tailskip, d.PrivateKey.PrivateKeyOpenssh, PrivateKeyDepends)
+ if err != nil {
+ return err
+ }
+ d.Files = append(d.Files, file)
+ TLSCertRequestDepends := []pulumi.Resource{CAKey, CACert, d.PrivateKey}
+ d.TLSCertRequest, err = tls.NewCertRequest(d.Context, fmt.Sprintf("%s-tls-cr", d.Hostname), &tls.CertRequestArgs{
+ PrivateKeyPem: d.PrivateKey.PrivateKeyPem,
+ DnsNames: goStringArrayToPulumiStringArray([]string{d.Hostname}),
+ IpAddresses: goStringArrayToPulumiStringArray(d.Addresses),
+ Subject: &tls.CertRequestSubjectArgs{
+ CommonName: pulumi.String("inskip.me"),
+ Organization: pulumi.String("Kat Inskip"),
+ },
+ }, pulumi.DependsOn(TLSCertRequestDepends))
+ if err != nil {
+ return err
+ }
+ TLSCertDepends := []pulumi.Resource{CAKey, CACert, d.TLSCertRequest, d.PrivateKey}
+ d.TLSCert, err = tls.NewLocallySignedCert(d.Context, fmt.Sprintf("%s-tls-cert", d.Hostname), &tls.LocallySignedCertArgs{
+ AllowedUses: goStringArrayToPulumiStringArray([]string{"digital_signature",
+ "digital_signature",
+ "key_encipherment",
+ "key_agreement",
+ "email_protection",
+ }),
+ CaPrivateKeyPem: CAKey.PrivateKeyPem,
+ CaCertPem: CACert.CertPem,
+ CertRequestPem: d.TLSCertRequest.CertRequestPem,
+ ValidityPeriodHours: pulumi.Int(1440),
+ EarlyRenewalHours: pulumi.Int(168),
+ }, pulumi.DependsOn(TLSCertDepends))
+ file, err = CreatePulumiFile(d.Context, fmt.Sprintf("%s-pem-cert", d.Hostname), d.Tailskip, d.TLSCert.CertPem, TLSCertDepends)
+ d.Files = append(d.Files, file)
+ if err != nil {
+ return err
+ }
+ return err
+}
diff --git a/iac/dns.go b/iac/dns.go
deleted file mode 100644
index 301234f7..00000000
--- a/iac/dns.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package iac
-
-import(
- "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
- cloudflare "github.com/pulumi/pulumi-cloudflare/sdk/v4/go/cloudflare"
- "fmt"
-)
-
-func HandleDNS(ctx *pulumi.Context, config KatConfig) (zones map[string]*cloudflare.Zone, dnssec map[string]*cloudflare.ZoneDnssec, records map[string]*cloudflare.Record, err error) {
- zones = make(map[string]*cloudflare.Zone)
- dnssec = make(map[string]*cloudflare.ZoneDnssec)
- records = make(map[string]*cloudflare.Record)
-
- for name, zone := range config.Zones {
- ctx.Log.Info(fmt.Sprintf("Handling zone %s", name), nil)
- zones[name], err = zone.handle(ctx, name)
- if err != nil {
- return nil, nil, nil, err
- }
- dnssec[name], err = cloudflare.NewZoneDnssec(ctx, fmt.Sprintf("%s-dnssec", name), &cloudflare.ZoneDnssecArgs{
- ZoneId: zones[name].ID(),
- })
- if err != nil {
- return nil, nil, nil, err
- }
- for _, record := range zone.Records {
- record_, err := record.handle(ctx, name, zones[name])
- if err != nil {
- return nil, nil, nil, err
- }
- record_index := record.getName(name, zones[name])
- records[record_index] = record_
- }
- }
-
- return zones, dnssec, records, err
-}
diff --git a/iac/files.go b/iac/files.go
index ada8a01e..a42f1600 100644
--- a/iac/files.go
+++ b/iac/files.go
@@ -1,43 +1,23 @@
package iac
import (
- "github.com/pulumi/pulumi-command/sdk/go/command/local"
- "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
- "github.com/pulumi/pulumi-tls/sdk/v4/go/tls"
- "fmt"
- "os"
- "path"
+ "github.com/pulumi/pulumi-command/sdk/go/command/remote"
+ "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
-func createPulumiFile(ctx *pulumi.Context, name string, value pulumi.StringOutput, resource pulumi.Resource) (*local.Command, error) {
- repo_root := os.Getenv("REPO_ROOT")
- data_root := path.Join(repo_root, "./data")
- ctx.Export(name, value)
- return local.NewCommand(ctx, name, &local.CommandArgs{
- Create: pulumi.String(fmt.Sprintf("pulumi stack output %s --non-interactive --show-secrets > %s", name, name)),
- Update: pulumi.String(fmt.Sprintf("pulumi stack output %s --non-interactive --show-secrets > %s", name, name)),
- Delete: pulumi.String(fmt.Sprintf("rm %s", name)),
- Dir: pulumi.String(data_root),
- Environment: goMapToPulumiMap(map[string]string{
- "PULUMI_SKIP_UPDATE_CHECK": "true",
- }),
- }, pulumi.DependsOn([]pulumi.Resource{resource}))
-}
-
-func PKITLSFiles(ctx *pulumi.Context, files_ map[string]*local.Command, keys map[string]*tls.PrivateKey, certs map[string]*tls.LocallySignedCert) (files map[string]*local.Command, err error) {
- for name_, key := range keys {
- name := fmt.Sprintf("%s-file", name_)
- files_[name], err = createPulumiFile(ctx, name, key.PrivateKeyPem, key)
- if err != nil {
- return nil, err
- }
- }
- for name_, cert := range certs {
- name := fmt.Sprintf("%s-file", name_)
- files_[name], err = createPulumiFile(ctx, name, cert.CertPem, cert)
- if err != nil {
- return nil, err
- }
- }
- return files_, err
+func CreatePulumiFile(ctx *pulumi.Context, name string, fqdn string, value pulumi.StringOutput, resources []pulumi.Resource) (*remote.Command, error) {
+ environment := goMapToPulumiMap(map[string]string{
+ "PULUMI_SKIP_UPDATE_CHECK": "true",
+ })
+ return remote.NewCommand(ctx, name, &remote.CommandArgs{
+ Connection: &remote.ConnectionArgs{
+ Host: pulumi.String(fqdn),
+ Port: pulumi.Float64Ptr(22),
+ User: pulumi.String("deploy"),
+ AgentSocketPath: pulumi.String("/Users/kat/.gnupg/S.gpg-agent.ssh"),
+ },
+ Create: pulumi.Sprintf("sudo mkdir -p /var/lib/secrets && sudo chown deploy:users -R /var/lib/secrets && cd /var/lib/secrets && echo \"%s\" > \"%s\"", value, name),
+ Delete: pulumi.Sprintf("cd /var/lib/secrets && rm %s", name),
+ Environment: environment,
+ }, pulumi.DependsOn(resources))
}
diff --git a/iac/inskip.go b/iac/inskip.go
new file mode 100644
index 00000000..b9953f97
--- /dev/null
+++ b/iac/inskip.go
@@ -0,0 +1,93 @@
+package iac
+
+import (
+ "github.com/pulumi/pulumi-cloudflare/sdk/v4/go/cloudflare"
+ "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
+)
+
+func InskipPage(ctx *pulumi.Context) error {
+ _, err := cloudflare.NewPagesProject(ctx, "inskip-root", &cloudflare.PagesProjectArgs{
+ AccountId: pulumi.ID("0467b993b65d8fd4a53fe24ed2fbb2a1"),
+ Name: pulumi.String("inskip-root"),
+ ProductionBranch: pulumi.String("main"),
+ BuildConfig: &cloudflare.PagesProjectBuildConfigArgs{
+ BuildCommand: pulumi.String("hugo"),
+ DestinationDir: pulumi.String("public"),
+ RootDir: pulumi.String("/"),
+ },
+ Source: &cloudflare.PagesProjectSourceArgs{
+ Type: pulumi.String("github"),
+ Config: &cloudflare.PagesProjectSourceConfigArgs{
+ DeploymentsEnabled: pulumi.Bool(true),
+ Owner: pulumi.String("kittywitch"),
+ PrCommentsEnabled: pulumi.Bool(false),
+ PreviewBranchExcludes: pulumi.StringArray{
+ pulumi.String("main"),
+ pulumi.String("prod"),
+ },
+ PreviewBranchIncludes: pulumi.StringArray{
+ pulumi.String("dev"),
+ pulumi.String("preview"),
+ },
+ PreviewDeploymentSetting: pulumi.String("custom"),
+ ProductionBranch: pulumi.String("main"),
+ ProductionDeploymentEnabled: pulumi.Bool(true),
+ RepoName: pulumi.String("inskip.me"),
+ },
+ },
+ DeploymentConfigs: &cloudflare.PagesProjectDeploymentConfigsArgs{
+ Preview: &cloudflare.PagesProjectDeploymentConfigsPreviewArgs{
+ CompatibilityDate: pulumi.String("2022-08-15"),
+ CompatibilityFlags: pulumi.StringArray{},
+ /* D1Databases: pulumi.AnyMap{
+ "D1BINDING": pulumi.Any("445e2955-951a-4358-a35b-a4d0c813f63"),
+ },
+ DurableObjectNamespaces: pulumi.AnyMap{
+ "DOBINDING": pulumi.Any("5eb63bbbe01eeed093cb22bb8f5acdc3"),
+ },
+ EnvironmentVariables: pulumi.AnyMap{
+ "ENVIRONMENT": pulumi.Any("preview"),
+ },
+ KvNamespaces: pulumi.AnyMap{
+ "KVBINDING": pulumi.Any("5eb63bbbe01eeed093cb22bb8f5acdc3"),
+ },
+ R2Buckets: pulumi.AnyMap{
+ "R2BINDING": pulumi.Any("some-bucket"),
+ }, */
+ },
+ Production: &cloudflare.PagesProjectDeploymentConfigsProductionArgs{
+ CompatibilityDate: pulumi.String("2022-08-16"),
+ CompatibilityFlags: pulumi.StringArray{},
+ /*D1Databases: pulumi.AnyMap{
+ "D1BINDING1": pulumi.Any("445e2955-951a-4358-a35b-a4d0c813f63"),
+ "D1BINDING2": pulumi.Any("a399414b-c697-409a-a688-377db6433cd9"),
+ },
+ DurableObjectNamespaces: pulumi.AnyMap{
+ "DOBINDING1": pulumi.Any("5eb63bbbe01eeed093cb22bb8f5acdc3"),
+ "DOBINDING2": pulumi.Any("3cdca5f8bb22bc390deee10ebbb36be5"),
+ },
+ EnvironmentVariables: pulumi.AnyMap{
+ "ENVIRONMENT": pulumi.Any("production"),
+ "OTHERVALUE": pulumi.Any("other value"),
+ },
+ KvNamespaces: pulumi.AnyMap{
+ "KVBINDING1": pulumi.Any("5eb63bbbe01eeed093cb22bb8f5acdc3"),
+ "KVBINDING2": pulumi.Any("3cdca5f8bb22bc390deee10ebbb36be5"),
+ },
+ R2Buckets: pulumi.AnyMap{
+ "R2BINDING1": pulumi.Any("some-bucket"),
+ "R2BINDING2": pulumi.Any("other-bucket"),
+ },*/
+ },
+ },
+ })
+ _, err = cloudflare.NewPagesDomain(ctx, "inskip-root", &cloudflare.PagesDomainArgs{
+ AccountId: pulumi.String("0467b993b65d8fd4a53fe24ed2fbb2a1"),
+ Domain: pulumi.String("inskip.me"),
+ ProjectName: pulumi.String("inskip-root"),
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/iac/record.go b/iac/record.go
index cf93772d..70695230 100644
--- a/iac/record.go
+++ b/iac/record.go
@@ -1,93 +1,102 @@
package iac
import (
- "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
- cloudflare "github.com/pulumi/pulumi-cloudflare/sdk/v4/go/cloudflare"
- "github.com/creasty/defaults"
- "fmt"
- "strings"
- "crypto/md5"
- "encoding/hex"
+ "crypto/md5"
+ "encoding/hex"
+ "fmt"
+ "github.com/creasty/defaults"
+ "github.com/pulumi/pulumi-cloudflare/sdk/v4/go/cloudflare"
+ "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
+ "strings"
)
type DNSRecordType string
const (
- A DNSRecordType = "a"
- AAAA = "aaaa"
- MX = "mx"
- TXT = "txt"
- CAA = "caa"
+ A DNSRecordType = "a"
+ AAAA = "aaaa"
+ MX = "mx"
+ TXT = "txt"
+ CAA = "caa"
+ CNAME = "cname"
)
type DNSRecord struct {
- Name string `default:"@" yaml:"name"`
- Kind DNSRecordType `yaml:"kind"`
- Value string `yaml:"value,omitempty"`
- Priority int `yaml:"priority,omitempty"`
- Flags string `yaml:"flags,omitempty"`
- Tag string `yaml:"tag,omitempty"`
- Ttl int `default:"3600" yaml:"ttl,omitempty"`
+ CFRecord *cloudflare.Record
+ Zone *Zone
+ Name string `default:"@" yaml:"name"`
+ Kind DNSRecordType `yaml:"kind"`
+ Value string `yaml:"value,omitempty"`
+ Priority int `yaml:"priority,omitempty"`
+ Flags string `yaml:"flags,omitempty"`
+ Tag string `yaml:"tag,omitempty"`
+ Ttl int `default:"3600" yaml:"ttl,omitempty"`
}
-func (r *DNSRecord) UnmarshalYAML(unmarshal func(interface{}) error) error {
- defaults.Set(r)
+func (r *DNSRecord) UnmarshalYAML(unmarshal func(interface{}) error) (err error) {
+ err = defaults.Set(r)
- type plain DNSRecord
- if err := unmarshal((*plain)(r)); err != nil {
- return err
- }
+ if err != nil {
+ return err
+ }
- return nil
+ type plain DNSRecord
+ if err := unmarshal((*plain)(r)); err != nil {
+ return err
+ }
+
+ return err
}
-func (r *DNSRecord) getZone(Zone *cloudflare.Zone) (pulumi.StringOutput) {
- return Zone.ID().ToStringOutput()
+func (r *DNSRecord) getZone() pulumi.StringOutput {
+ return r.Zone.CFZone.ID().ToStringOutput()
}
-func (r *DNSRecord) getName(ZoneName string, Zone *cloudflare.Zone) (string) {
- base := fmt.Sprintf("%s-%s-%s", ZoneName, r.Kind, r.Name)
+func (r *DNSRecord) getName() string {
+ base := fmt.Sprintf("%s-%s-%s", r.Zone.Alias, r.Kind, r.Name)
- hash := md5.Sum([]byte(r.Value))
- hashString := hex.EncodeToString(hash[:])[:5]
- suffix := ""
- switch r.Kind {
- case MX:
- suffix = fmt.Sprintf("-%d-%s", r.Priority, hashString)
- case CAA:
- suffix = fmt.Sprintf("%s-%s", r.Flags, r.Tag)
- case A, AAAA, TXT:
- suffix = fmt.Sprintf("-%s", hashString)
- }
+ hash := md5.Sum([]byte(r.Value))
+ hashString := hex.EncodeToString(hash[:])[:5]
+ suffix := ""
+ switch r.Kind {
+ case MX:
+ suffix = fmt.Sprintf("-%d-%s", r.Priority, hashString)
+ case CAA:
+ suffix = fmt.Sprintf("%s-%s", r.Flags, r.Tag)
+ case A, AAAA, TXT, CNAME:
+ suffix = fmt.Sprintf("-%s", hashString)
+ }
- built := base + suffix
- return built
+ built := base + suffix
+ return built
}
-func (r *DNSRecord) handle(ctx *pulumi.Context, ZoneName string, zone *cloudflare.Zone) (*cloudflare.Record, error) {
- var recordArgs *cloudflare.RecordArgs
- switch r.Kind {
- case CAA:
- recordArgs = &cloudflare.RecordArgs{
- ZoneId: r.getZone(zone),
- Name: pulumi.String(r.Name),
- Type: pulumi.String(strings.ToUpper(string(r.Kind))),
- Ttl: pulumi.Int(r.Ttl),
- Data: &cloudflare.RecordDataArgs{
- Flags: pulumi.String(r.Flags),
- Tag: pulumi.String(r.Tag),
- Value: pulumi.String(r.Value),
- },
- }
- default:
- recordArgs = &cloudflare.RecordArgs{
- ZoneId: r.getZone(zone),
- Name: pulumi.String(r.Name),
- Type: pulumi.String(strings.ToUpper(string(r.Kind))),
- Ttl: pulumi.Int(r.Ttl),
- Priority: pulumi.Int(r.Priority),
- Value: pulumi.String(r.Value),
- }
- }
- return cloudflare.NewRecord(ctx, r.getName(ZoneName, zone), recordArgs)
+func (r *DNSRecord) handle(ctx *pulumi.Context, zone *Zone) (err error) {
+ r.Zone = zone
+ var recordArgs *cloudflare.RecordArgs
+ switch r.Kind {
+ case CAA:
+ recordArgs = &cloudflare.RecordArgs{
+ ZoneId: r.getZone(),
+ Name: pulumi.String(r.Name),
+ Type: pulumi.String(strings.ToUpper(string(r.Kind))),
+ Ttl: pulumi.Int(r.Ttl),
+ Data: &cloudflare.RecordDataArgs{
+ Flags: pulumi.String(r.Flags),
+ Tag: pulumi.String(r.Tag),
+ Value: pulumi.String(r.Value),
+ },
+ }
+ default:
+ recordArgs = &cloudflare.RecordArgs{
+ ZoneId: r.getZone(),
+ Name: pulumi.String(r.Name),
+ Type: pulumi.String(strings.ToUpper(string(r.Kind))),
+ Ttl: pulumi.Int(r.Ttl),
+ Priority: pulumi.Int(r.Priority),
+ Value: pulumi.String(r.Value),
+ }
+ }
+ r.CFRecord, err = cloudflare.NewRecord(ctx, r.getName(), recordArgs, pulumi.DependsOn([]pulumi.Resource{r.Zone.CFZone}))
+ return err
}
diff --git a/iac/ssh.go b/iac/ssh.go
index e69de29b..5831d87a 100644
--- a/iac/ssh.go
+++ b/iac/ssh.go
@@ -0,0 +1,91 @@
+package iac
+
+import (
+ "crypto/rand"
+ "crypto/rsa"
+ "fmt"
+ tls "github.com/pulumi/pulumi-tls/sdk/v4/go/tls"
+ "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
+ "golang.org/x/crypto/ssh"
+ "time"
+)
+
+// ca_key *tls.PrivateKey,
+// ca_cert *tls.SelfSignedCert) (key *tls.PrivateKey,
+// ca_key, ca_cert, err := iac.GenerateTLSCA(ctx)
+
+// parseprivatekey
+// newsignerfromkey
+
+func MakeCertificate() ssh.Certificate {
+ var newCert ssh.Certificate
+ // The sign() method fills in Nonce for us
+ newCert.Nonce = make([]byte, 32)
+ return newCert
+}
+
+func PrivateKeyOpenSSHToRSAPrivateKey(keyPEM string) (key *rsa.PrivateKey, err error) {
+ key_int, err := ssh.ParseRawPrivateKey([]byte(keyPEM))
+ key_raw := key_int.(*rsa.PrivateKey)
+ if err != nil {
+ return nil, err
+ }
+ return key_raw, err
+}
+
+func GenerateOpenSSHHost(caKey *tls.PrivateKey, userKey *tls.PrivateKey, keyID string, name string) (certificate pulumi.StringOutput, err error) {
+ return GenerateOpenSSH(caKey, userKey, keyID, ssh.HostCert, name)
+}
+
+func GenerateOpenSSHUser(caKey *tls.PrivateKey, userKey *tls.PrivateKey, keyID string, name string) (certificate pulumi.StringOutput, err error) {
+ return GenerateOpenSSH(caKey, userKey, keyID, ssh.UserCert, name)
+}
+
+func GenerateOpenSSH(caKey *tls.PrivateKey, userKey *tls.PrivateKey, keyID string, certType uint32, name string) (certificate pulumi.StringOutput, err error) {
+ var caKeyPem *rsa.PrivateKey
+ var signer ssh.Signer
+
+ newCert := caKey.PrivateKeyOpenssh.ApplyT(func(capriv string) (cert pulumi.StringOutput) {
+ newCertS := userKey.PrivateKeyOpenssh.ApplyT(func(content string) (cert pulumi.String) {
+ caKeyPem, err = PrivateKeyOpenSSHToRSAPrivateKey(capriv)
+ if err != nil {
+ panic(err)
+ }
+ signer, err = ssh.NewSignerFromKey(caKeyPem)
+ if err != nil {
+ panic(err)
+ }
+ newCert := MakeCertificate()
+ newCert.CertType = certType
+ key, err := PrivateKeyOpenSSHToRSAPrivateKey(content)
+ if err != nil {
+ panic(err)
+ }
+ newCert.Key, err = ssh.NewPublicKey(key.Public())
+ if err != nil {
+ panic(err)
+ }
+ newCert.Serial = 0
+ newCert.KeyId = keyID
+ newCert.ValidPrincipals = []string{fmt.Sprintf("%s.inskip.me", name)}
+ newCert.ValidAfter = 60
+ threemo, err := time.ParseDuration("730h")
+ if err != nil {
+ panic(err)
+ }
+ threemosecs := uint64(threemo.Seconds())
+ newCert.ValidBefore = threemosecs
+ err = newCert.SignCert(rand.Reader, signer)
+ return pulumi.String(string(ssh.MarshalAuthorizedKey(&newCert)))
+ }).(pulumi.StringOutput)
+ if err != nil {
+ panic(err)
+ }
+ return newCertS
+ }).(pulumi.StringOutput)
+
+ if err != nil {
+ return pulumi.StringOutput{}, err
+ }
+ return newCert, err
+}
diff --git a/iac/tailscale.go b/iac/tailscale.go
deleted file mode 100644
index e469d5d1..00000000
--- a/iac/tailscale.go
+++ /dev/null
@@ -1,110 +0,0 @@
-package iac
-
-import (
- "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
- tailscale "github.com/pulumi/pulumi-tailscale/sdk/go/tailscale"
- cloudflare "github.com/pulumi/pulumi-cloudflare/sdk/v4/go/cloudflare"
- tls "github.com/pulumi/pulumi-tls/sdk/v4/go/tls"
- "strings"
- "net"
- "fmt"
-)
-
-func MakeRecord(ctx *pulumi.Context, zones map[string]*cloudflare.Zone, name string, address string) (record *cloudflare.Record, index string, err error) {
- ip := net.ParseIP(address)
- kind := A;
- if ip.To4() == nil {
- kind = AAAA;
- }
- record_ := DNSRecord{
- Name: name,
- Kind: kind,
- Value: ip.String(),
- Ttl: 3600,
- }
- record, err = record_.handle(ctx, "inskip", zones["inskip"])
- index = record_.getName("inskip", zones["inskip"])
- if err != nil {
- return nil, "", err
- }
- return record, index, err
-}
-
-func HandleTSRecord(ctx *pulumi.Context, zones map[string]*cloudflare.Zone, device tailscale.GetDevicesDevice) (new_records map[string]*cloudflare.Record, err error) {
- if device.User != "kat@inskip.me" {
- return nil, nil
- }
- new_records = make(map[string]*cloudflare.Record)
- name := strings.Split(device.Name, ".")[0]
- for _, address := range device.Addresses {
- new_record, index, err := MakeRecord(ctx, zones, name, address)
- new_records[index] = new_record
- if err != nil {
- return nil, err
- }
- }
- return new_records, err
-}
-
-func HandleTSRecords(ctx *pulumi.Context,
- tailnet *tailscale.GetDevicesResult,
- zones map[string]*cloudflare.Zone,
- input_records map[string]*cloudflare.Record,
-) (records map[string]*cloudflare.Record, err error) {
- for _, device := range tailnet.Devices {
- new_records, err := HandleTSRecord(ctx, zones, device)
- if err != nil {
- return nil, err
- }
- for k,v := range new_records {
- input_records[k] = v
- }
- records = input_records
- }
- return records, err
-}
-
-func HandleTSHostCert(ctx *pulumi.Context,
- device tailscale.GetDevicesDevice,
- ca_key *tls.PrivateKey,
- ca_cert *tls.SelfSignedCert) (key *tls.PrivateKey,
- cr *tls.CertRequest,
- cert *tls.LocallySignedCert,
- err error) {
- name := strings.Split(device.Name, ".")[0]
- key, cr, cert, err = generateKeyPair(
- ctx,
- fmt.Sprintf("ts-%s-host", name),
- ca_key,
- ca_cert,
- []string{fmt.Sprintf("%s.inskip.me", name)},
- device.Addresses,
- )
- if err != nil {
- return nil, nil, nil, err
- }
- return key, cr, cert, err
-}
-
-func HandleTSHostCerts(ctx *pulumi.Context,
- tailnet *tailscale.GetDevicesResult,
- ca_key *tls.PrivateKey,
- ca_cert *tls.SelfSignedCert) (keys map[string]*tls.PrivateKey,
- crs map[string]*tls.CertRequest,
- certs map[string]*tls.LocallySignedCert,
- err error) {
- keys = make(map[string]*tls.PrivateKey)
- crs = make(map[string]*tls.CertRequest)
- certs = make(map[string]*tls.LocallySignedCert)
- for _, device := range tailnet.Devices {
- if device.User != "kat@inskip.me" {
- continue
- }
- name := strings.Split(device.Name, ".")[0]
- keys[fmt.Sprintf("ts-%s-host-key", name)], crs[fmt.Sprintf("ts-%s-host-cr", name)], certs[fmt.Sprintf("ts-%s-host-cert", name)], err = HandleTSHostCert(ctx, device, ca_key, ca_cert)
- if err != nil {
- return nil, nil, nil, err
- }
- }
- return keys, crs, certs, err
-}
diff --git a/iac/tls.go b/iac/tls.go
deleted file mode 100644
index cce3867a..00000000
--- a/iac/tls.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package iac
-
-import (
- "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
- tls "github.com/pulumi/pulumi-tls/sdk/v4/go/tls"
- "fmt"
-)
-
-func generateKeyPair(ctx *pulumi.Context,
- purpose string,
- ca_key *tls.PrivateKey,
- ca_cert *tls.SelfSignedCert,
- dns_names []string,
- ip_addresses []string) (key *tls.PrivateKey,
- cr *tls.CertRequest,
- cert *tls.LocallySignedCert,
- err error) {
- key, err = tls.NewPrivateKey(ctx, fmt.Sprintf("%s-key", purpose), &tls.PrivateKeyArgs{
- Algorithm: pulumi.String("RSA"),
- RsaBits: pulumi.Int(4096),
- }, pulumi.DependsOn([]pulumi.Resource{ca_key, ca_cert}))
- if err != nil {
- return nil, nil, nil, err
- }
- cr, err = tls.NewCertRequest(ctx, fmt.Sprintf("%s-cr", purpose), &tls.CertRequestArgs{
- PrivateKeyPem: key.PrivateKeyPem,
- DnsNames: goStringArrayToPulumiStringArray(dns_names),
- IpAddresses: goStringArrayToPulumiStringArray(ip_addresses),
- Subject: &tls.CertRequestSubjectArgs{
- CommonName: pulumi.String("inskip.me"),
- Organization: pulumi.String("Kat Inskip"),
- },
- }, pulumi.DependsOn([]pulumi.Resource{ca_key, ca_cert, key}))
- if err != nil {
- return nil, nil, nil, err
- }
- cert, err = tls.NewLocallySignedCert(ctx, fmt.Sprintf("%s-cert", purpose), &tls.LocallySignedCertArgs{
- AllowedUses: goStringArrayToPulumiStringArray([]string{"digital_signature",
- "digital_signature",
- "key_encipherment",
- "key_agreement",
- "email_protection",
- }),
- CaPrivateKeyPem: ca_key.PrivateKeyPem,
- CaCertPem: ca_cert.CertPem,
- CertRequestPem: cr.CertRequestPem,
- ValidityPeriodHours: pulumi.Int(1440),
- EarlyRenewalHours: pulumi.Int(168),
- }, pulumi.DependsOn([]pulumi.Resource{ca_key, ca_cert, key, cr}))
- if err != nil {
- return nil, nil, nil, err
- }
- return key, cr, cert, err
-}
diff --git a/iac/zone.go b/iac/zone.go
index 8190674c..4927a8a5 100644
--- a/iac/zone.go
+++ b/iac/zone.go
@@ -1,24 +1,63 @@
package iac
import (
- "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
- cloudflare "github.com/pulumi/pulumi-cloudflare/sdk/v4/go/cloudflare"
+ cloudflare "github.com/pulumi/pulumi-cloudflare/sdk/v4/go/cloudflare"
+ "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
+ "strings"
)
type Zone struct {
- Zone string `yaml:"name"`
- Records []DNSRecord `yaml:"records"`
+ Context *pulumi.Context
+ Alias string
+ Zone string `yaml:"name"`
+ ExtraRecords []DNSRecord `yaml:"records"`
+ CFZone *cloudflare.Zone
+ Devices []Device
+ CertAuth CertificateAuthority
+ DNSSec *cloudflare.ZoneDnssec
}
-func (z *Zone) handle(ctx *pulumi.Context, name string) (zone *cloudflare.Zone, err error) {
- zone, err = cloudflare.NewZone(ctx, name, &cloudflare.ZoneArgs{
- AccountId: pulumi.ID("0467b993b65d8fd4a53fe24ed2fbb2a1"),
- Zone: pulumi.String(z.Zone),
- Plan: pulumi.String("free"),
- })
- if err != nil {
- return nil, err
- }
- return zone, err
+func (z *Zone) Handle(ctx *pulumi.Context) (err error) {
+ z.Context = ctx
+ z.Alias = strings.ReplaceAll(z.Zone, ".", "-")
+ z.CFZone, err = cloudflare.NewZone(ctx, z.Alias, &cloudflare.ZoneArgs{
+ AccountId: pulumi.ID("0467b993b65d8fd4a53fe24ed2fbb2a1"),
+ Zone: pulumi.String(z.Zone),
+ Plan: pulumi.String("free"),
+ })
+ if z.Alias == "inskip-me" {
+ z.CertAuth = CertificateAuthority{}
+ err = z.CertAuth.handle(ctx)
+ if err != nil {
+ return err
+ }
+ err = z.handleTailscale()
+ if err != nil {
+ return err
+ }
+ }
+ for _, record := range z.ExtraRecords {
+ err = record.handle(ctx, z)
+ }
+ return err
}
+func (z *Zone) dnssec() (err error) {
+ z.DNSSec, err = cloudflare.NewZoneDnssec(z.Context, z.Alias, &cloudflare.ZoneDnssecArgs{
+ ZoneId: z.CFZone.ID(),
+ })
+ if err != nil {
+ return err
+ }
+ return err
+}
+
+func (z *Zone) handleTailscale() (err error) {
+ tailnet := Tailnet{}
+ err = tailnet.handle(z.Context, z, z.CertAuth.Key, z.CertAuth.Cert)
+ if err != nil {
+ return err
+ }
+ z.Devices = tailnet.Devices
+ return err
+}
diff --git a/kat/user/nixos.nix b/kat/user/nixos.nix
index 173e728c..128653a4 100644
--- a/kat/user/nixos.nix
+++ b/kat/user/nixos.nix
@@ -2,6 +2,7 @@
users.users.kat = {
uid = 1000;
isNormalUser = true;
+ hashedPassword = "$6$G26zDwcywO6$YzHK1YI6X0d7x/mV6maCx6B7V3M1JdE3VqxxjNc7muxUPkZo0YYwniAB2";
openssh.authorizedKeys = {
inherit (tree.kat.user.data) keys;
};
diff --git a/main.go b/main.go
index 7d5cd480..52d45ac6 100644
--- a/main.go
+++ b/main.go
@@ -1,68 +1,38 @@
package main
import (
- "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
- "github.com/pulumi/pulumi-tailscale/sdk/go/tailscale"
- "gopkg.in/yaml.v3"
- "os"
- "kittywitch/iac"
- "github.com/pulumi/pulumi-command/sdk/go/command/local"
+ "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
+ "gopkg.in/yaml.v3"
+ "kittywitch/iac"
+ "os"
)
func main() {
- katConfig := iac.KatConfig{}
+ store := iac.KatConfig{}
- configFile, err := os.ReadFile("config.yaml")
+ configFile, err := os.ReadFile("config.yaml")
- if err != nil {
- return
- }
+ if err != nil {
+ return
+ }
- if err := yaml.Unmarshal(configFile, &katConfig); err != nil {
- return
- }
+ if err := yaml.Unmarshal(configFile, &store); err != nil {
+ return
+ }
- pulumi.Run(func(ctx *pulumi.Context) error {
- tailnet, err := tailscale.GetDevices(ctx, &tailscale.GetDevicesArgs{}, nil)
- if err != nil {
- return err
- }
+ pulumi.Run(func(ctx *pulumi.Context) error {
+ for _, zone := range store.Zones {
+ err = zone.Handle(ctx)
+ if err != nil {
+ return err
+ }
+ }
- // zones, dnssec, records
- zones, _, records, err := iac.HandleDNS(ctx, katConfig)
+ err = iac.InskipPage(ctx)
+ if err != nil {
+ return err
+ }
- if err != nil {
- return err
- }
-
- records, err = iac.HandleTSRecords(ctx, tailnet, zones, records)
-
- if err != nil {
- return err
- }
-
- ca_key, ca_cert, err := iac.GenerateTLSCA(ctx)
-
- if err != nil {
- return err
- }
-
- keys, _, certs, err := iac.HandleTSHostCerts(ctx, tailnet, ca_key, ca_cert)
-
- if err != nil {
- return err
- }
-
- // files for those certs
-
- files := make(map[string]*local.Command)
-
- files, err = iac.PKITLSFiles(ctx, files, keys, certs)
-
- if err != nil {
- return err
- }
-
- return err
- })
+ return err
+ })
}
diff --git a/modules/common/distributed.nix b/modules/common/distributed.nix
index 824baa79..1ed3cf02 100644
--- a/modules/common/distributed.nix
+++ b/modules/common/distributed.nix
@@ -1,6 +1,6 @@
{ lib, config, inputs, ... }: let
# TODO: convert to nix-std
- inherit (lib.attrsets) mapAttrsToList mapAttrs;
+ inherit (lib.attrsets) mapAttrsToList mapAttrs filterAttrs;
inherit (lib.lists) optionals;
inherit (lib.options) mkOption;
inherit (lib.types) int attrsOf submodule;
@@ -13,7 +13,7 @@
maxJobs = 100;
speedFactor = config.distributed.outputs.${name};
supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ];
- } ) (inputs.self.nixosConfigurations // inputs.self.darwinConfigurations);
+ } ) (filterAttrs (n: _: n != config.networking.hostName) (inputs.self.nixosConfigurations // inputs.self.darwinConfigurations));
daiyousei = {
hostName = "daiyousei.inskip.me";
sshUser = "root";
diff --git a/systems/sumireko.nix b/systems/sumireko.nix
index 29e02fb9..c440c4ea 100644
--- a/systems/sumireko.nix
+++ b/systems/sumireko.nix
@@ -9,6 +9,17 @@ _: let
distributed.systems.renko.preference = 5;
+ environment.systemPackages = with pkgs; [
+ fd # fd, better fine!
+ ripgrep # rg, better grep!
+ go # Required for pulumi
+ pulumi-bin # Infrastructure as code
+ deadnix # dead-code scanner
+ alejandra # code formatter
+ statix # anti-pattern finder
+ deploy-rs.deploy-rs # deployment system
+ ];
+
homebrew = {
brewPrefix = "/opt/homebrew/bin";
brews = [