安全密码提示

时间:2018-07-17 16:40:10

标签: security authentication go configuration go-templates

我正在研究软件包config,该软件包指定了用于批量配置网络设备的配置选项和命令。现在,config.New函数接受可以包含文本模板值的yaml源文本。对于yaml文件中的auth键,您可以指定模板值auth: {{.Password}}来提示用户输入执行模板的密码。

此功能安全吗?原始yaml源文件不会在模板执行时进行修改,据我所知,只能通过从*Config返回的config.New结构访问用户指定的密码值。不幸的是,必须导出Config的字段,才能使yaml被viper编组。这会带来安全问题吗?

这是我的代码:

package config

import (
    "fmt"
    "github.com/spf13/viper"
    "golang.org/x/crypto/ssh/terminal"
    "io"
    "os"
    "text/template"
)

// Config contains network device configuration options and commands.
type Config struct {
    Hosts   string `yaml:"hosts"`   // hosts to configure
    User    string `yaml:"user"`    // username for host login
    Auth    string `yaml:"auth"`    // SSH authentication method
    Allow   string `yaml:"allow"`   // allow either all or known hosts
    Timeout int    `yaml:"timeout"` // duration to wait to establish a connection
    Config []struct {
        Vendor string   `yaml:"vendor"` // vendor that supports `cmds`
        Cmds   []string `yaml:"cmds"`   // configuration commands to run
    } `yaml:"config"`               // list of vendor-configuration command sets
}

// New creates a new Config from a yaml or text template file.
func New(src string) (*Config, error) {
    var cfg Config
    pr, pw := io.Pipe()
    tmpl, err := template.New("config").Parse(src)
    if err != nil {
        return nil, err
    }
    tmplErr := make(chan error, 1)
    go func(tmpl *template.Template, cfg Config, pw *io.PipeWriter, tmplErr chan<- error) {
        defer pw.Close()
        if err := tmpl.Execute(pw, &cfg); err != nil {
            tmplErr <- err
        }
        close(tmplErr)
    }(tmpl, cfg, pw, tmplErr)
    select {
    case err := <-tmplErr:
        return nil, err
    default:
        v := viper.New()
        v.SetConfigType("yaml")
        if err := v.ReadConfig(pr); err != nil {
            return nil, err
        }
        if err := v.Unmarshal(&cfg); err != nil {
            return nil, err
        }
        return &cfg, nil
    }
}

// Password prompts the user for their password.
func (c *Config) Password() string {
    fmt.Fprint(os.Stderr, "Password: ")
    password, err := terminal.ReadPassword(int(os.Stdin.Fd()))
    if err != nil {
        panic(err)
    }
    fmt.Fprintln(os.Stderr)
    return string(password)
}

示例main.go

package main

import (
    "fmt"
    ".../config"
    "log"
)

const TestConfig = `
# Example configuration for restarting access points.
---
hosts  : access_points
user   : user
auth   : &password {{.Password}} # Prompt for password and store the value.
allow  : known_hosts             # Only allow connections to known hosts.
timeout: 5

config:
  - vendor: cisco
    cmds:
      - enable
      - *password                # Pass the password value to enter enabled mode.
      - capwap ap restart
      - exit
`

func main() {
    cfg, err := config.New(TestConfig)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(cfg.Auth)
}

任何提示或建议,不胜感激。我不想意外泄露任何人的密码或泄漏敏感数据。

0 个答案:

没有答案