[Feature Request] Using 1P SSH from inside a local Docker container

Ryan Parman
Ryan Parman
Community Member
edited May 2022 in SSH

My team and I regularly use Docker for lightweight local environments that are pre-configured with things we need to develop that project. (It helps avoid things like "works on my machine".) If I need to work on a Terraform module, I can launch the Docker environment that has all the tools I need pre-installed and ready-to-go, and I can make my changes, run tests, and perform all sorts of general software development tasks. When I'm done, I press Ctrl+D.

We can easily read specific environment variables from the host environment and pass them into the Docker environment (e.g., AWS credentials, Terraform variables), and for Git, we can mount the local SSH directory into the container in read-only mode so that we can fetch and push (-v ~/.ssh:/root/.ssh:ro) to GitHub Enterprise.

Herein lies the problem with migrating the SSH keys into 1Password and not having them on-disk. There's nothing to mount, and 1Password only runs on the host. The low-fi solution is to keep my SSH keys on-disk for Docker, while copying them into 1P for use with that SSH agent, but then what's the point to using 1Password SSH?

A higher-fi solution (since this is desktop-use Docker; not for deployment) would be the ability to mount a unix socket from the host into the Docker container, and have some kind of tiny agent built for Linux (namely Alpine Linux) that can run and facilitate whatever signals need to be sent so that when I run git pull inside the Docker container, this agent sends a signal to 1Password on the host asking for authentication.


1Password Version: 80600043 (beta channel)
Extension Version: N/A
OS Version: macOS 12.3β

«1

Comments

  • altano
    altano
    Community Member

    Are you SSHing into the Docker container from your local machine with 1Password? If so, can you use SSH agent forwarding? The 1P SSH docs don't mention it isn't supported but I haven't tested it myself.

  • altano
    altano
    Community Member
    edited February 2022

    I was curious so I just tested ForwardAgent with 1Password's agent: it works! 🎉

    • Local machine is a Mac with 1Password+agent.
    • I ssh'd into HostA which has my public key in authorized_keys
    • From within that ssh session, I ssh'd into HostB which also has my public key in authorized_keys. HostA does NOT have 1Password (it's a headless Linux lxc container)

    ~/.ssh/config entry is simple:

    host <myhost>
        ForwardAgent yes
    

    Note that ForwardAgent has some serious security considerations everyone should heed: https://vincent.bernat.ch/en/blog/2020-safer-ssh-agent-forwarding. In your case, you're treating your Docker container as a trusted local development machine and were ready to mount your private keys into it, so using ForwardAgent would obviously be even more secure and just fine for your situation.

    1Password experts: is there an opportunity for 1Password's agent to make ForwardAgent more secure by prompting on every use of the key, even through a server we've forwarded the key to? AddKeysToAgent confirm doesn't seem to accomplish this.

  • Ryan Parman
    Ryan Parman
    Community Member
    edited February 2022

    Without looking into your links (yet), it's important to note that the first hop (from host to local container) isn't over SSH. I'm using docker run, not ssh.

    SSH only comes into play during the second hop from the container → GitHub.

    I'm trying to figure out how to leverage 1P8 for the first hop.

  • SeanSith
    SeanSith
    Community Member
    edited March 2022

    I tried a 1Password 8 beta update (to "8700028, on Beta channel") and my preferred setup now works (it didn't before)!

    Nope, I was mistaken. I was testing in the wrong window.

    We're using a setup similar to what is described blog.unixshell.se/2020/01/quick-tip-use-host-ssh-agent-in-docker/.

    Effectively we've been doing the following:

    docker-compose.yml:

    version: '3'
    
    services:
      app:
        image: (most images should work, but I last tested with 'ruby:3.1')
        environment:
          SSH_AUTH_SOCK: /ssh-agent
        volumes:
          - $SSH_AUTH_SOCK:/ssh-agent
    

    then executing docker compose run --rm app /bin/bash and performing SSH activities from there.

    At this point, using the 1Password 8 SSH-Agent, I receive the following error:

    Error response from daemon: error while creating mount source path '/host_mnt/Users/seansith/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock': mkdir /host_mnt/Users/seansith/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock: operation not supported
    

    But when I use the macOS default ssh-agent at /run/host-services/ssh-auth.sock, it works fine.

  • SeanSith
    SeanSith
    Community Member

    We had been using a setup similar to what is described blog.unixshell.se/2020/01/quick-tip-use-host-ssh-agent-in-docker/.

    Effectively we've been doing the following:

    docker-compose.yml:

    version: '3'
    
    services:
      app:
        image: (most images should work, but I last tested with 'ruby:3.1')
        environment:
          SSH_AUTH_SOCK: /ssh-agent
        volumes:
          - $SSH_AUTH_SOCK:/ssh-agent
    

    then executing docker compose run --rm app /bin/bash and performing SSH activities from there.

    Unfortunately, with the 1Password agent, we receive the following error message:

    Error response from daemon: error while creating mount source path '/host_mnt/Users/seansith/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock': mkdir /host_mnt/Users/seansith/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock: operation not supported
    

    This works just fine with the macOS default SSH agent.

    Setup:

    • macOS 12.3
    • Docker Desktop for Mac 4.6.1
    • 1Password 8 (80700028, on BETA channel)
  • oandreyev
    oandreyev
    Community Member

    Using Linux and Docker, it's pretty easy to forward agent to docker... but...

    Here the command:

    docker-compose run -it -v $(readlink -f $SSH_AUTH_SOCK):/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent php bash
    

    running ssh -vvv user@host

    getting logs:

    debug3: sign_and_send_pubkey: signing using rsa-sha2-512 SHA256:DOtczsfW9/BfTeVkOL4jqTmT7z4BOkocRdFs3LjG4ng
    sign_and_send_pubkey: signing failed for RSA "SSH Key | RSA 4096" from agent: agent refused operation
    

    1P logs:

    ==> 1Password_r00018.log <==
    INFO  2022-06-22T15:53:18.791 tokio-runtime-worker(ThreadId(16)) [1P:foundation/op-sys-info/src/process_information/linux.rs:367] no GUI info available to determine top level parent
    ERROR 2022-06-22T15:53:18.791 tokio-runtime-worker(ThreadId(16)) [1P:ssh/op-session-info/src/linux.rs:10] process tree is empty
    WARN  2022-06-22T15:53:18.791 tokio-runtime-worker(ThreadId(16)) [1P:ssh/op-ssh-agent/src/lib.rs:356] Unable to get client_info for pid: 826034
    

    so the problem is that 1P is trying to open Password Prompt and fails.

  • floris_1P
    edited June 2022

    @SeanSith @Ryan Parman
    On macOS, you should be able to 'forward' your SSH_AUTH_SOCK to your Docker container by adding these magic flags to your docker run command:
    -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock -e SSH_AUTH_SOCK="/run/host-services/ssh-auth.sock"
    More info here and here.

    One thing to keep in mind here though is that you will be authorizing Docker Desktop entirely. So every new Docker container launched from any terminal tab will automatically be authorized to use that key.

  • SeanSith
    SeanSith
    Community Member

    @floris_1P That socket is/was macOS's default ssh-agent socket. Is 1Password hooking into that/overwriting it somehow to make this work? I'd tried to mount the socket from the original SSH documentation into the container but was probably blocked by sandboxing. I'm curious because that reduces the amount of setup my users will have to go through and potentially unlocks some other usage for us.

  • floris_1P
    edited June 2022

    @SeanSith Could you try if this works:

    export SSH_AUTH_SOCK=~/Library/Group\ Containers/2BUA8C4S2C.com.1password/t/agent.sock
    docker run -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock -e SSH_AUTH_SOCK="/run/host-services/ssh-auth.sock" alpine sh -c 'apk add openssh && ssh-add -l'
    
  • SeanSith
    SeanSith
    Community Member

    @floris_1P Yes, both what you suggested 3 hours ago and your most recent message work. More surprised that it does because I had previously not been able to talk to 1Password when using macOS's default ssh-agent socket. Prior to integrating with 1Password for ssh-agent support, we'd been passing macOS's agent using the same socket. In initial testing, however, /run/host_services/ssh-auth.sock had not worked. Glad that it does now, though, as it helps us avoid having to tweak docker-compose.yml files for our development team.

  • Great!

  • jpgrusling
    jpgrusling
    Community Member

    @floris_1P I have been able to follow your instructions to get a similar setup working on macOS. However, when I try to repeat this on a Ubuntu machine, I am unsuccessful. It appears to be getting hung up on being able to prompt for system credentials. I can use the SSH agent outside of the container, but inside it fails with the error sign_and_send_pubkey indicating agent refused operation. Please let me know if you have any ideas.

  • @jpgrusling The solution in this thread is only intended for Docker for Mac. Support for Docker for Linux is something we're looking to improve on. What would help us get there is if you could provide us with your SSH agent diagnostics, as described here.

  • juanitototo
    juanitototo
    Community Member

    @floris_1P I have tried this solution you proposed but somehow still seems to be using the system ssh-agent rather than the 1password unix socket.

    What makes you think that adding the env variable SSH_AUTH_SOCK will change behaviour from the docker "hypervisor" when mounting the /run/host-services/ssh-auth.sock ? Surely this variable is local to that and outside of the magic that happens with the /run/host-services/ssh-auth.sock mountpoint ?

  • juanitototo
    juanitototo
    Community Member
    edited November 2022

    Ok so forget that last comment, actually open Docker from terminal using open -a Docker works, rather than opening from Spotlight seach. So indeed this env variable needs to be set before docker starts more info here https://github.com/docker/for-mac/issues/6541

  • jpgrusling
    jpgrusling
    Community Member

    @floris_1P I did follow up with the logs as requested. I haven't heard back yet so I just want to make sure the logs were forwarded to you.

  • Hi @jpgrusling:

    I took a look for your message, and it looks like my colleague Dayton was able to confirm that we received the logs early in November and replied to your message. Let me know if you didn't receive it, and I can take a closer look.

    Jack

  • jpgrusling
    jpgrusling
    Community Member

    @Jack.P_1P Dayton responded only to say that they had forwarded the logs to @floris_1P.

  • Hi @jpgrusling:

    We're continuing to investigate this SSH issue, so we'll be sure to let you know as soon as we know more. Thanks for sharing your logs!

    Jack

  • aetos
    aetos
    Community Member

    I am working with Windows and VSCode DevContainer.
    Creating a repository on a Docker Volume instead of mounting a local directory improves performance and enables change watching using inotify.
    In this case, Git must be run inside the Docker container to clone the code, sign the commit, and push it, which requires SSH.
    However, there is no way to communicate between the SSH client in the Docker container and the 1Password SSH Agent on Windows.
    Unlike WSL, the npiperelay cannot be run on the Docker container.

    When I execute Git commands on the container, I want to be automatically prompted for authentication by Windows Hello to use the SSH key managed by 1Password.

  • Hi @aetos:

    Are you able to configure which command is used to connect to your container? If you use ssh -A to forward your SSH agent, then you should be prompted to use 1Password for SSH. Let me know how you get on with that.

    Jack

  • aetos
    aetos
    Community Member
    edited December 2022

    I use docker run -it and do not use SSH to connect to the container.

  • ajm1811
    ajm1811
    Community Member

    Did anyone get any further with this from a Windows box? I'd be really interested to know if anyone has got that to work as that's exactly what I'm trying to do. I want to develop in VSCode/devcontainers from my Windows machine but have 1P handle the ssh keys to my repos in GitHub.

  • Hi @ajm1811:

    Are you using WSL2 or Hyper-V backed containers? I've just tested on my end, and I was able to use WSL2 backed containers with 1Password SSH agent. Let me know.

    Jack

  • ajm1811
    ajm1811
    Community Member

    Thanks for the reply @Jack.P_1P. I'm using WSL2. Running ssh-add -l from inside the container does indeed list my key. Also ssh -T git@github.com passes as well. But when I try to clone my repo from inside the container I get this:

    Any idea what I'm missing?

  • Hi @ajm1811:

    Thanks for following up! I've done a bit more investigation into this, and have determined the cause. When VSCode deploys a devcontainer, it copies some of your dotfiles from your Windows profile into your container for a consistent experience. One of the files copied in is your ~/.gitconfig file. Because of this, any settings that are set in your Windows ~/.gitconfig file are now set in the container.

    The solution for this is two separate actions to take:

    • If when you installed Git for Windows, you selected "Use bundled OpenSSH" or an option to pick which SSH client wasn't available, uninstall and reinstall Git for Windows, and select "Use external OpenSSH".

    • Additionally, remove the setting sshCommand = C:/Windows/System32/OpenSSH/ssh.exe from your ~/.gitconfig file in your Windows profile.

    This will result in Git in the context of Windows no longer having a bundled SSH, which means it'll use the system SSH (which is supported by 1Password SSH agent). When your ~/.gitconfig is copied into the container, it won't contain the line setting the SSH command, so your container won't attempt to use an SSH it can't access.

    Let me know how you get on with that!

    Jack

  • ajm1811
    ajm1811
    Community Member

    @Jack.P_1P - it worked!! I had to uninstall git a couple of times, delete any remaining files and then reboot before reinstalling but it's working now. Thanks so much.

  • Glad to hear it @ajm1811! Feel free to get in touch if there's anything else we can help you with.

    Jack

  • girish
    girish
    Community Member

    @floris_1P can you help me with this? - this is in docker for mac - followed all steps here https://developer.1password.com/docs/ssh/agent/compatibility/#ssh-auth-sock

    However, this works great.

    export SSH_AUTH_SOCK=~/Library/Group\ Containers/2BUA8C4S2C.com.1password/t/agent.sock
    docker run -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock -e SSH_AUTH_SOCK="/run/host-services/ssh-auth.sock" alpine sh -c 'apk add openssh && ssh-add -l'
    
    fetch https://dl-cdn.alpinelinux.org/alpine/v3.17/main/aarch64/APKINDEX.tar.gz
    fetch https://dl-cdn.alpinelinux.org/alpine/v3.17/community/aarch64/APKINDEX.tar.gz
    (1/10) Installing openssh-keygen (9.1_p1-r2)
    (2/10) Installing ncurses-terminfo-base (6.3_p20221119-r0)
    (3/10) Installing ncurses-libs (6.3_p20221119-r0)
    (4/10) Installing libedit (20221030.3.1-r0)
    (5/10) Installing openssh-client-common (9.1_p1-r2)
    (6/10) Installing openssh-client-default (9.1_p1-r2)
    (7/10) Installing openssh-sftp-server (9.1_p1-r2)
    (8/10) Installing openssh-server-common (9.1_p1-r2)
    (9/10) Installing openssh-server (9.1_p1-r2)
    (10/10) Installing openssh (9.1_p1-r2)
    Executing busybox-1.35.0-r29.trigger
    OK: 15 MiB in 25 packages
    256 SHA256:[XXXXXX] SSH Key ED25519 M2 (ED25519)
    

    My current docker-compose has the following:

     environment:
          - SSH_AUTH_SOCK='/run/host-services/ssh-auth.sock'
    volumes:
        - /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock
    
  • Hi @girish:

    I notice this looks like Visual Studio Code's remote development extension. Is that correct? Would you mind sharing the contents of ~/.ssh/config from macOS, rather than your Docker container? I'll be able to dig in more once I've seen your SSH config.

    Jack