"error initializing client: connecting to desktop app: read: connection reset"

Options
wheelerlaw
wheelerlaw
Community Member

I am trying to execute the op command from a Golang app like so:

package main

import (
    "encoding/json"
    "log"
    "os/exec"
)

func main() {
    op := exec.Command("op", "item", "get", "DocSend", "--format=json")
    //op := exec.Command("env")
    out, err := op.Output()
    if e, ok := err.(*exec.ExitError); ok {
        log.Fatal(e, ": ", string(e.Stderr))
    }

    var item map[string]interface{}
    if err := json.Unmarshal(out, &item); err != nil {
        log.Fatal(err)
    }
    println(item["fields"])
}

However, I keep getting the following error:

2023/04/13 10:40:45 exit status 1: [ERROR] 2023/04/13 10:40:45 error initializing client: connecting to desktop app: read: connection reset, make sure the CLI is correctly installed and Connect with 1Password CLI is enabled in the 1Password app

When I perform the exact same thing but from a Python script like so:

#!/usr/bin/env python

import json
import subprocess

op = subprocess.run(["op", "item", "get", "DocSend", "--format=json"], capture_output=True)

item = json.loads(op.stdout)
print(item["fields"])

...there is no issue, and it happily prints out the item fields:

[{'id': 'username', 'type': 'STRING', 'purpose': 'USERNAME', 'label': 'username', 'value': ... }, ...]

Why can I not call op from a golang app but I can from a python one?

1PasswordCLI version 2.16.1
1Password version 8.10.4
OS: Fedora 37
Go 1.20.2
Python 3.10.9


1Password Version: 8.10.4
Extension Version: Not Provided
OS Version: Fedora 37
Browser:_ Not Provided

Comments

  • wheelerlaw
    wheelerlaw
    Community Member
    Options

    Interestingly enough, when I call the Python script from the Go app, it works fine. Given the following Python script named op.py:

    #!/usr/bin/env python
    
    import subprocess
    
    subprocess.run(["op", "item", "get", "DocSend", "--format=json"])
    

    and the following Go app in the same directory:

    package main
    
    import (
        "encoding/json"
        "fmt"
        "log"
        "os/exec"
    )
    
    func main() {
        op := exec.Command("/usr/bin/python3.11", "./op.py")
        //op := exec.Command("op", "item", "get", "DocSend", "--format=json")
        out, err := op.Output()
        if e, ok := err.(*exec.ExitError); ok {
            log.Fatal(e, ": ", string(e.Stderr))
        }
    
        fmt.Printf("%s", out)
    
        var item map[string]interface{}
        if err := json.Unmarshal(out, &item); err != nil {
            log.Fatal(err)
        }
        fmt.Println(item["fields"])
    }
    

    ...it works fine, the output gets printed. I can test that it is being printed by the Go app and not by the Python script because if I remove the fmt.Printf(...) and below, nothing gets printed.

  • wheelerlaw
    wheelerlaw
    Community Member
    Options

    The issue is reproducible. Here is a Vagrantfile that will reproduce the issue:

    # To replicate the issue with running the `op` command directly from a Golang app
    Vagrant.configure("2") do |config|
      config.vm.box = "generic/fedora37"
      config.vm.provider "virtualbox" do |vb|
        vb.gui = true
        vb.memory = "2048"
        vb.cpus = "2"
        vb.customize ["modifyvm", :id, "--graphicscontroller", "vmsvga"]
      end
      config.vm.provision "shell", privileged: false, inline: <<~'EOF'
        #!/usr/bin/env bash
    
        set -x
        sudo dnf update -y
        sudo dnf group install -y "Fedora Workstation" --allowerasing
        sudo systemctl enable gdm.service
        sudo systemctl set-default graphical.target
    
        sudo dnf install -y golang
        sudo rpm --import https://downloads.1password.com/linux/keys/1password.asc
        sudo sh -c 'echo -e "[1password]\nname=1Password Stable Channel\nbaseurl=https://downloads.1password.com/linux/rpm/stable/\$basearch\nenabled=1\ngpgcheck=1\nrepo_gpgcheck=1\ngpgkey=\"https://downloads.1password.com/linux/keys/1password.asc\"" > /etc/yum.repos.d/1password.repo'
        sudo dnf install -y 1password 1password-cli
    
        echo '
        package main
    
        import (
            "log"
            "os/exec"
            "os"
            "fmt"
        )
    
        func main() {
            fmt.Println(os.Args)
            var opExecutable string
            if os.Args[1] == "python" {
                opExecutable = "./op.py"
            } else if os.Args[1] == "direct" {
                opExecutable = "op"
            }
            op := exec.Command(opExecutable, "item", "list")
            out, err := op.Output()
            if e, ok := err.(*exec.ExitError); ok {
                log.Fatal(e, ": ", string(e.Stderr))
            }
    
            println(string(out))
        }
        ' > ~/main.go
    
        echo '#!/usr/bin/env python3
        import subprocess
        import sys
        subprocess.run(["op"] + sys.argv[1:])
        ' > ~/op.py
    
        chmod +x ~/op.py
    
        set +x
        echo "Now reboot the VM with 'vagrant reload'. Once that is done, log into the VM when it loads (password is 'vagrant'), sign into 1Password"
        echo "and configure it to allow connection from the CLI. Then, from the terminal in the VM, run 'op signin'."
        echo "To replicate the issue, run 'go run main.go direct'. To run it though Python, run 'go run main.go python'."
    
      EOF
    end
    
This discussion has been closed.