Skip to content

Commit

Permalink
Authentication (#1946)
Browse files Browse the repository at this point in the history
* Implementing https listener. Https and http may both be specified. Removing RelayListener.

* Better default handling if https is specified and http is not

* initial sketch of web again

* more work on auth

* auth closer to working

* UI for creating tokens

* slight change to token help

* update gorilla. tweak

* vendor. activating redis

* work on stuff

* ui changes

* default cookie secret.

* some code review changes

* compiling would be nice

* metadata and collect allow insecure to localhost.

* Trying to do as much in proc as possible. Gets rid of several dirty hacks.

* fix

* allowing username overrides for authorized users

* ui tweaks

* ui tweak

* ui tweak
  • Loading branch information
Craig Peterson committed Jan 6, 2017
1 parent cdcee21 commit 67f50fd
Show file tree
Hide file tree
Showing 73 changed files with 7,575 additions and 1,991 deletions.
9 changes: 8 additions & 1 deletion cmd/bosun/conf/conf.go
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ import (
// outside of the package without a setter // outside of the package without a setter
type SystemConfProvider interface { type SystemConfProvider interface {
GetHTTPListen() string GetHTTPListen() string
GetRelayListen() string GetHTTPSListen() string
GetTLSCertFile() string
GetTLSKeyFile() string


GetSMTPHost() string GetSMTPHost() string
GetSMTPUsername() string // SMTP username GetSMTPUsername() string // SMTP username
Expand Down Expand Up @@ -67,6 +69,8 @@ type SystemConfProvider interface {
GetAnnotateElasticHosts() expr.ElasticHosts GetAnnotateElasticHosts() expr.ElasticHosts
GetAnnotateIndex() string GetAnnotateIndex() string


GetAuthConf() *AuthConf

// Contexts // Contexts
GetTSDBContext() opentsdb.Context GetTSDBContext() opentsdb.Context
GetGraphiteContext() graphite.Context GetGraphiteContext() graphite.Context
Expand All @@ -90,6 +94,9 @@ func ValidateSystemConf(sc SystemConfProvider) error {
if sc.GetDefaultRunEvery() <= 0 { if sc.GetDefaultRunEvery() <= 0 {
return fmt.Errorf("default run every must be greater than 0, is %v", sc.GetDefaultRunEvery()) return fmt.Errorf("default run every must be greater than 0, is %v", sc.GetDefaultRunEvery())
} }
if sc.GetHTTPSListen() != "" && (sc.GetTLSCertFile() == "" || sc.GetTLSKeyFile() == "") {
return fmt.Errorf("must specify TLSCertFile and TLSKeyFile if HTTPSListen is specified")
}
return nil return nil
} }


Expand Down
4 changes: 3 additions & 1 deletion cmd/bosun/conf/notify.go
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -158,7 +158,9 @@ func SendMail(addr, username, password string, from string, to []string, msg []b
if len(username) > 0 || len(password) > 0 { if len(username) > 0 || len(password) > 0 {
hostWithoutPort := strings.Split(addr, ":")[0] hostWithoutPort := strings.Split(addr, ":")[0]
auth := smtp.PlainAuth("", username, password, hostWithoutPort) auth := smtp.PlainAuth("", username, password, hostWithoutPort)
c.Auth(auth) if err = c.Auth(auth); err != nil {
return err
}
} }
} }
if err = c.Mail(from); err != nil { if err = c.Mail(from); err != nil {
Expand Down
77 changes: 70 additions & 7 deletions cmd/bosun/conf/system.go
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ import (
// SystemConf contains all the information that bosun needs to run. Outside of the conf package // SystemConf contains all the information that bosun needs to run. Outside of the conf package
// usage should be through conf.SystemConfProvider // usage should be through conf.SystemConfProvider
type SystemConf struct { type SystemConf struct {
HTTPListen string HTTPListen string
RelayListen string HTTPSListen string
TLSCertFile string
TLSKeyFile string

Hostname string Hostname string
Ping bool Ping bool
PingDuration Duration // Duration from now to stop pinging hosts based on time since the host tag was touched PingDuration Duration // Duration from now to stop pinging hosts based on time since the host tag was touched
Expand All @@ -45,6 +48,8 @@ type SystemConf struct {


AnnotateConf AnnotateConf AnnotateConf AnnotateConf


AuthConf *AuthConf

EnableSave bool EnableSave bool
EnableReload bool EnableReload bool
CommandHookPath string CommandHookPath string
Expand Down Expand Up @@ -140,6 +145,43 @@ type SMTPConf struct {
Password string `json:"-"` Password string `json:"-"`
} }


//AuthConf is configuration for bosun's authentication
type AuthConf struct {
AuthDisabled bool
//Secret string to hash auth tokens. Needed to enable token auth.
TokenSecret string
//Secret sting used to encrypt cookie.
CookieSecret string
//LDAP configuration
LDAP LDAPConf
}

type LDAPConf struct {
// Domain name (used to make domain/username)
Domain string
// LDAP server
LdapAddr string
// allow insecure ldap connection?
AllowInsecure bool
// default permission level for anyone who can log in. Try "Reader".
DefaultPermission string
//List of group level permissions
Groups []LDAPGroup
//List of user specific permission levels
Users map[string]string
//Root search path for group lookups. Usually something like "DC=myorg,DC=com".
//Only needed if using group permissions
RootSearchPath string
}

//LDAPGroup is a Group level access specification for ldap
type LDAPGroup struct {
// group search path string
Path string
// Access to grant members of group Ex: "Admin"
Role string
}

// GetSystemConfProvider returns the SystemConfProvider interface // GetSystemConfProvider returns the SystemConfProvider interface
// and validates the logic of the configuration. If the configuration // and validates the logic of the configuration. If the configuration
// is not valid an error is returned // is not valid an error is returned
Expand All @@ -151,12 +193,16 @@ func (sc *SystemConf) GetSystemConfProvider() (SystemConfProvider, error) {
return provider, nil return provider, nil
} }


const (
defaultHTTPListen = ":8070"
)

// NewSystemConf retruns a system conf with default values set // NewSystemConf retruns a system conf with default values set
func newSystemConf() *SystemConf { func newSystemConf() *SystemConf {
return &SystemConf{ return &SystemConf{
CheckFrequency: Duration{Duration: time.Minute * 5}, CheckFrequency: Duration{Duration: time.Minute * 5},
DefaultRunEvery: 1, DefaultRunEvery: 1,
HTTPListen: ":8070", HTTPListen: defaultHTTPListen,
DBConf: DBConf{ DBConf: DBConf{
LedisDir: "ledis_data", LedisDir: "ledis_data",
LedisBindAddr: "127.0.0.1:9565", LedisBindAddr: "127.0.0.1:9565",
Expand Down Expand Up @@ -199,6 +245,10 @@ func loadSystemConfig(conf string, isFileName bool) (*SystemConf, error) {
return sc, fmt.Errorf("undecoded fields in system configuration: %v", decodeMeta.Undecoded()) return sc, fmt.Errorf("undecoded fields in system configuration: %v", decodeMeta.Undecoded())
} }
sc.md = decodeMeta sc.md = decodeMeta
// clear default http listen if not explicitly specified
if !decodeMeta.IsDefined("HTTPListen") && decodeMeta.IsDefined("HTTPSListen") {
sc.HTTPListen = ""
}
return sc, nil return sc, nil
} }


Expand All @@ -207,10 +257,19 @@ func (sc *SystemConf) GetHTTPListen() string {
return sc.HTTPListen return sc.HTTPListen
} }


// GetRelayListen returns an address on which bosun will listen and Proxy all requests to /api // GetHTTPSListen returns the hostname:port that Bosun should listen on with tls
// it was added so one can make OpenTSDB API endpoints available at the same URL as Bosun. func (sc *SystemConf) GetHTTPSListen() string {
func (sc *SystemConf) GetRelayListen() string { return sc.HTTPSListen
return sc.RelayListen }

// GetTLSCertFile returns the path to the tls certificate to listen with (pem format). Must be specified with HTTPSListen.
func (sc *SystemConf) GetTLSCertFile() string {
return sc.TLSCertFile
}

// GetTLSKeyFile returns the path to the tls key to listen with (pem format). Must be specified with HTTPSListen.
func (sc *SystemConf) GetTLSKeyFile() string {
return sc.TLSKeyFile
} }


// GetSMTPHost returns the SMTP mail server host that Bosun will use to relay through // GetSMTPHost returns the SMTP mail server host that Bosun will use to relay through
Expand Down Expand Up @@ -271,6 +330,10 @@ func (sc *SystemConf) GetRedisPassword() string {
return sc.DBConf.RedisPassword return sc.DBConf.RedisPassword
} }


func (sc *SystemConf) GetAuthConf() *AuthConf {
return sc.AuthConf
}

// GetTimeAndDate returns the http://www.timeanddate.com/ that should be available to the UI // GetTimeAndDate returns the http://www.timeanddate.com/ that should be available to the UI
// so it can show links to translate UTC times to various timezones. This feature is only // so it can show links to translate UTC times to various timezones. This feature is only
// for creating UI Links as Bosun is expected to be running on a machine that is set to UTC // for creating UI Links as Bosun is expected to be running on a machine that is set to UTC
Expand Down
5 changes: 5 additions & 0 deletions cmd/bosun/database/database.go
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ import (
"github.com/garyburd/redigo/redis" "github.com/garyburd/redigo/redis"
"github.com/siddontang/ledisdb/config" "github.com/siddontang/ledisdb/config"
"github.com/siddontang/ledisdb/server" "github.com/siddontang/ledisdb/server"

"github.com/captncraig/easyauth/providers/token/redisStore"
) )


// Core data access interface for everything sched needs // Core data access interface for everything sched needs
type DataAccess interface { type DataAccess interface {
RedisConnector
Metadata() MetadataDataAccess Metadata() MetadataDataAccess
Configs() ConfigDataAccess Configs() ConfigDataAccess
Search() SearchDataAccess Search() SearchDataAccess
Expand Down Expand Up @@ -118,6 +121,8 @@ func (d *dataAccess) Get() redis.Conn {
} }
} }


var _ redisStore.Connector = (*dataAccess)(nil) //just a compile time interface check

//gets name of function that called the currently executing function. //gets name of function that called the currently executing function.
func myCallerName() string { func myCallerName() string {
fpcs := make([]uintptr, 1) fpcs := make([]uintptr, 1)
Expand Down
40 changes: 21 additions & 19 deletions cmd/bosun/main.go
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -109,32 +109,31 @@ func main() {
os.Exit(0) os.Exit(0)
} }
var ruleProvider conf.RuleConfProvider = ruleConf var ruleProvider conf.RuleConfProvider = ruleConf
httpListen := &url.URL{
Scheme: "http", addrToSendTo := sysProvider.GetHTTPSListen()
Host: sysProvider.GetHTTPListen(), proto := "https"
if addrToSendTo == "" {
addrToSendTo = sysProvider.GetHTTPListen()
proto = "http"
} }
if strings.HasPrefix(httpListen.Host, ":") { selfAddress := &url.URL{
httpListen.Host = "localhost" + httpListen.Host Scheme: proto,
Host: addrToSendTo,
} }
if err := metadata.Init(httpListen, false); err != nil { if strings.HasPrefix(selfAddress.Host, ":") {
slog.Fatal(err) selfAddress.Host = "localhost" + selfAddress.Host
} }

if err := sched.Load(sysProvider, ruleProvider, *flagSkipLast, *flagQuiet); err != nil { if err := sched.Load(sysProvider, ruleProvider, *flagSkipLast, *flagQuiet); err != nil {
slog.Fatal(err) slog.Fatal(err)
} }
if sysProvider.GetRelayListen() != "" { if err := metadata.InitF(false, func(k metadata.Metakey, v interface{}) error { return sched.DefaultSched.PutMetadata(k, v) }); err != nil {
go func() { slog.Fatal(err)
mux := http.NewServeMux()
mux.Handle("/api/", util.NewSingleHostProxy(httpListen))
s := &http.Server{
Addr: sysProvider.GetRelayListen(),
Handler: mux,
}
slog.Fatal(s.ListenAndServe())
}()
} }
if sysProvider.GetTSDBHost() != "" { if sysProvider.GetTSDBHost() != "" {
if err := collect.Init(httpListen, "bosun"); err != nil { relay := web.Relay(sysProvider.GetTSDBHost())
collect.DirectHandler = relay
if err := collect.Init(selfAddress, "bosun"); err != nil {
slog.Fatal(err) slog.Fatal(err)
} }
tsdbHost := &url.URL{ tsdbHost := &url.URL{
Expand Down Expand Up @@ -218,7 +217,9 @@ func main() {
ruleProvider.SetReload(reload) ruleProvider.SetReload(reload)


go func() { go func() {
slog.Fatal(web.Listen(sysProvider.GetHTTPListen(), *flagDev, sysProvider.GetTSDBHost(), reload)) slog.Fatal(web.Listen(sysProvider.GetHTTPListen(), sysProvider.GetHTTPSListen(),
sysProvider.GetTLSCertFile(), sysProvider.GetTLSKeyFile(), *flagDev,
sysProvider.GetTSDBHost(), reload, sysProvider.GetAuthConf()))
}() }()
go func() { go func() {
if !*flagNoChecks { if !*flagNoChecks {
Expand Down Expand Up @@ -255,6 +256,7 @@ func main() {
} }


func quit() { func quit() {
slog.Error("Exiting")
os.Exit(0) os.Exit(0)
} }


Expand Down
9 changes: 1 addition & 8 deletions cmd/bosun/sched/sched.go
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package sched // import "bosun.org/cmd/bosun/sched"


import ( import (
"fmt" "fmt"
"reflect"
"strings" "strings"
"sync" "sync"
"time" "time"
Expand Down Expand Up @@ -153,13 +152,7 @@ func (s *Schedule) PutMetadata(k metadata.Metakey, v interface{}) error {
slog.Error(err) slog.Error(err)
return err return err
} }
strVal, ok := v.(string) return s.DataAccess.Metadata().PutMetricMetadata(k.Metric, k.Name, fmt.Sprint(v))
if !ok {
err := fmt.Errorf("desc, rate, and unit require value to be string. Found: %s", reflect.TypeOf(v))
slog.Error(err)
return err
}
return s.DataAccess.Metadata().PutMetricMetadata(k.Metric, k.Name, strVal)
} }


func (s *Schedule) DeleteMetadata(tags opentsdb.TagSet, name string) error { func (s *Schedule) DeleteMetadata(tags opentsdb.TagSet, name string) error {
Expand Down
Binary file removed cmd/bosun/web/bosun.state
Binary file not shown.
19 changes: 2 additions & 17 deletions cmd/bosun/web/embed.go
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package web
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"io"
"log" "log"
"os" "os"
"os/exec" "os/exec"
Expand Down Expand Up @@ -47,25 +46,11 @@ func RunTsc() {
} }


func run(name string, arg ...string) { func run(name string, arg ...string) {
log.Println("running", name) log.Println("running", name, arg)
c := exec.Command(name, arg...) c := exec.Command(name, arg...)
stdout, err := c.StdoutPipe() if err := c.Run(); err != nil {
if err != nil {
log.Fatal(err)
}
stderr, err := c.StderrPipe()
if err != nil {
log.Fatal(err)
}
if err := c.Start(); err != nil {
log.Fatal(err)
}
go func() { io.Copy(os.Stdout, stdout) }()
go func() { io.Copy(os.Stderr, stderr) }()
if err := c.Wait(); err != nil {
log.Printf("run error: %v: %v", name, err) log.Printf("run error: %v: %v", name, err)
} }
log.Println("run complete:", name)
} }


func deepCompareDifferent(file1, file2 string) bool { func deepCompareDifferent(file1, file2 string) bool {
Expand Down
Loading

0 comments on commit 67f50fd

Please sign in to comment.