Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Private SSH Dependencies #401

Closed
Raniz85 opened this issue Apr 1, 2020 · 11 comments
Closed

Feature Request: Private SSH Dependencies #401

Raniz85 opened this issue Apr 1, 2020 · 11 comments
Labels
A-config Area: cross-toml config enhancement

Comments

@Raniz85
Copy link

Raniz85 commented Apr 1, 2020

I ran into a wall when trying to compile a project with dependencies on private Git repositories. Since these require the use of my private key they fail.

It would be nice if we could specify a private key to forward in Cross.toml - or forward the socket to the SSH agent.

@Raniz85
Copy link
Author

Raniz85 commented Apr 1, 2020

The SSH Agent socket can be forwarded using the following options to Docker run:

--volume $SSH_AUTH_SOCK:/ssh-agent --env SSH_AUTH_SOCK=/ssh-agent

It would be nice to have an option in Cross.toml that runs the build with this on the docker command line.

@philippludwig
Copy link

How exactly did you accomplish that? With a setting in Cross.toml?

@Raniz85
Copy link
Author

Raniz85 commented Jul 12, 2020

I have not accomplished this, this is a feature request. I'll edit the title to clarify that

@Raniz85 Raniz85 changed the title Private SSH Dependencies Feature Request: Private SSH Dependencies Jul 12, 2020
@TotalKrill
Copy link

Found a solution, cross allows to specify custom commands to the docker container being run through DOCKER_OPTS env variable.

So for me using fish shell:

env DOCKER_OPTS="--volume $SSH_AUTH_SOCK:/ssh-agent --env SSH_AUTH_SOCK=/ssh-agent" cross build --target armv7-unknown-linux-gnueabihf -v

you should see your ssh agent in the output from there since I added the verbose flag

@saskenuba
Copy link

saskenuba commented Jan 14, 2022

Found a solution, cross allows to specify custom commands to the docker container being run through DOCKER_OPTS env variable.

So for me using fish shell:

env DOCKER_OPTS="--volume $SSH_AUTH_SOCK:/ssh-agent --env SSH_AUTH_SOCK=/ssh-agent" cross build --target armv7-unknown-linux-gnueabihf -v

you should see your ssh agent in the output from there since I added the verbose flag

I've tried your solution, but I am hitting the following error:

Status: Downloaded newer image for rustembedded/cross:x86_64-unknown-linux-gnu-0.2.1
    Updating git repository `https://github.com/saskenuba/cargo-i18n`
     Running `git fetch --force --update-head-ok 'saskenuba/cargo-i18n' '+HEAD:refs/remotes/origin/HEAD'`
    Updating git repository `https://github.com/graphql-rust/juniper`
     Running `git fetch --tags --force --update-head-ok 'graphql-rust/juniper' '+refs/heads/*:refs/remotes/origin/*' '+HEAD:refs/remotes/origin/HEAD'`
    Updating git repository `ssh://git@github.com/saskenuba/steam-inventory-parser.git`
     Running `git fetch --force --update-head-ok 'ssh://git@github.com/saskenuba/steam-inventory-parser.git' '+HEAD:refs/remotes/origin/HEAD'`
error: failed to get `steam-inventory-parser` as a dependency of package `mercadoskin_server v0.2.1-alpha (/project)`

Caused by:
  failed to load source for dependency `steam-inventory-parser`

Caused by:
  Unable to update ssh://git@github.com/saskenuba/steam-inventory-parser.git#9e581bc1

Caused by:
  failed to clone into: /cargo/git/db/steam-inventory-parser-3c7619ad73098109

Caused by:
  process didn't exit successfully: `git fetch --force --update-head-ok 'ssh://git@github.com/saskenuba/steam-inventory-parser.git' '+HEAD:refs/remotes/origin/HEAD'` (exit status: 128)
  --- stderr
  error: cannot run ssh: No such file or directory
  fatal: unable to fork
Error: The operation was canceled.

On Cross.toml

[build.env]
passthrough = [
    "SSH_AUTH_SOCK",
    "SSH_AGENT_PID",
    "CARGO_NET_GIT_FETCH_WITH_CLI",
]

Without CARGO_NET_GIT_FETCH_WITH_CLI env, it doesn't find the repo.

The workflow.yml step:

- name: Build release binaries
        run: ${{ env.CARGO }} build --verbose --release ${{ env.TARGET_FLAGS }} --target-dir ${{ env.TARGET_DIR }}
        env:
          DOCKER_OPTS: "-v ${{ env.SSH_AUTH_SOCK }}:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent"

Now I don't really know what to do. I checked the docker images and they all have dropbear.
The seems to be related to cross indeed, since it compiles and fetches the private dependencies normally with cargo.

@Alexhuszagh
Copy link
Contributor

Alexhuszagh commented May 27, 2022

On Cross.toml

[build.env]
passthrough = [
    "SSH_AUTH_SOCK",
    "SSH_AGENT_PID",
    "CARGO_NET_GIT_FETCH_WITH_CLI",
]

I believe this is your issue, since SSH_AUTH_SOCK isn't mounted in the same place on the host and the container. This is why the above options use --volume $SSH_AUTH_SOCK:/ssh-agent --env SSH_AUTH_SOCK=/ssh-agent, which changes the value of SSH_AUTH_SOCK in the container to the proper mounted location.

@Alexhuszagh
Copy link
Contributor

Alexhuszagh commented May 27, 2022

So I've created a sample repository and commit to provide this feature. I have a private dependency private_lib (obviously, you won't be able to access this) and a binary that depends on this. The variable name maybe should be renamed, and obviously this needs to be tested on more hosts. Since cargo itself doesn't store git credentials (to my knowledge, this may have changed recently), and SSH is often not installed on the prebuilt images, I doubt it's a good idea to provide credentials manually in the configuration file. This could accidentally expose secrets, and would likely require more work.

Attempting to build with the default cross produces:

$ cross build --target powerpc64le-unknown-linux-gnu
    Updating git repository `ssh://git@github.com/Alexhuszagh/private_lib.git`
error: failed to get `private_lib` as a dependency of package `ssh_dependency v0.1.0 (/project)`

Caused by:
  failed to load source for dependency `private_lib`

Caused by:
  Unable to update ssh://git@github.com/Alexhuszagh/private_lib.git

Caused by:
  failed to fetch into: /cargo/git/db/private_lib-6a7407a49dcd9e72

Caused by:
  failed to authenticate when downloading repository

  * attempted ssh-agent authentication, but no usernames succeeded: `git`

  if the git CLI succeeds then `net.git-fetch-with-cli` may help here
  https://doc.rust-lang.org/cargo/reference/config.html#netgit-fetch-with-cli

Caused by:
  error authenticating: no auth sock variable; class=Ssh (23)

However, using cross installed from the SSH branch allows the SSH agent to be passed to the container (and therefore to cross):

$ /path/to/cross/cross/target/debug/cross build --target powerpc64le-unknown-linux-gnu
    Updating git repository `ssh://git@github.com/Alexhuszagh/private_lib.git`
    Finished dev [unoptimized + debuginfo] target(s) in 0.87s

This works by adding a config variable ssh_agent_passthrough which can provided to build.env or [target.(...).env], or the environment variable ENV_SSH_AGENT_PASSTHROUGH. See Cross.toml in my repository for an example on use. It then mounts $SSH_AUTH_SOCK to /ssh-agent and then providing an environment variable SSH_AUTH_SOCK=/ssh-agent to the container. I haven't yet tested this on Windows or macOS (only Linux), which might be an important thing to do.

@Alexhuszagh
Copy link
Contributor

It seems like we might need to canonicalize SSH_AUTH_SOCK as others are reporting here, which means we would need to call fs::canonicalize(ssh_auth_sock). It looks like this is a pretty standard way to do this.

Unfortunately, docker provides a much better way... but only when building images, using the RUN --mount=type=ssh,id=projecta git clone ... syntax.

We might also want to mount this in /tmp as well, so say, --volume "$SSH_AUTH_SOCK":/tmp/ssh-agent --env SSH_AUTH_SOCK=/tmp/ssh-agent. I know it works with WSL but not sure about Windows more generally. I'd assume it works on macOS, but I don't have the hardware to test.

@Alexhuszagh
Copy link
Contributor

This works on WSL, but it won't work on Windows more generally since it doesn't export SSH_AUTH_SOCK, at least not with the default OpenSSH install found in C:\Windows\System32\OpenSSH. I'll try to find a workaround or working solution.

@Emilgardis
Copy link
Member

the pipe can be found with

❯ [System.IO.Directory]::EnumerateFiles('\\.\pipe\') |? {$_ -like "*openssh*" }
\\.\pipe\openssh-ssh-agent

which should always be just that. It's a windows pipe though, and i'm not sure it will carry across with the CE

@Alexhuszagh
Copy link
Contributor

This was unexpectedly fixed in #684, and without needing to forward any SSH credentials. You can test it works with the following in a crate with a private SSH dependency.

eval `ssh-agent`
ssh-add /path/to/key
cargo metadata --format-version=1 --filter-platform arm-unknown-linux-gnueabihf
# kill the SSH agent, to ensure it works
eval `ssh-agent -k`
cross build --target arm-unknown-linux-gnueabihf

No environment variable forwarding required, which should make this much more resilient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-config Area: cross-toml config enhancement
Projects
None yet
Development

No branches or pull requests

6 participants