Skip to content

Commit

Permalink
handle ssh-agent & ssh exec. Reorganized code.
Browse files Browse the repository at this point in the history
  • Loading branch information
AnalogJ committed Apr 20, 2018
1 parent 57338c3 commit 87e7696
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 130 deletions.
12 changes: 5 additions & 7 deletions cmd/drawbridge/drawbridge.go
Expand Up @@ -7,9 +7,7 @@ import (

"bufio"
"drawbridge/pkg/config"
"drawbridge/pkg/connect"
"drawbridge/pkg/create"
"drawbridge/pkg/list"
"drawbridge/pkg/actions"
"drawbridge/pkg/utils"
"drawbridge/pkg/version"
"gopkg.in/urfave/cli.v2"
Expand Down Expand Up @@ -81,7 +79,7 @@ func main() {
return err
}

createEngine := create.CreateEngine{Config: config}
createEngine := actions.CreateAction{Config: config}
return createEngine.Start(cliAnswers)
},

Expand All @@ -92,7 +90,7 @@ func main() {
Usage: "List all drawbridge managed ssh configs",
Action: func(c *cli.Context) error {

listEngine := list.ListEngine{Config: config}
listEngine := actions.ListAction{Config: config}
return listEngine.Start()
},

Expand All @@ -103,7 +101,7 @@ func main() {
Usage: "Connect to a drawbridge managed ssh config",
Action: func(c *cli.Context) error {

listEngine := list.ListEngine{Config: config}
listEngine := actions.ListAction{Config: config}
listEngine.Start()

reader := bufio.NewReader(os.Stdin)
Expand All @@ -116,7 +114,7 @@ func main() {
}
answerIndex := i - 1

connectEngine := connect.ConnectEngine{Config: config}
connectEngine := actions.ConnectAction{Config: config}
return connectEngine.Start(listEngine.OrderedAnswers[answerIndex].(map[string]interface{}))
},

Expand Down
61 changes: 61 additions & 0 deletions pkg/actions/connect.go
@@ -0,0 +1,61 @@
package actions

import (
"drawbridge/pkg/config"
"drawbridge/pkg/utils"
"path/filepath"
"syscall"
"os"
"os/exec"
)

type ConnectAction struct {
Config config.Interface
}

func (e *ConnectAction) Start(answerData map[string]interface{}) error {

//"-c", "command1; command2; command3; ..."

tmplData, err := e.Config.GetActiveConfigTemplate()
if err != nil {
return nil
}
tmplConfigFilepath, err := utils.PopulateTemplate(tmplData.FilePath, answerData)
if err != nil {
return nil
}
tmplConfigFilepath, err = utils.ExpandPath(filepath.Join(e.Config.GetString("options.config_dir"), tmplConfigFilepath))
if err != nil {
return nil
}

tmplPemFilepath, err := utils.PopulateTemplate(tmplData.PemFilePath, answerData)
if err != nil {
return nil
}
tmplPemFilepath, err = utils.ExpandPath(filepath.Join(e.Config.GetString("options.pem_dir"), tmplPemFilepath))
if err != nil {
return nil
}

//TODO: Print the lines we're running.

//TODO: Check that the bastion host is accessible.

//TODO: add the ssh/pem key to the ssh-agent (if its running).


//https://gobyexample.com/execing-processes
//https://groob.io/posts/golang-execve/


binary, lookErr := exec.LookPath("ssh")
if lookErr != nil {
panic(lookErr)
}

args := []string{"ssh", "bastion", "-F", tmplConfigFilepath}

return syscall.Exec(binary, args, os.Environ())
}
12 changes: 6 additions & 6 deletions pkg/create/create.go → pkg/actions/create.go
@@ -1,4 +1,4 @@
package create
package actions

import (
"bufio"
Expand All @@ -14,11 +14,11 @@ import (
"strings"
)

type CreateEngine struct {
type CreateAction struct {
Config config.Interface
}

func (e *CreateEngine) Start(cliAnswerData map[string]interface{}) error {
func (e *CreateAction) Start(cliAnswerData map[string]interface{}) error {

// prepare answer data with config.options
answerData := map[string]interface{}{}
Expand Down Expand Up @@ -66,7 +66,7 @@ func (e *CreateEngine) Start(cliAnswerData map[string]interface{}) error {
return err
}

err = activeConfigTemplate.WriteConfigTemplate(answerData, e.Config.GetString("options.config_dir"))
err = activeConfigTemplate.WriteTemplate(answerData)
if err != nil {
return err
}
Expand Down Expand Up @@ -103,7 +103,7 @@ func (e *CreateEngine) Start(cliAnswerData map[string]interface{}) error {
return nil
}

func (e *CreateEngine) Query(questions map[string]config.Question, answerData map[string]interface{}) (map[string]interface{}, error) {
func (e *CreateAction) Query(questions map[string]config.Question, answerData map[string]interface{}) (map[string]interface{}, error) {
for questionKey, questionData := range questions {

val, ok := questionData.Schema["required"]
Expand All @@ -118,7 +118,7 @@ func (e *CreateEngine) Query(questions map[string]config.Question, answerData ma
return answerData, nil
}

func (e *CreateEngine) queryResponse(questionKey string, question config.Question) interface{} {
func (e *CreateAction) queryResponse(questionKey string, question config.Question) interface{} {

for true {
//this question is not answered, and it is required. We should ask the user.
Expand Down
1 change: 1 addition & 0 deletions pkg/actions/delete.go
@@ -0,0 +1 @@
package actions
1 change: 1 addition & 0 deletions pkg/actions/download.go
@@ -0,0 +1 @@
package actions
8 changes: 4 additions & 4 deletions pkg/list/list.go → pkg/actions/list.go
@@ -1,4 +1,4 @@
package list
package actions

import (
"drawbridge/pkg/config"
Expand All @@ -16,13 +16,13 @@ import (
"strings"
)

type ListEngine struct {
type ListAction struct {
Config config.Interface
GroupedAnswers *gabs.Container
OrderedAnswers []interface{}
}

func (e *ListEngine) Start() error {
func (e *ListAction) Start() error {

configDir := e.Config.GetString("options.config_dir")
configDir, err := utils.ExpandPath(configDir)
Expand Down Expand Up @@ -115,7 +115,7 @@ func (e *ListEngine) Start() error {
return nil
}

func (e *ListEngine) PrintUI(level int, groups []string, groupedAnswers *gabs.Container) error {
func (e *ListAction) PrintUI(level int, groups []string, groupedAnswers *gabs.Container) error {
children, _ := groupedAnswers.ChildrenMap()
for groupKey, child := range children {
nextGroups := []string{}
Expand Down
51 changes: 21 additions & 30 deletions pkg/config/config.go
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"drawbridge/pkg/errors"
"drawbridge/pkg/utils"
"drawbridge/pkg/config/template"
"fmt"
"github.com/spf13/viper"
"github.com/xeipuuv/gojsonschema"
Expand Down Expand Up @@ -34,22 +35,13 @@ func (c *configuration) Init() error {
c.SetDefault("options.config_dir", "~/.ssh/drawbridge")
c.SetDefault("options.pem_dir", "~/.ssh")
c.SetDefault("options.active_config_template", "default")
c.SetDefault("options.active_pem_template", "default")

c.SetDefault("options.active_extra_templates", []string{})
c.SetDefault("options.ui_group_priority", []string{"environment", "username"})
c.SetDefault("options.ui_question_hidden", []string{})
//TODO: options.overwrite == false/

c.SetDefault("questions", map[string]Question{
"pem_filename": {
Description: "Pem key used to ssh to bastion",
DefaultValue: "id_rsa",
Schema: map[string]interface{}{
"type": "string",
"required": true,
},
},
"environment": {
Description: "Environment name for this stack",
DefaultValue: "test",
Expand All @@ -76,11 +68,7 @@ func (c *configuration) Init() error {
},
})
c.SetDefault("answers", []map[string]interface{}{})



c.SetDefault("pem_templates.default", "{{pem_dir}}/{{.environment}}-{{.username}}-pem")

c.SetDefault("config_templates.default.pem_filepath", "{{.environment}}-{{.username}}-pem")
c.SetDefault("config_templates.default.filepath", "{{.environment}}-{{.username}}-config")
c.SetDefault("config_templates.default.content", utils.StripIndent(
`
Expand Down Expand Up @@ -291,6 +279,14 @@ func (c *configuration) ValidateConfigFile(configFilePath string) error {
"type": "array",
"additionalProperties":false
},
"variables":{
"type": "object",
"patternProperties": {
"^[a-z0-9]*$":{
"type":"string"
}
}
},
"config_templates":{
"type": "object",
"patternProperties": {
Expand All @@ -304,19 +300,14 @@ func (c *configuration) ValidateConfigFile(configFilePath string) error {
},
"content": {
"type": "string"
},
"pem_filepath": {
"type": "string"
}
}
}
}
},
"pem_templates":{
"type": "object",
"patternProperties": {
"^[a-z0-9]*$":{
"type":"string"
}
}
},
"extra_templates":{
"type": "object",
"patternProperties": {
Expand Down Expand Up @@ -381,42 +372,42 @@ func (c *configuration) GetQuestions() (map[string]Question, error) {
return questionsMap, err
}

func (c *configuration) GetConfigTemplates() (map[string]Template, error) {
func (c *configuration) GetConfigTemplates() (map[string]template.ConfigTemplate, error) {
//deserialize Templates
templateMap := map[string]Template{}
templateMap := map[string]template.ConfigTemplate{}
err := c.UnmarshalKey("config_templates", &templateMap)
return templateMap, err
}

func (c *configuration) GetActiveConfigTemplate() (Template, error) {
func (c *configuration) GetActiveConfigTemplate() (template.ConfigTemplate, error) {
//deserialize Templates
activeTemplateName := c.GetString("options.active_config_template")

allTemplates, err := c.GetConfigTemplates()
if err != nil {
return Template{}, err
return template.ConfigTemplate{}, err
}

activeTemplate := allTemplates[activeTemplateName]
return activeTemplate, nil
}

func (c *configuration) GetExtraTemplates() (map[string]Template, error) {
func (c *configuration) GetExtraTemplates() (map[string]template.FileTemplate, error) {
//deserialize Templates
templateMap := map[string]Template{}
templateMap := map[string]template.FileTemplate{}
err := c.UnmarshalKey("extra_templates", &templateMap)
return templateMap, err
}

func (c *configuration) GetActiveExtraTemplates() ([]Template, error) {
func (c *configuration) GetActiveExtraTemplates() ([]template.FileTemplate, error) {
//deserialize Templates
activeTemplateNames := c.GetStringSlice("options.active_extra_templates")

allTemplates, err := c.GetExtraTemplates()
if err != nil {
return nil, err
}
activeTemplates := []Template{}
activeTemplates := []template.FileTemplate{}

for _, activeTemplateName := range activeTemplateNames {
activeTemplate := allTemplates[activeTemplateName]
Expand Down
10 changes: 6 additions & 4 deletions pkg/config/interface.go
@@ -1,5 +1,7 @@
package config

import "drawbridge/pkg/config/template"

// Create mock using:
// mockgen -source=pkg/config/interface.go -destination=pkg/config/mock/mock_config.go
type Interface interface {
Expand All @@ -21,8 +23,8 @@ type Interface interface {
//GetQuestionsSchema() (map[string]interface{}, error)
//GetQuestionSchema(question Question) (map[string]interface{}, error)

GetConfigTemplates() (map[string]Template, error)
GetActiveConfigTemplate() (Template, error)
GetExtraTemplates() (map[string]Template, error)
GetActiveExtraTemplates() ([]Template, error)
GetConfigTemplates() (map[string]template.ConfigTemplate, error)
GetActiveConfigTemplate() (template.ConfigTemplate, error)
GetExtraTemplates() (map[string]template.FileTemplate, error)
GetActiveExtraTemplates() ([]template.FileTemplate, error)
}

0 comments on commit 87e7696

Please sign in to comment.