What is the best way to deal with plain text passwords in Go

huangapple go评论72阅读模式
英文:

What is the best way to deal with plain text passwords in Go

问题

我正在创建一个简单的程序,用于在我的IP更改时将其注册到OpenDNS。我知道有ddclient,但出于学习目的,我想自己编写一个。

为了能够在OpenDNS上执行任何操作,我必须调用指定我的用户名和密码的URL,所以一个curl示例可能是这样的:curl -u user:password https://updates.opendns.com/nic/update?hostname=xxxx&myip=123.123.123.123

在Go中,我创建了以下函数:

func registerNewIpToOpenDns(ip string) (int, error) {

	openDnsURL := "https://updates.opendns.com/nic/update?hostname=xxxx&myip=" + ip
	req, err := http.NewRequest("GET", openDnsURL, nil)
	if err != nil {
		return 0, err
	}
	req.SetBasicAuth("USER", "PASS")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()

	return resp.StatusCode, nil
}

那么我应该如何输入用户/密码到这个程序中呢?我将在Github上将这个项目设为“Public”。

我在考虑创建一个名为“input”的文件,并将其添加到.gitignore中。
这样,如果其他人想使用该程序,他们只需要创建自己的“input”文件,程序将从中读取。

你觉得呢?

英文:

I'm creating a simple program to register my IP to OpenDNS when it changes. I know about the ddclient but I want to write my own just for learning purposes.

To be able to perform any operation on OpenDNS, I have to call the URL specifying my user and pass, so a curl example would be something like: curl -u user:password https://updates.opendns.com/nic/update?hostname=xxxx&myip=123.123.123.123

In Go I created the following function:

func registerNewIpToOpenDns(ip string) (int, error) {

	openDnsURL := "https://updates.opendns.com/nic/update?hostname=xxxx&myip=" + ip
	req, err := http.NewRequest("GET", openDnsURL, nil)
	if err != nil {
		return 0, err
	}
	req.SetBasicAuth("USER", "PASS")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return 0, err
	}
	defer resp.Body.Close()

	return resp.StatusCode, nil
}

So how should I perform the input of the user/pass to this program? I will let this project 'Public' in Github.

I was thinking in creating a file something like "input" and add it to .gitignore.
So if someone else wants to use the program, the person would just need to create it own "input" file and the program would read from it.

What do you think?

答案1

得分: 1

将不适用于所有人的配置数据放在环境变量中。

使用os.Getenv()在运行时检索变量。确保它们被设置为一些有效的值(至少不是空字符串),作为程序配置的一部分。

然后,如果你从systemd运行程序,可以在systemd配置文件中设置环境变量;或者在专门用于此进程的用户的.bash_config中设置;或者在程序执行的最方便的地方设置。

或者,创建一个配置文件,从程序中读取。我通常使用Json编码来进行这样的配置,但你也可以使用其他格式。从配置文件中读取机密信息可能比环境变量更安全,因为环境变量通常可以被系统进程检查。

当我创建一个配置文件时,我通常使用一个结构体来建模我的配置,

type Config struct {
   Username string
   Password string
}

然后,在程序的初始化过程中,我会做一些类似这样的操作:

const ConfigFileEnv = "ConfigFile" // 避免输入错误
var config Config
... 
if f, err := os.Open(os.Getenv(ConfigFileEnv)); err != nil {
  panic(fmt.Errorf("无法打开配置文件 %s: %w",
    os.Getenv(ConfigFileEnv),
    err,
  ))
} else if err := json.NewDecoder(f).Decode(&config); err != nil {
   panic(fmt.Errorf("无法从配置文件 %s 解码 JSON: %w", 
      os.Getenv(ConfigFileEnv),
      err,
   ))
}
// 现在配置文件已加载到config中
...
req.SetBasicAuth(config.Username, config.Password)

工作的最小示例(不包含你的逻辑):https://github.com/farrellit/stackoverflow/tree/main/69335827

英文:

Put the configuration data that wouldn't be true for everybody in environment variables.

Use os.Getenv() to retrieve the variables at runtime. Make sure they are set to something valid looking (at least not empty string) as part of your program's configuration.

You can then set the environment variables in a systemd configuration file if you're running this from systemd, or in the .bash_config for a user dedicated to this process, or wherever is the most convenient for where your program is executed.

Or, create a configuration file you can read from your program. I usually use Json encoding for configuration like this, but you could use anything. Reading secrets from configuration files might arguably be somewhat safer than environment variables which can often be introspected by system processes.

When I create a configuration file, I usually model my configuration with a struct,

type Config struct {
   Username string
   Password string
}

Then as part of my program's initialization, I'd do something like

const ConfigFileEnv "ConfigFile" // avoid typing errors 
var config Config
... 
if f, err := os.Open(os.Getenv(ConfigFileEnv); err != nil {
  panic(fmt.Errorf("Couldn't open config file %s: %w",
    os.Getenv(ConfigFileEnv),
    err,
  ))
} else if err := json.NewDecoder(f).Decode(&config); err != nil {
   panic(fmt.Errorf("Couldn't decode json from config file %s: %w", 
      os.Getenv(ConfigFileEnv),
      err
   )
}
// Now config file has been loaded into config
...
req.SetBasicAuth(config.Username, config.Password)

Working minimal example (without your logic): https://github.com/farrellit/stackoverflow/tree/main/69335827

huangapple
  • 本文由 发表于 2021年9月26日 22:22:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/69335827.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定