microsoft / vscode-remote-release

Visual Studio Code Remote Development: Open any folder in WSL, in a Docker container, or on a remote machine using SSH and take advantage of VS Code's full feature set.
https://aka.ms/vscode-remote
Other
3.6k stars 273 forks source link

Containers: Git credentials helper for external shells #4202

Open fhuonder opened 3 years ago

fhuonder commented 3 years ago

I have Windows 10 with Docker for Windows, WSL 2 and the docker engine is integrated into the WSL2. The devcontainer is a Ubuntu 20.04 based image.

In the WSL I configured git according to https://docs.microsoft.com/en-us/windows/wsl/tutorials/wsl-git (git credential manager setup). In the running devcontainer git works. In the devcontainer's bash shell it does not. On every git command it says Remote-Containers CLI: RPC pipe not configured. Message: {"command":"fill","stdin":"protocol=https\nhost=bitbucket.org\nusername=fhuonder\n"}

In the devcontainer's bash the git config for the credential helper looks like credential.helper=!f() { /root/.vscode-server/bin/940b5f4bb5fa47866a54529ed759d95d09ee80be/node /tmp/vscode-remote-containers-f71604cb655ae555002aed74e1d2d934ff7f5afe.js $*; }; f

Any hints? I already searched to issues but only found similar issue but not exactly the same.

Regards, Florian

chrmarti commented 3 years ago

Is the REMOTE_CONTAINERS_IPC environment variable somehow unset in your terminal?

fhuonder commented 3 years ago

Hi @chrmarti It is set

root@2da8b293a15f:/workspaces/myworkspace# echo $REMOTE_CONTAINERS_IPC
/tmp/vscode-remote-containers-ipc-5dc5cb2dc65472fbedc40278f4bd1686999cf2c9.sock
chrmarti commented 3 years ago

The error message should only show when that environment variable is not set. Could you post your devcontainer.json?

fhuonder commented 3 years ago

Here it is

{
    "name": "app",
    "dockerComposeFile": [
        "./docker-compose.yml"
    ],
    "service": "app",
    "shutdownAction": "stopCompose",
    "workspaceFolder": "/workspaces/myworkspace",
    "extensions": [
        "ms-azuretools.vscode-docker@1.8.1",
        "dart-code.dart-code@3.17.0",
        "dart-code.flutter@3.17.0",
        "k--kato.intellij-idea-keybindings@0.2.41",
        "abhiagr.logcat@0.0.7",
        "humao.rest-client@0.24.4"
    ],
    "forwardPorts": [
        9100
    ],
    "remoteEnv": {
        "ANDROID_SDK_ROOT": "/android-sdk",
        "ANDROID_HOME": "/android-sdk"
    },
    "settings": {
        "workbench.editor.enablePreview": false,
        "workbench.editor.enablePreviewFromQuickOpen": false,
        "files.associations": {
            "*.arb": "json"
        },
        "debug.openDebug": "openOnDebugBreak",
        "dart.flutterSdkPath": "/flutter",
        "dart.lineLength": 180,
        "editor.rulers": [
            180
        ],
        "[dart]": {
            "editor.selectionHighlight": false,
            "editor.suggest.snippetsPreventQuickSuggestions": false,
            "editor.suggestSelection": "first",
            "editor.tabCompletion": "onlySnippets",
            "editor.wordBasedSuggestions": false,
        }
    },
    "postStartCommand": "flutter doctor -v"
}
chrmarti commented 3 years ago

Could you also attach the docker-compose.yml? I'd like to understand if there is a chance of the credential helper being called twice.

fhuonder commented 3 years ago

docker-compose.yml

version: '3'
services:
    app:
        build:
            context: .
            dockerfile: ./Dockerfile
        environment:
          - ADB_SERVER_SOCKET=tcp:host.docker.internal:5037
          - TZ=Europe/Zurich
        volumes: 
          - ..:/workspaces/myworkspace:delegated
          - ~/.aws:/home/root/.aws:ro
          - app-commandhistory:/commandhistory
          - app-androidsdk:/android-sdk
          - app-pubcache:/flutter/.pub-cache
          - /var/run/docker.sock:/var/run/docker.sock
        networks: 
            - app-network
        command: >
            bash -c "
            { echo -n 10388 | xargs -d ' ' -I% bash -c 'socat tcp-listen:%,fork tcp:host.docker.internal:% &' ; }
            && /bin/sh -c \"while sleep 1000; do :; done\""

networks:
    app-network:
        external:
            name: xyz

volumes:
    app-commandhistory:
    app-androidsdk:
    app-pubcache:
fhuonder commented 3 years ago

For the sake of completness, here the Dockerfile:

FROM ubuntu:20.04

ENV TZ=Europe/Zurich
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

ARG ANDROID_COMMANDLINE_TOOLS_ARTIFACT=https://dl.google.com/android/repository/commandlinetools-linux-6609375_latest.zip
ARG ANDROID_PLATFORM=android-29
ARG ANDROID_BUILD_TOOLS=30.0.3
ARG FLUTTER_ARTIFACT=https://storage.googleapis.com/flutter_infra/releases/dev/linux/flutter_linux_1.24.0-7.0.pre-dev.tar.xz

# replace shell with bash so we can source files
RUN rm /bin/sh && ln -s /bin/bash /bin/sh

# Hack to get openjdk to install in a container
RUN mkdir -p /usr/share/man/man1 \
    && mkdir -p /usr/share/man/man7

RUN echo "export PROMPT_COMMAND='history -a' && export HISTFILE=/commandhistory/.bash_history" >> "/root/.bashrc" && \
    echo "alias ll='ls -al'" >> "/root/.bashrc" && \
    echo "alias ..='cd ..'" >> "/root/.bashrc" && \
    echo "alias cd..='cd ..'" >> "/root/.bashrc" && \
    echo "alias cls='clear'" >> "/root/.bashrc"

RUN mkdir -p /etc/apk/ && \
    echo 'http://dl-cdn.alpinelinux.org/alpine/v3.9/community' > /etc/apk/repositories && \
    apt-get update && \
    apt-get install -y vim curl git tig docker-compose mongo-tools mongodb-clients rsync zip unzip awscli xz-utils lib32stdc++6 openjdk-8-jdk-headless net-tools socat

# Android SDK
RUN curl -o commandlinetools-linux.zip ${ANDROID_COMMANDLINE_TOOLS_ARTIFACT}
RUN mkdir -p android-sdk/cmdline-tools && unzip /commandlinetools-linux.zip -d android-sdk/cmdline-tools
RUN rm /commandlinetools-linux.zip
ENV PATH="/android-sdk/cmdline-tools/tools/bin:/android-sdk/build-tools:/android-sdk/platform-tools:${PATH}"

# SDK manager
RUN yes | sdkmanager --licenses
RUN sdkmanager "platforms;${ANDROID_PLATFORM}" "platform-tools" "build-tools;${ANDROID_BUILD_TOOLS}"

# Flutter
RUN curl -o flutter.tar.xz ${FLUTTER_ARTIFACT}
RUN tar xf flutter.tar.xz
RUN rm flutter.tar.xz
ENV PATH="/flutter/bin:${PATH}"

RUN flutter config --no-analytics

#Coloring
COPY dircolors/dircolors.256dark /root/.dircolors
RUN echo "set background=dark" > /root/.vimrc

#git autocomplete
ADD https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash /root/.git-completion.bash
RUN echo -e "if [ -f ~/.git-completion.bash ]; then\n"\
            ". ~/.git-completion.bash\n"\
            "fi\n"\
            >> /root/.bashrc

#flutter autocomplete
RUN flutter bash-completion > /root/.flutter-completion.bash
RUN echo -e "if [ -f ~/.flutter-completion.bash ]; then\n"\
            ". ~/.flutter-completion.bash\n"\
            "fi\n"\
            >> /root/.bashrc
chrmarti commented 3 years ago

That should work. Can you try running the credentials helper manually in the remote terminal that has REMOTE_CONTAINERS_IPC set? You need to copy the exact identifiers from the .gitconfig, add get at the end and then press enter when it waits for input:

/root/.vscode-server/bin/.../node /tmp/vscode-remote-containers-....js get
fhuonder commented 3 years ago

This is the output

root@2da8b293a15f:/workspaces/myworkspace# /root/.vscode-server/bin/ea3859d4ba2f3e577a159bc91e3074c5d85c0523/node /tmp/vscode-remote-containers-b8a645161f92ae794ce8b38d191ce25cb14157aa.js get

fatal: refusing to work with credential missing host field
chrmarti commented 3 years ago

Are you seeing the Remote-Containers CLI: RPC pipe not configured. error in that same terminal?

fhuonder commented 3 years ago

Ah sorry.. No...

From the vscode integrated terminal the output is

root@2da8b293a15f:/workspaces/myworkspace# /root/.vscode-server/bin/ea3859d4ba2f3e577a159bc91e3074c5d85c0523/node /tmp/vscode-remote-containers-b8a645161f92ae794ce8b38d191ce25cb14157aa.js get

fatal: refusing to work with credential missing host field
root@2da8b293a15f:/workspaces/digitalassistant# git fetch

Git fetch is successful.

When I connect to the bash of the container via docker (docker exec -it <devcontainerid> bash) the output is

root@2da8b293a15f:/workspaces/myworkspace# /root/.vscode-server/bin/ea3859d4ba2f3e577a159bc91e3074c5d85c0523/node /tmp/vscode-remote-containers-b8a645161f92ae794ce8b38d191ce25cb14157aa.js get

Remote-Containers CLI: RPC pipe not configured. Message: {"command":"fill","stdin":"\n"}
root@2da8b293a15f:/workspaces/digitalassistant# git fetch
Remote-Containers CLI: RPC pipe not configured. Message: {"command":"fill","stdin":"protocol=https\nhost=bitbucket.org\nusername=fhuonder\n"}
Remote-Containers CLI: RPC pipe not configured. Message: {"command":"fill","stdin":"protocol=https\nhost=bitbucket.org\nusername=fhuonder\n"}
Password for 'https://fhuonder@bitbucket.org':

In the bash started through docker the env variable REMOTE_CONTAINERS_IPC is empty.

Sorry for the confusion.

So how to correctly set the variable for this scenario? I like to connect to the bash because the integrated terminal is not so handy because it cannot be popped out.

chrmarti commented 3 years ago

The problem with the REMOTE_CONTAINERS_IPC socket is that it only works for as long as VS Code is running. With that limitation, you could copy its value from the integrated terminal and set it in your docker exec session.

fhuonder commented 3 years ago

Hmmm... For me it would be okay when it runs as long as vscode is running. Isn't there any possibility to set it automatically for all shells (independent of where they are started from)?

chrmarti commented 3 years ago

It would make sense, but the implementation needs more thought. Marking as feature request. Thanks.

arkiaconsulting commented 3 years ago

A temporary workaround (ugly) to populate de REMOTE_CONTAINERS_IPC inside your external shell:

......
"postCreateCommand": "echo 'export REMOTE_CONTAINERS_IPC=$(find /tmp -name vscode-remote-containers-ipc*)' >> ~/.bashrc"
.......

not good: the environment variable takes an additional value each time the container is restarted

max06 commented 3 years ago

I'm using

docker exec -it $(docker ps -qf 'label=name=DevContainer for x') bash -c 'SSH_AUTH_SOCK=$(ls -t /tmp/vscode-ssh-auth* | head -1) TERM=xterm-256color bash'

to connect to a running devcontainer and have access to my ssh-agent - similar to what you're trying to achive. Pretty sure you can adapt this.

posita commented 2 years ago

I'm using

docker exec -it $(docker ps -qf 'label=name=DevContainer for x') bash -c 'SSH_AUTH_SOCK=$(ls -t /tmp/vscode-ssh-auth* | head -1) TERM=xterm-256color bash'

to connect to a running devcontainer and have access to my ssh-agent - similar to what you're trying to achive. Pretty sure you can adapt this.

That won't always work because of #6346.

Bjoernolav commented 2 years ago

I'm having the same problem. I use https for authentication, and share my git credentials with wsl. Running ubuntu-22.04 in wsl, and git authentication works as expected there. Furthermore, I have my code checked out in wsl and run VSCode from wsl (so the setup is Windows -> wsl -> dev container).

Using this setup, the git credentials is not shared from wsl to the dev conainer, and the REMOTE_CONTAINERS_IPC variable is emtpy in the dev container. If I run export REMOTE_CONTAINERS_IPC=$(find /tmp -name vscode-remote-containers-ipc*) in the dev container (from the example above), git works from the dev container.

my devcontainer.json file looks like:

// See https://aka.ms/vscode-remote/devcontainer.json for format details.
{
    "build": { 
        "dockerfile": "Dockerfile"
    },
    "runArgs": [
        "--network=host",
        "--cap-add=SYS_PTRACE",
        "--security-opt=seccomp:unconfined",
        "--security-opt=apparmor:unconfined",
        "--name",
        "dev_container"
    ],
    "mounts": [
        "type=bind,source=/tmp/.X11-unix,target=/tmp/.X11-unix",
        "type=bind,source=/mnt/wslg,target=/mnt/wslg",
        "type=bind,source=/etc/apt/auth.conf.d,target=/etc/apt/auth.conf.d"
    ],
    "containerEnv": {
        "DISPLAY": "${localEnv:DISPLAY}",
        "WAYLAND_DISPLAY": "${localEnv:WAYLAND_DISPLAY}",
        "XDG_RUNTIME_DIR": "${localEnv:XDG_RUNTIME_DIR}",
        "PULSE_SERVER": "${localEnv:PULSE_SERVER}"
    },
    "appPort": [
        "2001-2004:2001-2004/udp",
        "2010:2010/udp",
        "5095-5096:5095-5096/udp"
    ],
    "onCreateCommand": "sudo apt-get update && sudo apt-get install -y openssh-client",
    // Set *default* container specific settings.json values on container create.
    "settings": {
        "terminal.integrated.profiles.linux": {
            "bash": {
                "path": "bash"
            },
        },
        "terminal.integrated.defaultProfile.linux": "bash"
    },
    "extensions": [
        "ms-vscode.cpptools-extension-pack",
        "ms-vscode.cmake-tools",
        "twxs.cmake",
        "ms-python.python"
    ]
}
skurhse commented 2 years ago

working for me if the container is running with vscode up; gets the most recently modified socket.

docker container exec -it -- $container /usr/bin/env bash -c '
    export REMOTE_CONTAINERS_IPC=$(
      find /tmp -name '\''vscode-remote-containers-ipc*'\'' -type s \
        -printf "%T@ %p\n" | sort -n | cut -d " " -f 2- | tail -n 1);$SHELL'
cjbottaro commented 1 year ago

We are this extension to attach to an already running container. Our main workflow is to docker exec shells in the already container. I don't understand why this extension breaks that workflow.

y22uta commented 1 year ago

I was able to solve a similar problem by referring to this article. Thank you very much. https://rexbytes.com/2022/08/23/visual-studio-docker-container-target-stop-importing-local-git-config/

metaskills commented 1 year ago

I made a little shell function which includes some of the help here. Sharing below:

function dc-console() {
  DEVC_JSON=$(devcontainer read-configuration --workspace-folder .)
  DEVC_USER=$(echo $DEVC_JSON | jq -r '.configuration.remoteUser' || echo 'vscode')
  DEVC_WORKDIR=$(echo $DEVC_JSON | jq -r '.workspace.workspaceFolder')
  CONTAINER_ID=$(docker ps --filter "status=running" --filter "label=devcontainer.local_folder=$(pwd)" --format "{{.ID}}")
  SSH_AUTH_SOCK=$(docker exec $CONTAINER_ID bash -c 'ls -t /tmp/vscode-ssh-auth* | head -1')
  REMOTE_CONTAINERS_IPC=$(docker exec $CONTAINER_ID bash -c 'find /tmp -name "vscode-remote-containers-ipc*" | head -1')
  docker exec \
    --env REMOTE_CONTAINERS=true \
    --env REMOTE_CONTAINERS_IPC=$REMOTE_CONTAINERS_IPC \
    --env SSH_AUTH_SOCK=$SSH_AUTH_SOCK \
    --env GITHUB_USER \
    --env GITHUB_TOKEN \
    --user $DEVC_USER \
    --workdir $DEVC_WORKDIR \
    --interactive \
    --tty \
    $CONTAINER_ID \
    /bin/zsh
}
BigCat3997 commented 1 year ago

I was able to solve a similar problem by referring to this article. Thank you very much. https://rexbytes.com/2022/08/23/visual-studio-docker-container-target-stop-importing-local-git-config/

This worked perfect, thanks a lot.

reconlabs-sergio commented 1 year ago

I was able to solve a similar problem by referring to this article. Thank you very much. https://rexbytes.com/2022/08/23/visual-studio-docker-container-target-stop-importing-local-git-config/

This solved my issues and should be the extension's default behaviour!!!!!! 😡