Skip to content

Commit 31c4dc4

Browse files
authored
Merge pull request #4 from guggero/newline-trim-fix
Newline trim fix
2 parents 70784c8 + fd7a6d3 commit 31c4dc4

File tree

11 files changed

+268
-95
lines changed

11 files changed

+268
-95
lines changed

.github/workflows/main.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ env:
1717
GOCACHE: /home/runner/work/go/pkg/build
1818
GOPATH: /home/runner/work/go
1919

20+
GO_VERSION: 1.17.6
21+
2022
jobs:
2123
########################
2224
# lint code
@@ -32,3 +34,32 @@ jobs:
3234

3335
- name: lint
3436
run: make lint
37+
38+
########################
39+
# run unit tests
40+
########################
41+
unit-test:
42+
name: run unit tests
43+
runs-on: ubuntu-latest
44+
steps:
45+
- name: git checkout
46+
uses: actions/checkout@v2
47+
48+
- name: go cache
49+
uses: actions/cache@v1
50+
with:
51+
path: /home/runner/work/go
52+
key: lnd-${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ github.job }}-${{ hashFiles('**/go.sum') }}
53+
restore-keys: |
54+
lndinit-${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ github.job }}-${{ hashFiles('**/go.sum') }}
55+
lndinit-${{ runner.os }}-go-${{ env.GO_VERSION }}-${{ github.job }}-
56+
lndinit-${{ runner.os }}-go-${{ env.GO_VERSION }}-
57+
lndinit-${{ runner.os }}-go-
58+
59+
- name: setup go ${{ env.GO_VERSION }}
60+
uses: actions/setup-go@v2
61+
with:
62+
go-version: '${{ env.GO_VERSION }}'
63+
64+
- name: run unit test
65+
run: make unit

Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ COMMIT_HASH := $(shell git rev-parse HEAD)
1010

1111
GOBUILD := go build -v
1212
GOINSTALL := go install -v
13-
GOTEST := go test
13+
GOTEST := go test -v
1414
DOCKER_TOOLS := docker run -v $$(pwd):/build lndinit-tools
1515

1616
GOFILES_NOVENDOR = $(shell find . -type f -name '*.go' -not -path "./vendor/*")
@@ -103,6 +103,10 @@ scratch: build
103103
# UTILITIES
104104
# =========
105105

106+
unit:
107+
@$(call print, "Running unit tests.")
108+
$(GOTEST) ./...
109+
106110
fmt: $(GOIMPORTS_BIN)
107111
@$(call print, "Fixing imports.")
108112
gosimports -w $(GOFILES_NOVENDOR)

cmd_gen_password.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func (x *genPasswordCommand) Execute(_ []string) error {
7373
}
7474
}
7575

76-
fmt.Printf("%s\n", passwordString)
76+
fmt.Printf("%s", passwordString)
7777

7878
return nil
7979
}

cmd_gen_seed.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ func (x *genSeedCommand) Execute(_ []string) error {
124124
}
125125
}
126126

127-
fmt.Printf("%s\n", seedWords)
127+
fmt.Printf("%s", seedWords)
128128

129129
return nil
130130
}

cmd_init_wallet.go

Lines changed: 88 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -107,76 +107,9 @@ func (x *initWalletCommand) Execute(_ []string) error {
107107
requireSeed := (x.InitType == typeFile) ||
108108
(x.InitType == typeRpc && !x.InitRpc.WatchOnly)
109109

110-
// First find out where we want to read the secrets from.
111-
var (
112-
seed string
113-
seedPassPhrase string
114-
walletPassword string
115-
err error
116-
)
117-
switch x.SecretSource {
118-
// Read all secrets from individual files.
119-
case storageFile:
120-
if requireSeed {
121-
log("Reading seed from file")
122-
seed, err = readFile(x.File.Seed)
123-
if err != nil {
124-
return err
125-
}
126-
}
127-
128-
// The seed passphrase is optional.
129-
if x.File.SeedPassphrase != "" {
130-
log("Reading seed passphrase from file")
131-
seedPassPhrase, err = readFile(x.File.SeedPassphrase)
132-
if err != nil {
133-
return err
134-
}
135-
}
136-
137-
log("Reading wallet password from file")
138-
walletPassword, err = readFile(x.File.WalletPassword)
139-
if err != nil {
140-
return err
141-
}
142-
143-
// Read passphrase from Kubernetes secret.
144-
case storageK8s:
145-
k8sSecret := &k8sSecretOptions{
146-
Namespace: x.K8s.Namespace,
147-
SecretName: x.K8s.SecretName,
148-
Base64: x.K8s.Base64,
149-
}
150-
k8sSecret.SecretKeyName = x.K8s.SeedKeyName
151-
152-
if requireSeed {
153-
log("Reading seed from k8s secret %s (namespace %s)",
154-
x.K8s.SecretName, x.K8s.Namespace)
155-
seed, _, err = readK8s(k8sSecret)
156-
if err != nil {
157-
return err
158-
}
159-
}
160-
161-
// The seed passphrase is optional.
162-
if x.K8s.SeedPassphraseKeyName != "" {
163-
log("Reading seed passphrase from k8s secret %s "+
164-
"(namespace %s)", x.K8s.SecretName,
165-
x.K8s.Namespace)
166-
k8sSecret.SecretKeyName = x.K8s.SeedPassphraseKeyName
167-
seedPassPhrase, _, err = readK8s(k8sSecret)
168-
if err != nil {
169-
return err
170-
}
171-
}
172-
173-
log("Reading wallet password from k8s secret %s (namespace %s)",
174-
x.K8s.SecretName, x.K8s.Namespace)
175-
k8sSecret.SecretKeyName = x.K8s.WalletPasswordKeyName
176-
walletPassword, _, err = readK8s(k8sSecret)
177-
if err != nil {
178-
return err
179-
}
110+
seed, seedPassPhrase, walletPassword, err := x.readInput(requireSeed)
111+
if err != nil {
112+
return fmt.Errorf("error reading input parameters: %v", err)
180113
}
181114

182115
switch x.InitType {
@@ -268,6 +201,91 @@ func (x *initWalletCommand) Execute(_ []string) error {
268201
}
269202
}
270203

204+
func (x *initWalletCommand) readInput(requireSeed bool) (string, string, string,
205+
error) {
206+
207+
// First find out where we want to read the secrets from.
208+
var (
209+
seed string
210+
seedPassPhrase string
211+
walletPassword string
212+
err error
213+
)
214+
switch x.SecretSource {
215+
// Read all secrets from individual files.
216+
case storageFile:
217+
if requireSeed {
218+
log("Reading seed from file")
219+
seed, err = readFile(x.File.Seed)
220+
if err != nil {
221+
return "", "", "", err
222+
}
223+
}
224+
225+
// The seed passphrase is optional.
226+
if x.File.SeedPassphrase != "" {
227+
log("Reading seed passphrase from file")
228+
seedPassPhrase, err = readFile(x.File.SeedPassphrase)
229+
if err != nil {
230+
return "", "", "", err
231+
}
232+
}
233+
234+
log("Reading wallet password from file")
235+
walletPassword, err = readFile(x.File.WalletPassword)
236+
if err != nil {
237+
return "", "", "", err
238+
}
239+
240+
// Read passphrase from Kubernetes secret.
241+
case storageK8s:
242+
k8sSecret := &k8sSecretOptions{
243+
Namespace: x.K8s.Namespace,
244+
SecretName: x.K8s.SecretName,
245+
Base64: x.K8s.Base64,
246+
}
247+
k8sSecret.SecretKeyName = x.K8s.SeedKeyName
248+
249+
if requireSeed {
250+
log("Reading seed from k8s secret %s (namespace %s)",
251+
x.K8s.SecretName, x.K8s.Namespace)
252+
seed, _, err = readK8s(k8sSecret)
253+
if err != nil {
254+
return "", "", "", err
255+
}
256+
}
257+
258+
// The seed passphrase is optional.
259+
if x.K8s.SeedPassphraseKeyName != "" {
260+
log("Reading seed passphrase from k8s secret %s "+
261+
"(namespace %s)", x.K8s.SecretName,
262+
x.K8s.Namespace)
263+
k8sSecret.SecretKeyName = x.K8s.SeedPassphraseKeyName
264+
seedPassPhrase, _, err = readK8s(k8sSecret)
265+
if err != nil {
266+
return "", "", "", err
267+
}
268+
}
269+
270+
log("Reading wallet password from k8s secret %s (namespace %s)",
271+
x.K8s.SecretName, x.K8s.Namespace)
272+
k8sSecret.SecretKeyName = x.K8s.WalletPasswordKeyName
273+
walletPassword, _, err = readK8s(k8sSecret)
274+
if err != nil {
275+
return "", "", "", err
276+
}
277+
}
278+
279+
// The seed, its passphrase and the wallet password should all never
280+
// have a newline at their end, otherwise that might lead to errors
281+
// further down the line.
282+
seed = stripNewline(seed)
283+
seedPassPhrase = stripNewline(seedPassPhrase)
284+
walletPassword = stripNewline(walletPassword)
285+
286+
return seed, seedPassPhrase, walletPassword, nil
287+
}
288+
271289
func createWalletFile(cipherSeed *aezeed.CipherSeed, walletPassword, walletDir,
272290
network string, validatePassword bool) error {
273291

cmd_init_wallet_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package main
2+
3+
import (
4+
"io/ioutil"
5+
"testing"
6+
7+
"github.com/stretchr/testify/require"
8+
)
9+
10+
var (
11+
testSeedWithNewline = []byte("seed phrase with newline\n")
12+
testPasswordWithNewline = []byte("p4ssw0rd\r\n\n\r\r\n")
13+
)
14+
15+
// TestReadInput makes sure input files are always trimmed so we don't have any
16+
// newline characters left over.
17+
func TestReadInput(t *testing.T) {
18+
cmd := newInitWalletCommand()
19+
20+
cmd.File.Seed = writeToTempFile(t, testSeedWithNewline)
21+
cmd.File.WalletPassword = writeToTempFile(t, testPasswordWithNewline)
22+
23+
seed, seedPassphrase, walletPassword, err := cmd.readInput(true)
24+
require.NoError(t, err)
25+
require.Equal(t, "seed phrase with newline", seed)
26+
require.Equal(t, "", seedPassphrase)
27+
require.Equal(t, "p4ssw0rd", walletPassword)
28+
}
29+
30+
func writeToTempFile(t *testing.T, data []byte) string {
31+
tempFileName, err := ioutil.TempFile("", "*.txt")
32+
require.NoError(t, err)
33+
34+
err = ioutil.WriteFile(tempFileName.Name(), data, 0600)
35+
require.NoError(t, err)
36+
37+
return tempFileName.Name()
38+
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/kkdai/bstream v1.0.0
88
github.com/lightninglabs/protobuf-hex-display v1.4.3-hex-display
99
github.com/lightningnetwork/lnd v0.14.2-beta
10+
github.com/stretchr/testify v1.7.0
1011
google.golang.org/grpc v1.38.0
1112
k8s.io/api v0.18.3
1213
k8s.io/apimachinery v0.18.3
@@ -92,7 +93,6 @@ require (
9293
github.com/sirupsen/logrus v1.7.0 // indirect
9394
github.com/soheilhy/cmux v0.1.5 // indirect
9495
github.com/spf13/pflag v1.0.5 // indirect
95-
github.com/stretchr/testify v1.7.0 // indirect
9696
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect
9797
github.com/ulikunitz/xz v0.5.10 // indirect
9898
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect

k8s.go

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -93,22 +93,14 @@ func readK8s(opts *k8sSecretOptions) (string, *jsonK8sObject, error) {
9393
opts.SecretKeyName)
9494
}
9595

96-
// Remove any newlines at the end of the file. We won't ever write a
97-
// newline ourselves but maybe the file was provisioned by another
98-
// process or user.
99-
content := stripNewline(string(secret.Data[opts.SecretKeyName]))
100-
10196
// There is an additional layer of base64 encoding applied to each of
10297
// the secrets. Try to de-code it now.
103-
if opts.Base64 {
104-
decoded, err := base64.StdEncoding.DecodeString(content)
105-
if err != nil {
106-
return "", nil, fmt.Errorf("failed to base64 decode "+
107-
"secret %s key %s: %v", opts.SecretName,
108-
opts.SecretKeyName, err)
109-
}
110-
111-
content = stripNewline(string(decoded))
98+
content, err := secretToString(
99+
secret.Data[opts.SecretKeyName], opts.Base64,
100+
)
101+
if err != nil {
102+
return "", nil, fmt.Errorf("failed to decode raw secret %s "+
103+
"key %s: %v", opts.SecretName, opts.SecretKeyName, err)
112104
}
113105

114106
return content, &jsonK8sObject{
@@ -243,3 +235,20 @@ func createSecretK8s(client *kubernetes.Clientset, opts *k8sSecretOptions,
243235

244236
return nil
245237
}
238+
239+
// secretToString turns the raw bytes of a secret into a string, removing the
240+
// additional layer of base64 encoding if there is expected to be one.
241+
func secretToString(rawSecret []byte, doubleBase64 bool) (string, error) {
242+
content := string(rawSecret)
243+
if doubleBase64 {
244+
decoded, err := base64.StdEncoding.DecodeString(content)
245+
if err != nil {
246+
return "", fmt.Errorf("failed to base64 decode: %v",
247+
err)
248+
}
249+
250+
content = string(decoded)
251+
}
252+
253+
return content, nil
254+
}

0 commit comments

Comments
 (0)