Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 14 additions & 14 deletions cmd/homerunner/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (

"github.com/matrix-org/complement/internal/config"
"github.com/matrix-org/complement/internal/docker"
"github.com/matrix-org/complement/internal/federation"
"github.com/sirupsen/logrus"
)

Expand All @@ -25,6 +24,19 @@ type Config struct {
Snapshot string
}

func (c *Config) DeriveComplementConfig(baseImageURI string) *config.Complement {
cfg := &config.Complement{
BaseImageURI: baseImageURI,
DebugLoggingEnabled: true,
SpawnHSTimeout: c.SpawnHSTimeout,
KeepBlueprints: c.KeepBlueprints,
BestEffort: true,
PackageNamespace: Pkg,
}
_ = cfg.GenerateCA()
return cfg
}

func NewConfig() *Config {
cfg := &Config{
HomeserverLifetimeMins: 30,
Expand All @@ -46,14 +58,7 @@ func NewConfig() *Config {
}

func cleanup(c *Config) {
cfg := &config.Complement{
PackageNamespace: Pkg,
BaseImageURI: "nothing",
DebugLoggingEnabled: true,
SpawnHSTimeout: c.SpawnHSTimeout,
KeepBlueprints: c.KeepBlueprints,
BestEffort: true,
}
cfg := c.DeriveComplementConfig("nothing")
builder, err := docker.NewBuilder(cfg)
if err != nil {
logrus.WithError(err).Fatalf("failed to run cleanup")
Expand All @@ -69,11 +74,6 @@ func main() {
}
cleanup(cfg)

_, _, err = federation.GetOrCreateCaCert()
if err != nil {
logrus.Fatalf("failed to make CA certs")
}

if cfg.Snapshot != "" {
logrus.Infof("Running in single-shot snapshot mode for request file '%s'", cfg.Snapshot)
// pretend the file is the request
Expand Down
9 changes: 1 addition & 8 deletions cmd/homerunner/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"time"

"github.com/matrix-org/complement/internal/b"
"github.com/matrix-org/complement/internal/config"
"github.com/matrix-org/complement/internal/docker"
"github.com/sirupsen/logrus"
)
Expand Down Expand Up @@ -36,13 +35,7 @@ func (r *Runtime) CreateDeployment(imageURI string, blueprint *b.Blueprint) (*do
return nil, expires, fmt.Errorf("blueprint must be supplied")
}
namespace := "homerunner_" + blueprint.Name
cfg := &config.Complement{
BaseImageURI: imageURI,
DebugLoggingEnabled: true,
SpawnHSTimeout: r.Config.SpawnHSTimeout,
BestEffort: true,
PackageNamespace: Pkg,
}
cfg := r.Config.DeriveComplementConfig(imageURI)
builder, err := docker.NewBuilder(cfg)
if err != nil {
return nil, expires, err
Expand Down
87 changes: 87 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package config

import (
"bytes"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"fmt"
"math/big"
"os"
"strconv"
"strings"
Expand All @@ -18,6 +25,10 @@ type Complement struct {
KeepBlueprints []string
// The namespace for all complement created blueprints and deployments
PackageNamespace string
// Certificate Authority generated values for this run of complement. Homeservers will use this
// as a base to derive their own signed Federation certificates.
CACertificate *x509.Certificate
CAPrivateKey *rsa.PrivateKey
}

func NewConfigFromEnvVars() *Complement {
Expand All @@ -37,9 +48,40 @@ func NewConfigFromEnvVars() *Complement {
panic("COMPLEMENT_BASE_IMAGE must be set")
}
cfg.PackageNamespace = "pkg"

// create CA certs and keys
if err := cfg.GenerateCA(); err != nil {
panic("Failed to generate CA certificate/key: " + err.Error())
}

return cfg
}

func (c *Complement) GenerateCA() error {
cert, key, err := generateCAValues()
if err != nil {
return err
}
c.CACertificate = cert
c.CAPrivateKey = key
return nil
}

func (c *Complement) CACertificateBytes() ([]byte, error) {
cert := bytes.NewBuffer(nil)
err := pem.Encode(cert, &pem.Block{Type: "CERTIFICATE", Bytes: c.CACertificate.Raw})
return cert.Bytes(), err
}

func (c *Complement) CAPrivateKeyBytes() ([]byte, error) {
caKey := bytes.NewBuffer(nil)
err := pem.Encode(caKey, &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: x509.MarshalPKCS1PrivateKey(c.CAPrivateKey),
})
return caKey.Bytes(), err
}

func parseEnvWithDefault(key string, def int) int {
s := os.Getenv(key)
if s != "" {
Expand All @@ -52,3 +94,48 @@ func parseEnvWithDefault(key string, def int) int {
}
return def
}

// Generate a certificate and private key
func generateCAValues() (*x509.Certificate, *rsa.PrivateKey, error) {
// valid for 10 years
certificateDuration := time.Hour * 24 * 365 * 10
priv, err := rsa.GenerateKey(rand.Reader, 4096)
if err != nil {
return nil, nil, err
}
notBefore := time.Now()
notAfter := notBefore.Add(certificateDuration)
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return nil, nil, err
}
caCert := x509.Certificate{
SerialNumber: serialNumber,
NotBefore: notBefore,
NotAfter: notAfter,
IsCA: true,
KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature | x509.KeyUsageCRLSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
Subject: pkix.Name{
Organization: []string{"matrix.org"},
Country: []string{"GB"},
Province: []string{"London"},
Locality: []string{"London"},
StreetAddress: []string{"123 Street"},
PostalCode: []string{"12345"},
},
}

derBytes, err := x509.CreateCertificate(rand.Reader, &caCert, &caCert, &priv.PublicKey, priv)
if err != nil {
return nil, nil, err
}
selfSignedCert, err := x509.ParseCertificates(derBytes)
if err != nil {
return nil, nil, err
}

return selfSignedCert[0], priv, nil
}
16 changes: 6 additions & 10 deletions internal/docker/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,8 @@ var (
const complementLabel = "complement_context"

type Builder struct {
Config *config.Complement
CSAPIPort int
FederationPort int
Docker *client.Client
Config *config.Complement
Docker *client.Client
}

func NewBuilder(cfg *config.Complement) (*Builder, error) {
Expand All @@ -53,10 +51,8 @@ func NewBuilder(cfg *config.Complement) (*Builder, error) {
return nil, err
}
return &Builder{
Docker: cli,
Config: cfg,
CSAPIPort: 8008,
FederationPort: 8448,
Docker: cli,
Config: cfg,
}, nil
}

Expand Down Expand Up @@ -362,9 +358,9 @@ func (d *Builder) deployBaseImage(blueprintName string, hs b.Homeserver, context
asIDToRegistrationMap := asIDToRegistrationFromLabels(labelsForApplicationServices(hs))

return deployImage(
d.Docker, d.Config.BaseImageURI, d.CSAPIPort, fmt.Sprintf("complement_%s", contextStr),
d.Docker, d.Config.BaseImageURI, fmt.Sprintf("complement_%s", contextStr),
d.Config.PackageNamespace, blueprintName, hs.Name, asIDToRegistrationMap, contextStr,
networkID, d.Config.SpawnHSTimeout, d.Config.DebugLoggingEnabled,
networkID, d.Config,
)
}

Expand Down
Loading