眾所周知,Golang 適合寫 CLI 工具,但你可能還不知道 Golang 還可以打包配置文件。
背景
最近在寫一個(gè)涉及到管理阿里云 ECS 的 CLI 工具,這里當(dāng)然就要考慮阿里云資源使用的安全性了,要求阿里云賬號(hào)的 AccessKeyId 和 AccessKeySecret 不能下發(fā)給 CLI 工具的使用者。
所以這里選擇將一份包含 AccessKeyId 和 AccessKeySecret 的配置文件打包進(jìn)了 CLI 工具中,CLI 工具的使用者默認(rèn)將使用已經(jīng)打包了的配置文件,當(dāng)然也可以通過(guò)指定配置文件或傳遞參數(shù)的方式使用新的配置信息。
實(shí)現(xiàn)
工具
這里將介紹 Golang 的一個(gè)可以把任意文件轉(zhuǎn)換成 Go 代碼的庫(kù) go-bindata,可以用于嵌入二進(jìn)制文件到 Go 程序中。同時(shí),也支持在轉(zhuǎn)換成原始的字節(jié)切片前使用 gzip 進(jìn)行壓縮文件數(shù)據(jù)。
關(guān)于該工具的具體介紹請(qǐng)?zhí)D(zhuǎn)至 https://github.com/go-bindata/go-bindata
打包
使用 go-bindata 工具將包含敏感信息的配置文件轉(zhuǎn)換成 Go 的源代碼,下面是項(xiàng)目 Makefile 的部分內(nèi)容,工具名稱就叫 mycli 吧。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
NAME = mycli CONFIG = configs/config.yaml .PHONY: build build: cp $(CONFIG) config.yaml mkdir -p cmd/mycli/asset go-bindata -pkg asset -o cmd/mycli/asset/asset.go \ scripts/... \ config.yaml CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/linux/mycli cmd/mycli/*.go CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o bin/darwin/mycli cmd/mycli/*.go chmod +x ./bin/linux/mycli ./bin/darwin/mycli rm -f config.yaml mycli ln -s bin/linux/mycli mycli |
其中將文件轉(zhuǎn)換成 Go 源代碼的部分如下:
1
2
3
|
go-bindata -pkg asset -o cmd/mycli/asset/asset.go \ scripts/... \ config.yaml |
關(guān)于 go-bindata 命令行工具的選項(xiàng)說(shuō)明:
- -pkg 指定 package 名稱,調(diào)用的寫法將變成 asset.Asset("config.yaml")
- -o 指定生成的 Go 源代碼存放的位置
生成的 asset.go 代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
// Code generated by go-bindata. // sources: // scripts/create.sh // scripts/sub/delete.sh // config.yaml // DO NOT EDIT! package asset func bindataRead(data []byte, name string) ([]byte, error) { ... } type asset struct { bytes []byte info os.FileInfo } type bindataFileInfo struct { name string size int64 mode os.FileMode modTime time.Time } func (fi bindataFileInfo) Name() string { return fi.name } func (fi bindataFileInfo) Size() int64 { return fi.size } func (fi bindataFileInfo) Mode() os.FileMode { return fi.mode } func (fi bindataFileInfo) ModTime() time.Time { return fi.modTime } func (fi bindataFileInfo) IsDir() bool { return false } func (fi bindataFileInfo) Sys() interface{} { return nil } ... |
調(diào)用
使用 Asset 方法進(jìn)行加載打包好的配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
const preloadConfigFile = "config.yaml" type Config struct { ... } func PreloadConfig() (*Config, error) { b, err := asset.Asset(preloadConfigFile) if err != nil { return nil, fmt.Errorf("failed to read config: %v", err) } var config *Config err = yaml.Unmarshal(b, &config) return config, err } |
總結(jié)
使用 go-bindata 將文件轉(zhuǎn)換成 Go 的源代碼,然后編譯成二進(jìn)制文件,最終只需要將二進(jìn)制文件交給使用者,通過(guò)這種方式可以減少工具的使用者對(duì)一些敏感信息的直接接觸,保障資源的安全性。
其實(shí),真正要做到對(duì)資源訪問(wèn)的完全把控,可以將 CLI 工具再次進(jìn)行封裝成 Jenkins job 類似的可視化操作界面,既方便使用者使用,又可以限制使用者對(duì)工具的使用范圍,包括傳遞給 CLI 工具的參數(shù)。
到此這篇關(guān)于Golang打包配置文件的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Golang打包配置文件內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://juejin.cn/post/6943973550185250847