Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions cmd/dmr/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@
package main

import (
"bufio"
"context"
"fmt"
"os"
"os/exec"
"os/signal"
"path/filepath"
"strings"
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated
"syscall"

"github.com/docker/cli/cli/command"
Expand All @@ -27,6 +31,15 @@
}

func run() error {
if len(os.Args) > 1 {
switch os.Args[1] {
case "config":
return runConfig(os.Args[2:])
case "launch":
return runLaunch(os.Args[2:])
}
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated
}
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated

cli, err := command.NewDockerCli()
if err != nil {
return fmt.Errorf("unable to initialize CLI: %w", err)
Expand Down Expand Up @@ -67,3 +80,124 @@
},
}
}

func runConfig(args []string) error {
if len(args) != 2 {
return fmt.Errorf("usage: dmr config sandbox.tool <tool>")
}

key := args[0]
value := args[1]

if key != "sandbox.tool" {
return fmt.Errorf("unsupported config key %q", key)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps much better if we can add a list of supported tools in the top of the file and only support here like


var allowedSandboxTools = map[string]struct{}{
    "firejail":   {},
    "bubblewrap": {},
    "bwrap":      {},
}

if _, ok := allowedSandboxTools[value]; !ok {
        return fmt.Errorf("unsupported sandbox tool %q", sandboxTool)
    }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure but lets just start with sbx for this PR, these can be follow on PRs

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ericcurtin yes, this was my exact point, like it's better if we can specify the supported ones, both here and the launch

return writeSandboxToolConfig(value)
}

func runLaunch(args []string) error {
if len(args) == 0 {
return fmt.Errorf("usage: dmr launch <tool> [args...]")
}

sandboxTool, err := readSandboxToolConfig()
if err != nil {
return err
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same thing like above can be done here for verifying supported tools

if sandboxTool == "" {
return fmt.Errorf("sandbox.tool is not configured. Run: dmr config sandbox.tool <tool>")
}

cmd := exec.Command(sandboxTool, args...)

Check failure on line 113 in cmd/dmr/main.go

View workflow job for this annotation

GitHub Actions / lint (linux)

G702: Command injection via taint analysis (gosec)
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
Outdated
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

return cmd.Run()
}
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated

func dmrConfigPath() (string, error) {
configDir, err := os.UserConfigDir()
if err != nil {
return "", fmt.Errorf("unable to determine config directory: %w", err)
}

return filepath.Join(configDir, "dmr", "config.toml"), nil
}

func writeSandboxToolConfig(tool string) error {
path, err := dmrConfigPath()
if err != nil {
return err
}

if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
return fmt.Errorf("unable to create config directory: %w", err)
}

content := fmt.Sprintf("[sandbox]\ntool = %q\n", tool)

if err := os.WriteFile(path, []byte(content), 0o600); err != nil {
return fmt.Errorf("unable to write config: %w", err)
}
if err := os.Chmod(path, 0o600); err != nil {
return fmt.Errorf("unable to secure config permissions: %w", err)
}

return nil
}

func readSandboxToolConfig() (string, error) {
path, err := dmrConfigPath()
if err != nil {
return "", err
}

file, err := os.Open(path)
if os.IsNotExist(err) {
return "", nil
}
if err != nil {
return "", fmt.Errorf("unable to read config: %w", err)
}
defer file.Close()

inSandboxSection := false
scanner := bufio.NewScanner(file)

for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())

if line == "" || strings.HasPrefix(line, "#") {
continue
}

if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
inSandboxSection = line == "[sandbox]"
continue
}

if !inSandboxSection {
continue
}

key, value, ok := strings.Cut(line, "=")
if !ok {
continue
}

if strings.TrimSpace(key) != "tool" {
continue
}

return strings.Trim(strings.TrimSpace(value), `"`), nil
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated
Comment thread
CoderHariswar marked this conversation as resolved.
Outdated
}

if err := scanner.Err(); err != nil {
return "", fmt.Errorf("unable to parse config: %w", err)
}

return "", nil
}
Loading