[Windows Shared Runners] Cannot add an SSH private deploy key to SSH Agent - how to proceed?

Hi,

I’m revisiting a previous issue I opened, that yielded no response, so I try again with more information.

I’m having a significant amount of trouble adding an SSH Key to ssh-agent on GitLab’s Windows Shared Runner, to subsequently allow me to access private repositories on GitLab (which I use in Node/React/React Native projects via NPM).

The actual SSH private key is set using a “file” environment variable, but directly adding this via ssh-add states that the permissions are too open, so I researched methods to try rectify this - none of which work.

Instead, I echo the key into a manually created file. Only now, I receive the “agent refused operation” when adding the key.

To add to the fire, the ssh agent even refuses keys generated inside the VM for testing purposes.

The SSH keys are all ed25519 type.

Here is my gitlab-ci.yml script - what am I missing?

stages:
  - test


test_windows:
    stage: test
    tags:
      - shared-windows
      - windows
      - windows-1809
    variables:
      CI_ARTIFACTS_PATH_TMP: '"$CI_PROJECT_DIR"'
    script:
      # ------------------------------------------------------------------------
      # Print the contents of some key directories
      # ------------------------------------------------------------------------
      - ls -l "C:\"
      - ls -l "C:\Users\"
      - ls -l "C:\Git\"
      - ls -l "C:\Git\usr\bin\"
      - ls -l "C:\Program Files\"
      - ls -l "C:\Windows\System32\OpenSSH\"


      # ------------------------------------------------------------------------
      # Install dependencies/helpers
      # ------------------------------------------------------------------------
      # No steps required

      # ------------------------------------------------------------------------
      # Configure SSH (OpenSSH variant)
      # ------------------------------------------------------------------------
      - Get-Command ssh-keygen
      - Get-Command ssh-add
      - Get-Command ssh
      - Set-Service -Name ssh-agent -StartupType Manual
      - Start-Service ssh-agent
      - Get-Service ssh-agent | select * # Check if it has started


      # ------------------------------------------------------------------------
      # Copy the DK_FILE ssh private key env variable into the id_ed25519 file (create if nonexistent)
      # ------------------------------------------------------------------------
      - $dk_file_txt = Get-Content $DK_FILE -Raw
      - echo $dk_file_txt
      - New-Item -ItemType "file" -Force -Path C:\Users\$env:UserName\.ssh\id_ed25519
      - echo "$dk_file_txt" > C:\Users\$env:UserName\.ssh\id_ed25519
      - (Get-Content C:\Users\$env:UserName\.ssh\id_ed25519 -Raw).Replace("`r`n","`n") | Set-Content C:\Users\$env:UserName\.ssh\id_ed25519 -Force


      # ------------------------------------------------------------------------
      # Set Key Permissions
      # ------------------------------------------------------------------------
      # :: Remove Inheritance ::
      # - cmd /c icacls "C:\Users\gitlab_runner\.ssh" /c /t /inheritance:d
      - cmd /c icacls C:\Users\$env:UserName\.ssh\id_ed25519 /c /t /inheritance:d
      # :: Set Ownership to Owner ::
      # - cmd /c icacls "C:\Users\gitlab_runner\.ssh" /c /t /grant %username%:F
      - cmd /c icacls C:\Users\$env:UserName\.ssh\id_ed25519 /c /t /grant %username%:F
      # :: Remove All Users, except for Owner ::
      # - cmd /c icacls "C:\Users\gitlab_runner\.ssh"  /c /t /remove Administrator BUILTIN\Administrators BUILTIN Everyone System Users
      - cmd /c icacls C:\Users\$env:UserName\.ssh\id_ed25519  /c /t /remove Administrator BUILTIN\Administrators BUILTIN Everyone System Users
      # :: Verify ::
      # - cmd /c icacls "C:\Users\gitlab_runner\.ssh"
      - cmd /c icacls C:\Users\$env:UserName\.ssh\id_ed25519

      # ------------------------------------------------------------------------
      # Add the SSH key via ssh-add
      # ------------------------------------------------------------------------
      - ssh-add C:\Users\$env:UserName\.ssh\id_ed25519

      # ------------------------------------------------------------------------
      # Test if it worked
      # ------------------------------------------------------------------------
      # - ssh -Tvvv git@gitlab.com
      # - git config --global core.sshCommand "'C:\Windows\System32\OpenSSH\ssh.exe'"
      # - npm install
      # - npm run package-win

      # ------------------------------------------------------------------------
      # Upload artifacts (if any)
      # ------------------------------------------------------------------------
      # - gitlab-runner artifacts-uploader --verbose --id "${CI_JOB_ID}" --token "${CI_JOB_TOKEN}" --url "${CI_SERVER_URL}" --artifact-format zip --artifact-type archive --path $CI_ARTIFACTS_PATH_TMP || exit 1

      # ------------------------------------------------------------------------
      # Finish...
      # ------------------------------------------------------------------------
      - exit 0
    artifacts:
      paths:
        - .ssh
      exclude:
        - node_modules


Note that I also tried a variant which used poshgit and set different aliases for ssh commands pointing to this installation.

When using the poshgit variant, the ssh private key was successfully added. However, when actually trying to run an ssh session I receive a “host key check failed” error. This then kills my npm install (using private repos as dependencies).

stages:
  - test


test_windows:
    stage: test
    tags:
      - shared-windows
      - windows
      - windows-1809
    variables:
      CI_ARTIFACTS_PATH_TMP: '"$CI_PROJECT_DIR"'
    script:
      # ------------------------------------------------------------------------
      # Print the contents of some key directories
      # ------------------------------------------------------------------------
      - ls -l "C:\"
      - ls -l "C:\Users\"
      - ls -l "C:\Git\"
      - ls -l "C:\Git\usr\bin\"
      - ls -l "C:\Program Files\"
      - ls -l "C:\Windows\System32\OpenSSH\"


      # ------------------------------------------------------------------------
      # Install dependencies/helpers
      # ------------------------------------------------------------------------


      # ------------------------------------------------------------------------
      # Configure SSH (Poshgit variant)
      # ------------------------------------------------------------------------
      - choco install poshgit -y --limit-output --no-progress
      - refreshenv
      - Import-Module 'C:\tools\poshgit\dahlbyk-posh-git-9bda399\src\posh-git.psd1'
      - refreshenv
      - $env:PATH+=";C:\Git\usr\bin"
      - Set-Alias ssh-keygen "$env:ProgramFiles\git\usr\bin\ssh-keygen.exe" # Provided by poshgit
      - Set-Alias ssh-agent "C:\Git\usr\bin\ssh-agent.exe"
      - Set-Alias ssh-add "C:\Git\usr\bin\ssh-add.exe"
      - Set-Alias ssh "C:\Git\usr\bin\ssh.exe"
      - Start-SshAgent -Quiet
      - echo "$env"
      - gci env:SSH_AUTH_SOCK
      - mkdir .ssh
      - Get-WindowsCapability -Online | ? Name -like 'OpenSSH*'
      # - ssh-keygen -f "$CI_PROJECT_DIR\.ssh\test_rsa" -t rsa -N '""'
      # - ssh-keygen -f "$CI_PROJECT_DIR\.ssh\test_ed25519" -t ed25519 -N '""'
      - New-Item -ItemType "directory" -Force -Path C:\Users\$env:UserName\.ssh\
      - ssh-keygen -a 100 -t ed25519 -f "C:\Users\$env:UserName\.ssh\id_ed25519" -C "MY_SSH_KEY" -N '""'
      - Remove-Item -Path "C:\Users\$env:UserName\.ssh\id_ed25519.pub"
      # - Set-Content -Path "C:\Users\$env:UserName\.ssh\id_ed25519" -Value $dk_file_txt -Force

      - ssh-add "C:\Users\$env:UserName\.ssh\id_ed25519"


      # ------------------------------------------------------------------------
      # Test if it worked
      # ------------------------------------------------------------------------
      # - ssh -o StrictHostKeyChecking=no git@gitlab.com uptime
      - ls -l "$env:ProgramFiles\"
      - ls -l "$env:ProgramFiles\git\"
      - ls -l "$env:ProgramFiles\git\bin"
      # - Set-Alias -Name git -Value "$env:ProgramFiles\git\bin\git.exe"
      # - npm config set git "$env:ProgramFiles\git\bin\git.exe"
      # - git config --global core.sshCommand "$env:ProgramFiles\git\usr\bin\ssh.exe"
      - ssh -Tvvv git@gitlab.com
      # - npm install # Fails with error code 128 (ssh failure)
      # - npm run package-win

      # ------------------------------------------------------------------------
      # Upload artifacts (if any)
      # ------------------------------------------------------------------------
      - gitlab-runner artifacts-uploader --verbose --id "${CI_JOB_ID}" --token "${CI_JOB_TOKEN}" --url "${CI_SERVER_URL}" --artifact-format zip --artifact-type archive --path $CI_ARTIFACTS_PATH_TMP || exit 1

      # ------------------------------------------------------------------------
      # Finish...
      # ------------------------------------------------------------------------
      - exit 0
    artifacts:
      paths:
        - .ssh
      exclude:
        - node_modules

Ideally, I’d prefer to work with openssh and not have to add external dependencies. I’d appreciate any and all help as I’ve lost so much time on this matter.

2 Likes

I’m interested as well. I wish to update a submodule hosted elsewhere during a Windows build.