aboutsummaryrefslogtreecommitdiff
path: root/server/config/config.go
blob: 82ddfec2af648baaa1197a3be3232b0419fd6fa2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package config

import (
	"os"
	"strconv"

	"github.com/hashicorp/go-multierror"
	"github.com/homemade/scl"
	"github.com/pkg/errors"
)

// Config holds the final server configuration.
type Config struct {
	Server *Server `hcl:"server"`
	Github *Github `hcl:"github"`
	SSH    *SSH    `hcl:"ssh"`
}

// Server holds the configuration specific to the web server and sessions.
type Server struct {
	Addr         string `hcl:"address"`
	Port         int    `hcl:"port"`
	User         string `hcl:"user"`
	CookieSecret string `hcl:"cookie_secret"`
	SecureCookie bool   `hcl:"secure_cookie"`
	CSRFSecret   string `hcl:"csrf_secret"`
	HTTPLogFile  string `hcl:"http_logfile"`
}

// Auth holds the configuration specific to the OAuth provider.
type Github struct {
	OauthClientID     string   `hcl:"oauth_client_id"`
	OauthClientSecret string   `hcl:"oauth_client_secret"`
	OauthCallbackURL  string   `hcl:"oauth_callback_url"`
	UsersWhitelist    []string `hcl:"users_whitelist"`
	OrgsWhitelist     []string `hcl:"orgs_whitelist"`
}

// SSH holds the configuration specific to signing ssh keys.
type SSH struct {
	SigningKey           string   `hcl:"signing_key"`
	AdditionalPrincipals []string `hcl:"additional_principals"`
	MaxAge               string   `hcl:"max_age"`
	Permissions          []string `hcl:"permissions"`
}

func verifyConfig(c *Config) error {
	var err error
	if c.SSH == nil {
		err = multierror.Append(err, errors.New("missing ssh config section"))
	}
	if c.Github == nil {
		err = multierror.Append(err, errors.New("missing github config section"))
	}
	if c.Server == nil {
		err = multierror.Append(err, errors.New("missing server config section"))
	}
	return err
}

func setFromEnvironment(c *Config) {
	port, err := strconv.Atoi(os.Getenv("PORT"))
	if err == nil {
		c.Server.Port = port
	}
	if os.Getenv("OAUTH_CLIENT_ID") != "" {
		c.Github.OauthClientID = os.Getenv("OAUTH_CLIENT_ID")
	}
	if os.Getenv("OAUTH_CLIENT_SECRET") != "" {
		c.Github.OauthClientSecret = os.Getenv("OAUTH_CLIENT_SECRET")
	}
	if os.Getenv("CSRF_SECRET") != "" {
		c.Server.CSRFSecret = os.Getenv("CSRF_SECRET")
	}
	if os.Getenv("COOKIE_SECRET") != "" {
		c.Server.CookieSecret = os.Getenv("COOKIE_SECRET")
	}
}

// ReadConfig parses a hcl configuration file into a Config struct.
func ReadConfig(f string) (*Config, error) {
	config := &Config{}
	if err := scl.DecodeFile(config, f); err != nil {
		return nil, errors.Wrapf(err, "unable to load config from file %s", f)
	}
	setFromEnvironment(config)
	if err := verifyConfig(config); err != nil {
		return nil, errors.Wrap(err, "unable to verify config")
	}
	return config, nil
}