From b6d4929a12070c62f522ad4537d74778da3e10db Mon Sep 17 00:00:00 2001 From: Jeff Lindsay Date: Mon, 8 May 2017 20:26:15 -0500 Subject: [PATCH 1/2] app/cmd: introduces preprocessors for session. moves early session handling logic into respective components. Signed-off-by: Jeff Lindsay --- .env.example | 3 +++ app/cmd/com.go | 25 ++++++++++++++++++++----- app/cmd/ssh.go | 36 ++++++------------------------------ app/console/cmd.go | 31 +++++++++++++++++++++++++++++++ lib/access/cmd.go | 22 ++++++++++++++++++++++ lib/access/com.go | 4 +++- lib/maint/cmd.go | 20 ++++++++++++++++++++ lib/maint/com.go | 35 ----------------------------------- lib/maint/daemon.go | 10 ++++++++++ lib/maint/maint.go | 32 ++++++++++++++++++++++++++++++++ run/channels/alpha.yaml | 3 +++ 11 files changed, 150 insertions(+), 71 deletions(-) create mode 100644 app/console/cmd.go create mode 100644 lib/access/cmd.go create mode 100644 lib/maint/cmd.go create mode 100644 lib/maint/daemon.go create mode 100644 lib/maint/maint.go diff --git a/.env.example b/.env.example index 2c7ed63..9cde808 100644 --- a/.env.example +++ b/.env.example @@ -9,3 +9,6 @@ # Example setting "api_token" for "auth0" component: # export AUTH0_API_TOKEN="some-crazy-secret" + +# Disables component that checks GitHub if in alpha group +# export ACCESS_ENABLED=false diff --git a/app/cmd/com.go b/app/cmd/com.go index 3769e39..07fbc56 100644 --- a/app/cmd/com.go +++ b/app/cmd/com.go @@ -1,15 +1,30 @@ package cmd import ( + "sort" + "github.com/gliderlabs/comlab/pkg/com" + "github.com/gliderlabs/ssh" ) func init() { - com.Register("cmd", &Component{}, - com.Option("access_denied_msg", - "Access Denied: Visit https://alpha.cmd.io/request to request access", - "message shown when user isn't allowed access"), - ) + com.Register("cmd", &Component{}) } type Component struct{} + +type Preprocessor interface { + PreprocessOrder() uint + PreprocessSession(sess ssh.Session) (cont bool, msg string) +} + +func Preprocessors() []Preprocessor { + var processors []Preprocessor + for _, com := range com.Enabled(new(Preprocessor), nil) { + processors = append(processors, com.(Preprocessor)) + } + sort.Slice(processors, func(i, j int) bool { + return processors[i].PreprocessOrder() <= processors[j].PreprocessOrder() + }) + return processors +} diff --git a/app/cmd/ssh.go b/app/cmd/ssh.go index 09bf7ca..496afdc 100644 --- a/app/cmd/ssh.go +++ b/app/cmd/ssh.go @@ -7,7 +7,6 @@ import ( "strings" "time" - "github.com/gliderlabs/comlab/pkg/com" "github.com/gliderlabs/comlab/pkg/log" "github.com/gliderlabs/ssh" "github.com/patrickmn/go-cache" @@ -17,10 +16,6 @@ import ( "github.com/gliderlabs/cmd/app/console" "github.com/gliderlabs/cmd/app/core" "github.com/gliderlabs/cmd/app/store" - "github.com/gliderlabs/cmd/lib/access" - "github.com/gliderlabs/cmd/lib/cli" - "github.com/gliderlabs/cmd/lib/maint" - "github.com/gliderlabs/cmd/lib/release" ) // Default expiry of 30 sec and expiry purge every 5 min. @@ -45,35 +40,16 @@ func (c *Component) HandleSSH(s ssh.Session) { log.Info(s, cmd, time.Since(start), msg) }() - // restrict access when maintenance mode is active - // TODO: should be handled via hook - if maint.Active() && !maint.IsAllowed(userName) { - msg = "maintenance" - fmt.Fprintln(s, maint.Notice()) - return - } - - // check for first time user - if user := console.ContextUser(s.Context()); user != nil { - if user.Account.CustomerID == "" { - fmt.Fprintf(s, cli.Bright("\nWelcome, %s!\n\n"), s.User()) - fmt.Fprintln(s, "We noticed this is your first login. So far so good!") - fmt.Fprintln(s, "Would you mind logging in via the web interface?") - fmt.Fprintln(s, "This way we can properly set up your account:\n") - fmt.Fprintf(s, cli.Bright("https://%s/login\n\n"), release.Hostname()) - fmt.Fprintln(s, "Then you can come back and use SSH as usual. Thanks!\n") + var cont bool + for _, preprocessor := range Preprocessors() { + cont, msg = preprocessor.PreprocessSession(s) + if !cont { authCache.Delete(s.User()) return } } - // check for channel access when user is not a token - if tok := uuid.FromStringOrNil(userName); tok == uuid.Nil && !access.Check(userName) { - msg = "channel access denied" - fmt.Fprintln(s, com.GetString("access_denied_msg")) - return - } - + // TODO: make builtins also a preprocessor! args := s.Command() if len(args) == 0 || strings.HasPrefix(args[0], ":") { if err := builtin.Execute(s); err != nil { @@ -83,7 +59,7 @@ func (c *Component) HandleSSH(s ssh.Session) { } cmdName = args[0] - // TODO: move elsewhere (via hook?) + // TODO: make into preprocessor // handle git-receive-pack by finding the first cmd which has io.cmd.git-receive == arg[1] if strings.HasPrefix(cmdName, "git-receive-pack") && len(args) > 1 { cmds := store.Selected().List(userName) diff --git a/app/console/cmd.go b/app/console/cmd.go new file mode 100644 index 0000000..d75d551 --- /dev/null +++ b/app/console/cmd.go @@ -0,0 +1,31 @@ +package console + +import ( + "fmt" + + "github.com/gliderlabs/cmd/lib/cli" + "github.com/gliderlabs/cmd/lib/release" + "github.com/gliderlabs/comlab/pkg/log" + "github.com/gliderlabs/ssh" +) + +func (c *Component) PreprocessOrder() uint { + return 10 +} + +func (c *Component) PreprocessSession(sess ssh.Session) (cont bool, msg string) { + // check for first time user + log.Local("check") + if user := ContextUser(sess.Context()); user != nil { + if user.Account.CustomerID == "" { + fmt.Fprintf(sess, cli.Bright("\nWelcome, %s!\n\n"), sess.User()) + fmt.Fprintln(sess, "We noticed this is your first login. So far so good!") + fmt.Fprintln(sess, "Would you mind logging in via the web interface?") + fmt.Fprintln(sess, "This way we can properly set up your account:\n") + fmt.Fprintf(sess, cli.Bright("https://%s/login\n\n"), release.Hostname()) + fmt.Fprintln(sess, "Then you can come back and use SSH as usual. Thanks!\n") + return false, "first time login" + } + } + return true, "" +} diff --git a/lib/access/cmd.go b/lib/access/cmd.go new file mode 100644 index 0000000..3fc6daa --- /dev/null +++ b/lib/access/cmd.go @@ -0,0 +1,22 @@ +package access + +import ( + "fmt" + + "github.com/gliderlabs/comlab/pkg/com" + "github.com/gliderlabs/ssh" + uuid "github.com/satori/go.uuid" +) + +func (c *Component) PreprocessOrder() uint { + return 20 +} + +func (c *Component) PreprocessSession(sess ssh.Session) (cont bool, msg string) { + // check for channel access when user is not a token + if token := uuid.FromStringOrNil(sess.User()); token == uuid.Nil && !Check(sess.User()) { + fmt.Fprintln(sess, com.GetString("deny_msg")) + return false, "channel access denied" + } + return true, "" +} diff --git a/lib/access/com.go b/lib/access/com.go index bc5aa4c..9a7a30c 100644 --- a/lib/access/com.go +++ b/lib/access/com.go @@ -12,7 +12,9 @@ import ( func init() { com.Register("access", &Component{}, com.Option("gh_team_id", "2144066", "GitHub team ID to allow access to"), - com.Option("gh_token", "", "GitHub access token")) + com.Option("gh_token", "", "GitHub access token"), + com.Option("deny_msg", "Access Denied", "User message on access denied"), + ) } type Component struct { diff --git a/lib/maint/cmd.go b/lib/maint/cmd.go new file mode 100644 index 0000000..988bab2 --- /dev/null +++ b/lib/maint/cmd.go @@ -0,0 +1,20 @@ +package maint + +import ( + "fmt" + + "github.com/gliderlabs/ssh" +) + +func (c *Component) PreprocessOrder() uint { + return 0 +} + +func (c *Component) PreprocessSession(sess ssh.Session) (cont bool, msg string) { + // restrict access when maintenance mode is active + if Active() && !IsAllowed(sess.User()) { + fmt.Fprintln(sess, Notice()) + return false, "maintenance" + } + return true, "" +} diff --git a/lib/maint/com.go b/lib/maint/com.go index 258e54a..c83cd4b 100644 --- a/lib/maint/com.go +++ b/lib/maint/com.go @@ -1,10 +1,7 @@ package maint import ( - "strings" - "github.com/gliderlabs/comlab/pkg/com" - "github.com/gliderlabs/comlab/pkg/log" ) func init() { @@ -17,35 +14,3 @@ func init() { // Component ... type Component struct { } - -func (c *Component) AppPreStart() error { - if Active() { - log.Info(Notice(), log.Fields{"active": "true"}) - } - return nil -} - -// Active returns current maintenance state -func Active() bool { - return com.GetBool("active") -} - -// Allowed returns a slice of users which are allowed access during maintenance -func Allowed() []string { - return strings.Split(com.GetString("allow"), ",") -} - -// IsAllowed returns true if name is allowed access during maintenance -func IsAllowed(name string) bool { - for _, u := range Allowed() { - if u == name { - return true - } - } - return false -} - -// Notice printed during maintenance -func Notice() string { - return com.GetString("notice") -} diff --git a/lib/maint/daemon.go b/lib/maint/daemon.go new file mode 100644 index 0000000..9f562cb --- /dev/null +++ b/lib/maint/daemon.go @@ -0,0 +1,10 @@ +package maint + +import "github.com/gliderlabs/comlab/pkg/log" + +func (c *Component) AppPreStart() error { + if Active() { + log.Info(Notice(), log.Fields{"active": "true"}) + } + return nil +} diff --git a/lib/maint/maint.go b/lib/maint/maint.go new file mode 100644 index 0000000..a9c567c --- /dev/null +++ b/lib/maint/maint.go @@ -0,0 +1,32 @@ +package maint + +import ( + "strings" + + "github.com/gliderlabs/comlab/pkg/com" +) + +// Active returns current maintenance state +func Active() bool { + return com.GetBool("active") +} + +// Allowed returns a slice of users which are allowed access during maintenance +func Allowed() []string { + return strings.Split(com.GetString("allow"), ",") +} + +// IsAllowed returns true if name is allowed access during maintenance +func IsAllowed(name string) bool { + for _, u := range Allowed() { + if u == name { + return true + } + } + return false +} + +// Notice printed during maintenance +func Notice() string { + return com.GetString("notice") +} diff --git a/run/channels/alpha.yaml b/run/channels/alpha.yaml index e7bc5fc..4a46832 100644 --- a/run/channels/alpha.yaml +++ b/run/channels/alpha.yaml @@ -11,6 +11,9 @@ data: active = false allow = "mattaitchison" + [access] + deny_msg = "Access Denied: Visit https://alpha.cmd.io/request to request access" + [docker] name = "_docker._tcp.sandbox.infra.gl" From 12fa9e9f2e2a9f4641e9984b0e6f01523a477d30 Mon Sep 17 00:00:00 2001 From: Jeff Lindsay Date: Tue, 9 May 2017 11:38:42 -0500 Subject: [PATCH 2/2] circleci: new ci env build Signed-off-by: Jeff Lindsay --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a24bab0..c312a3d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2 jobs: build: docker: - - image: gliderlabs/ci:build-64 + - image: gliderlabs/ci:build-2 command: ["/bin/bash"] - image: mattaitchison/dynamodb-local cmd: ["-inMemory" ,"-sharedDb"]