Skip to content

Commit 91b35b2

Browse files
authored
fix: make secrets and other kv arg parsing more rubust (#629)
* fix: make secrets and other kv arg parsing more rubust * fix: use correct falg name for participant attribute
1 parent 676aa5b commit 91b35b2

File tree

4 files changed

+55
-46
lines changed

4 files changed

+55
-46
lines changed

cmd/lk/agent.go

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,10 @@ var (
9999
silentFlag,
100100
regionFlag,
101101
},
102-
ArgsUsage: "[working-dir]",
102+
// NOTE: since secrets may contain commas, or indeed any special character we might want to treat as a flag separator,
103+
// we disable it entirely here and require multiple --secrets flags to be used.
104+
DisableSliceFlagSeparator: true,
105+
ArgsUsage: "[working-dir]",
103106
},
104107
{
105108
Name: "config",
@@ -120,7 +123,10 @@ var (
120123
secretsFlag,
121124
secretsFileFlag,
122125
},
123-
ArgsUsage: "[working-dir]",
126+
// NOTE: since secrets may contain commas, or indeed any special character we might want to treat as a flag separator,
127+
// we disable it entirely here and require multiple --secrets flags to be used.
128+
DisableSliceFlagSeparator: true,
129+
ArgsUsage: "[working-dir]",
124130
},
125131
{
126132
Name: "status",
@@ -141,7 +147,10 @@ var (
141147
secretsFlag,
142148
secretsFileFlag,
143149
},
144-
ArgsUsage: "[working-dir]",
150+
// NOTE: since secrets may contain commas, or indeed any special character we might want to treat as a flag separator,
151+
// we disable it entirely here and require multiple --secrets flags to be used.
152+
DisableSliceFlagSeparator: true,
153+
ArgsUsage: "[working-dir]",
145154
},
146155
{
147156
Name: "restart",
@@ -237,7 +246,10 @@ var (
237246
Value: false,
238247
},
239248
},
240-
ArgsUsage: "[working-dir]",
249+
// NOTE: since secrets may contain commas, or indeed any special character we might want to treat as a flag separator,
250+
// we disable it entirely here and require multiple --secrets flags to be used.
251+
DisableSliceFlagSeparator: true,
252+
ArgsUsage: "[working-dir]",
241253
},
242254
},
243255
},
@@ -293,7 +305,7 @@ func createAgent(ctx context.Context, cmd *cli.Command) error {
293305
}
294306

295307
// We have a configured project, but don't need to double-confirm if it was
296-
// set via a command line flag, because intent it clear.
308+
// set via a command line flag, because intent is clear.
297309
if !cmd.IsSet("project") {
298310
useProject := true
299311
if err := huh.NewForm(huh.NewGroup(huh.NewConfirm().
@@ -1012,13 +1024,18 @@ func selectAgent(ctx context.Context, _ *cli.Command) (string, error) {
10121024
func requireSecrets(_ context.Context, cmd *cli.Command, required, lazy bool) ([]*lkproto.AgentSecret, error) {
10131025
silent := cmd.Bool("silent")
10141026
secrets := make(map[string]*lkproto.AgentSecret)
1015-
for _, secret := range cmd.StringSlice("secrets") {
1016-
secret := strings.Split(secret, "=")
1017-
agentSecret := &lkproto.AgentSecret{
1018-
Name: secret[0],
1019-
Value: []byte(secret[1]),
1027+
1028+
if values, err := parseKeyValuePairs(cmd, "secrets"); err != nil {
1029+
return nil, fmt.Errorf("failed to parse secrets: %w", err)
1030+
} else {
1031+
for key, val := range values {
1032+
agentSecret := &lkproto.AgentSecret{
1033+
Name: key,
1034+
Value: []byte(val),
1035+
}
1036+
secrets[key] = agentSecret
10201037
}
1021-
secrets[secret[0]] = agentSecret
1038+
10221039
}
10231040

10241041
shouldReadFromDisk := cmd.IsSet("secrets-file") || !lazy || (required && len(secrets) == 0)

cmd/lk/room.go

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"context"
1919
"encoding/json"
2020
"fmt"
21+
"maps"
2122
"os"
2223
"os/signal"
2324
"regexp"
@@ -940,14 +941,9 @@ func joinRoom(ctx context.Context, cmd *cli.Command) error {
940941
},
941942
}
942943

943-
participantAttributes := make(map[string]string)
944-
945-
attrs := cmd.StringSlice("attribute")
946-
for _, attr := range attrs {
947-
kv := strings.Split(attr, "=")
948-
if len(kv) == 2 {
949-
participantAttributes[kv[0]] = kv[1]
950-
}
944+
participantAttributes, err := parseKeyValuePairs(cmd, "attribute")
945+
if err != nil {
946+
return fmt.Errorf("failed to parse participant attributes: %w", err)
951947
}
952948

953949
// Read attributes from JSON file if specified
@@ -963,9 +959,7 @@ func joinRoom(ctx context.Context, cmd *cli.Command) error {
963959
}
964960

965961
// Add attributes from file to the existing ones
966-
for key, value := range fileAttrs {
967-
participantAttributes[key] = value
968-
}
962+
maps.Copy(participantAttributes, fileAttrs)
969963
}
970964

971965
room, err := lksdk.ConnectToRoom(project.URL, lksdk.ConnectInfo{

cmd/lk/utils.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ package main
1717
import (
1818
"errors"
1919
"fmt"
20+
"maps"
2021
"os"
2122
"strings"
2223

24+
"github.com/joho/godotenv"
2325
"github.com/twitchtv/twirp"
2426
"github.com/urfave/cli/v3"
2527

@@ -161,6 +163,24 @@ func extractFlagOrArg(c *cli.Command, flag string) (string, error) {
161163
return value, nil
162164
}
163165

166+
func parseKeyValuePairs(c *cli.Command, flag string) (map[string]string, error) {
167+
pairs := c.StringSlice(flag)
168+
if len(pairs) == 0 {
169+
return nil, nil
170+
}
171+
172+
result := make(map[string]string, len(pairs))
173+
174+
for _, pair := range pairs {
175+
if m, err := godotenv.Unmarshal(pair); err != nil {
176+
return nil, fmt.Errorf("invalid key-value pair: %s: %w", pair, err)
177+
} else {
178+
maps.Copy(result, m)
179+
}
180+
}
181+
return result, nil
182+
}
183+
164184
type loadParams struct {
165185
requireURL bool
166186
}

pkg/agentfs/secrets-file.go

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@
1515
package agentfs
1616

1717
import (
18-
"bufio"
1918
"os"
20-
"strings"
2119

2220
"github.com/charmbracelet/huh"
21+
"github.com/joho/godotenv"
2322
"github.com/livekit/livekit-cli/v2/pkg/util"
2423
)
2524

@@ -33,33 +32,12 @@ var knownEnvFiles = []string{
3332
}
3433

3534
func ParseEnvFile(file string) (map[string]string, error) {
36-
env := make(map[string]string)
3735
f, err := os.Open(file)
3836
if err != nil {
3937
return nil, err
4038
}
4139
defer f.Close()
42-
43-
scanner := bufio.NewScanner(f)
44-
for scanner.Scan() {
45-
line := scanner.Text()
46-
if strings.HasPrefix(line, "#") {
47-
continue
48-
}
49-
50-
parts := strings.SplitN(line, "=", 2)
51-
if len(parts) < 2 {
52-
continue
53-
}
54-
55-
parts[0] = strings.TrimSpace(parts[0])
56-
parts[1] = strings.TrimSpace(parts[1])
57-
parts[1] = strings.Trim(parts[1], "\"'")
58-
parts[1] = strings.Split(parts[1], "#")[0]
59-
env[parts[0]] = parts[1]
60-
}
61-
62-
return env, nil
40+
return godotenv.Parse(f)
6341
}
6442

6543
func DetectEnvFile(maybeFile string) (string, map[string]string, error) {

0 commit comments

Comments
 (0)