2

I'm following the Clone a git repository with Tekton tutorial and try to clone a git repo using ssh.

The pipeline works fine, using HTTPS but for ssh it's complaining that the ssh configuration is missing. From the logs I can see that it finds the secret with the ssh files. But some lines later it complains that there' no ssh configuration.

Any ideas?

My pipeline.yaml (unchanged from the tutorial)

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: clone-read
spec:
  description: | 
    This pipeline clones a git repo, then echoes the README file to the stout.
  params:
  - name: repo-url
    type: string
    description: The git repo URL to clone from.
  workspaces:
  - name: shared-data
    description: | 
      This workspace contains the cloned repo files, so they can be read by the
      next task.
  - name: git-credentials
    description: My ssh credentials
  tasks:
  - name: fetch-source
    taskRef:
      name: git-clone
    workspaces:
    - name: output
      workspace: shared-data
    - name: ssh-directory
      workspace: git-credentials
    params:
    - name: url
      value: $(params.repo-url)
    - name: verbose
      value: true
  - name: show-readme
    runAfter: ["fetch-source"]
    taskRef:
      name: show-readme
    workspaces:
    - name: source
      workspace: shared-data

My pipelinerun.yaml (unchanged from the tutorial):

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  generateName: clone-read-run-
spec:
  pipelineRef:
    name: clone-read
  podTemplate:
    securityContext:
      fsGroup: 65532
  workspaces:
  - name: shared-data
    volumeClaimTemplate:
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
  - name: git-credentials
    secret:
      secretName: git-credentials
  params:
  - name: repo-url
    value: git@github.com:tektoncd/website.git

My sevret.yaml:

apiVersion: v1
kind: Secret
metadata:
  name: git-credentials
data:
  id_rsa: LS0tLS...
  id_rsa.pub: c3NoLXJ...
  known_hosts: Z2l0aH...

Logoutput:

 $ tkn pipelinerun logs clone-read-run-72zlj -f
[fetch-source : clone] + '[' false '=' true ]
[fetch-source : clone] + '[' true '=' true ]
[fetch-source : clone] + cp -R /workspace/ssh-directory /home/git/.ssh
[fetch-source : clone] + chmod 700 /home/git/.ssh
[fetch-source : clone] + chmod -R 400 /home/git/.ssh/id_rsa /home/git/.ssh/id_rsa.pub /home/git/.ssh/known_hosts
[fetch-source : clone] + '[' false '=' true ]
[fetch-source : clone] + CHECKOUT_DIR=/workspace/output/
[fetch-source : clone] + '[' true '=' true ]
[fetch-source : clone] + cleandir
[fetch-source : clone] + '[' -d /workspace/output/ ]
[fetch-source : clone] + rm -rf '/workspace/output//*'
[fetch-source : clone] + rm -rf '/workspace/output//.[!.]*'
[fetch-source : clone] + rm -rf '/workspace/output//..?*'
[fetch-source : clone] + test -z
[fetch-source : clone] + test -z
[fetch-source : clone] + test -z
[fetch-source : clone] + git config --global --add safe.directory /workspace/output
[fetch-source : clone] + /ko-app/git-init '-url=git@github.com:tektoncd/website.git' '-revision=' '-refspec=' '-path=/workspace/output/' '-sslVerify=true' '-submodules=true' '-depth=1' '-sparseCheckoutDirectories='
[fetch-source : clone] {"level":"warn","ts":1671382236.5119827,"caller":"git/git.go:271","msg":"URL(\"git@github.com:tektoncd/website.git\") appears to need SSH authentication but no SSH credentials have been provided"}
[fetch-source : clone] {"level":"error","ts":1671382237.3406594,"caller":"git/git.go:53","msg":"Error running git [fetch --recurse-submodules=yes --depth=1 origin --update-head-ok --force ]: exit status 128\ngit@github.com: Permission denied (publickey).\r\nfatal: Could not read from remote repository.\n\nPlease make sure you have the correct access rights\nand the repository exists.\n","stacktrace":"github.com/tektoncd/pipeline/pkg/git.run\n\tgithub.com/tektoncd/pipeline/pkg/git/git.go:53\ngithub.com/tektoncd/pipeline/pkg/git.Fetch\n\tgithub.com/tektoncd/pipeline/pkg/git/git.go:156\nmain.main\n\tgithub.com/tektoncd/pipeline/cmd/git-init/main.go:53\nruntime.main\n\truntime/proc.go:250"}
[fetch-source : clone] {"level":"fatal","ts":1671382237.340791,"caller":"git-init/main.go:54","msg":"Error fetching git repository: failed to fetch []: exit status 128","stacktrace":"main.main\n\tgithub.com/tektoncd/pipeline/cmd/git-init/main.go:54\nruntime.main\n\truntime/proc.go:250"}
tukan
  • 17,050
  • 1
  • 20
  • 48
BetaRide
  • 16,207
  • 29
  • 99
  • 177
  • The `secret.yaml` you show in your question matches the sample one in the page, but it needs to *not* match the sample. Did you generate actual keys and install them on GitHub and then put them in your `secret.yaml`? – torek Dec 18 '22 at 17:27
  • No, it does not match the sample one. And yes, I generated keys on GitHub. I can to a SSH clone one the command line just fine. – BetaRide Dec 18 '22 at 17:47
  • OK, the only other suggestion I have at this point is to use Git's `core.sshCommand` (or environment SSH_COMMAND variable) to run `ssh -v` (insert as many extra `-v`s as you like) so that you can trace the ssh command that Git runs, to see why it's not happy with the ssh keys. – torek Dec 19 '22 at 05:05
  • How can I do that? There's no such option for the git-clone task. – BetaRide Dec 19 '22 at 16:38
  • No idea, I've never used tekton. There must be some way to smuggle options in though, for debug purposes. – torek Dec 19 '22 at 22:37
  • @BetaRide Have you got any luck on solving this? – Sourabh Banka Mar 07 '23 at 07:27

2 Answers2

1

i have also face the same issue while testing the git-clone task and taskRun (the following files can be easily adapted with pipeline and pipelineRun).

The first problem is that the git-init docker image used by the git-clone task uses some hard-coded paths. When changing the git-init docker image tag, there are some internal changes, like the user and the home folder (on newer image v0.40, the user is git, located at /home/git, on earlier image, nonroot at /home/nonroot).

As the git-clone-task is public and doesn't have a huge script, i have opted to edit it and remove unnecessary code.

apiVersion: v1
kind: Secret
metadata:
  name: github-repo-credentials-secret
data:
  id_rsa: LS0tLS...
  known_hosts: Z2l0aH...

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
 name: github-repo-clone-task
spec:
 workspaces:
   - name: clonedDirectoryFolder
     description: Github cloned repo shared folder
   - name: githubSshFolder
     description: GitHub SSH credentials shared folder
 params:
   - name: repoUrl
     description: Repository URL to clone from.
     type: string
   - name: revision
     description: Branch, tag .... etc
     type: string
     default: "main"
   - name: deleteExisting
     description: Clean out the contents of the destination directory if it already exists before cloning.
     type: string
     default: "true"
   - name: userHome
     description: Absolute path to the user's home directory.
     type: string
     default: "/home/git"
   - name: gitInitImage
     description: The image providing the git-init binary that this Task runs.
     type: string
     default: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.25.0"
 steps:
   - name: clone-git-repo-ssh
     image: "$(params.gitInitImage)"
     #image: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.21.0"
     env:
       - name: PARAM_URL
         value: $(params.repoUrl)
       - name: PARAM_REVISION
         value: $(params.revision)
       - name: WORKSPACE_OUTPUT_PATH
         value: $(workspaces.clonedDirectoryFolder.path)
       - name: PARAM_DELETE_EXISTING
         value: $(params.deleteExisting)
       - name: WORKSPACE_SSH_DIRECTORY_BOUND
         value: $(workspaces.githubSshFolder.bound)
       - name: WORKSPACE_SSH_DIRECTORY_PATH
         value: $(workspaces.githubSshFolder.path)
       - name: PARAM_USER_HOME
         value: $(params.userHome)
       - name: GIT_SSH_COMMAND
       #  value: "ssh -i $(params.userHome)/.ssh/id_rsa -F /dev/null -o 'IdentitiesOnly yes'"  # both values work
         value: "ssh -i $(params.userHome)/.ssh/id_rsa"
     script: |
       #!/usr/bin/env sh
       set -eu

       set -x
       
       if [ "${WORKSPACE_SSH_DIRECTORY_BOUND}" = "true" ] ; then

          cp -R "${WORKSPACE_SSH_DIRECTORY_PATH}" "${PARAM_USER_HOME}"/.ssh

          chmod 700 "${PARAM_USER_HOME}"/.ssh

          chmod -R 400 "${PARAM_USER_HOME}"/.ssh/*
          
          chmod 600 "${PARAM_USER_HOME}"/.ssh/config         
                   
        fi
        
       # ln -s "${PARAM_USER_HOME}"/.ssh /tekton/creds  # uncomment this to get rid of this warming: appears to need SSH authentication but no SSH credentials have been provided
       
       CHECKOUT_DIR="${WORKSPACE_OUTPUT_PATH}"

       cleandir() {

          # Delete any existing contents of the repo directory if it exists.

          # We don't just "rm -rf ${CHECKOUT_DIR}" because ${CHECKOUT_DIR} might be "/"

          # or the root of a mounted volume.

          if [ -d "${CHECKOUT_DIR}" ] ; then

            # Delete non-hidden files and directories

            rm -rf "${CHECKOUT_DIR:?}"/*

            # Delete files and directories starting with . but excluding ..

            rm -rf "${CHECKOUT_DIR}"/.[!.]*

            # Delete files and directories starting with .. plus any other character

            rm -rf "${CHECKOUT_DIR}"/..?*

          fi

        }


        if [ "${PARAM_DELETE_EXISTING}" = "true" ] ; then

          cleandir || true

        fi
        
       git config --global --add safe.directory "${WORKSPACE_OUTPUT_PATH}"
       
       # uncomment the two lines below if the GIT_SSH_COMMAND env variable is not set
       
       #eval "$(ssh-agent -s)"
        
       #ssh-add "${PARAM_USER_HOME}"/.ssh/id_rsa
       
       /ko-app/git-init \
         -url="${PARAM_URL}" \
         -revision="${PARAM_REVISION}" \
         -path="${CHECKOUT_DIR}"
       cd "${CHECKOUT_DIR}"
       EXIT_CODE="$?"
       if [ "${EXIT_CODE}" != 0 ] ; then
         exit "${EXIT_CODE}"
       fi
       # Verify clone is success by reading readme file.
       cat ${CHECKOUT_DIR}/README.md

apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  name: github-repo-clone-task-run
spec:
  workspaces:
   - name: clonedDirectoryFolder
     volumeClaimTemplate:
       spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
   - name: githubSshFolder
     secret:
       secretName: github-repo-credentials-secret
  params:
    - name: repoUrl
      value: "git@github.com:tektoncd/website.git"  #git ssh clone Url
    - name: revision
      value: "main"
    - name: userHome
      value: "/home/git"
      #value: "/root"  # use this when the security context is set root
      #value: "/home/nonroot"  # use this value for ealier git-init:v0.29.0
    - name: gitInitImage
      #value: "alpine/git:latest"
      value: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.40.2"
      #value: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.29.0"  # if you use this image, set the userHome to /home/nonroot
  taskRef:
    name: github-repo-clone-task
  # uncomment this part to run the task as root
  
  #podTemplate:
  #  securityContext:
  #    runAsNonRoot: false
  #    runAsUser: 0

The GIT_SSH_COMMAND environment variable is used to force git to use the provided private key.

S_Passing
  • 21
  • 2
0

I just complete my answer in case you want to use the alpine git docker image. In this case there are few modifications on the previous Yaml Files.

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
 name: github-repo-clone-task-git-alpine
spec:
 workspaces:
   - name: clonedDirectoryFolder
     description: Github cloned repo shared folder
   - name: githubSshFolder
     description: GitHub SSH credentials shared folder
 params:
   - name: repoUrl
     description: Repository URL to clone from.
     type: string
   - name: revision
     description: Branch, tag .... etc
     type: string
     default: "main"
   - name: deleteExisting
     description: Clean out the contents of the destination directory if it already exists before cloning.
     type: string
     default: "true"
   - name: userHome
     description: Absolute path to the user's home directory.
     type: string
     default: "/root"
   - name: gitInitImage
     description: The image providing the git-init binary that this Task runs.
     type: string
     default: "alpine/git:latest"
 steps:
   - name: clone-git-repo-ssh
     image: "$(params.gitInitImage)"
     env:
       - name: PARAM_URL
         value: $(params.repoUrl)
       - name: PARAM_REVISION
         value: $(params.revision)
       - name: WORKSPACE_OUTPUT_PATH
         value: $(workspaces.clonedDirectoryFolder.path)
       - name: PARAM_DELETE_EXISTING
         value: $(params.deleteExisting)
       - name: WORKSPACE_SSH_DIRECTORY_BOUND
         value: $(workspaces.githubSshFolder.bound)
       - name: WORKSPACE_SSH_DIRECTORY_PATH
         value: $(workspaces.githubSshFolder.path)
       - name: PARAM_USER_HOME
         value: $(params.userHome)
       - name: GIT_SSH_COMMAND
       #  value: "ssh -i $(params.userHome)/.ssh/id_rsa -F /dev/null -o 'IdentitiesOnly yes'"  # both values work
         value: "ssh -i $(params.userHome)/.ssh/id_rsa"
     script: |
       #!/usr/bin/env sh
       set -eu

       set -x
       
       if [ "${WORKSPACE_SSH_DIRECTORY_BOUND}" = "true" ] ; then

          cp -R "${WORKSPACE_SSH_DIRECTORY_PATH}" "${PARAM_USER_HOME}"/.ssh

          chmod 700 "${PARAM_USER_HOME}"/.ssh

          chmod -R 400 "${PARAM_USER_HOME}"/.ssh/*
          
          chmod 600 "${PARAM_USER_HOME}"/.ssh/config         
                   
        fi
       
       CHECKOUT_DIR="${WORKSPACE_OUTPUT_PATH}"

       cleandir() {

          # Delete any existing contents of the repo directory if it exists.

          # We don't just "rm -rf ${CHECKOUT_DIR}" because ${CHECKOUT_DIR} might be "/"

          # or the root of a mounted volume.

          if [ -d "${CHECKOUT_DIR}" ] ; then

            # Delete non-hidden files and directories

            rm -rf "${CHECKOUT_DIR:?}"/*

            # Delete files and directories starting with . but excluding ..

            rm -rf "${CHECKOUT_DIR}"/.[!.]*

            # Delete files and directories starting with .. plus any other character

            rm -rf "${CHECKOUT_DIR}"/..?*

          fi

        }


        if [ "${PARAM_DELETE_EXISTING}" = "true" ] ; then

          cleandir || true

        fi
       
       # uncomment the two lines below if the GIT_SSH_COMMAND env variable is not set
       
       #eval "$(ssh-agent -s)"
        
       #ssh-add "${PARAM_USER_HOME}"/.ssh/id_rsa
       
       git clone "${PARAM_URL}" --branch="${PARAM_REVISION}" "${CHECKOUT_DIR}"
       cd "${CHECKOUT_DIR}"
       EXIT_CODE="$?"
       if [ "${EXIT_CODE}" != 0 ] ; then
         exit "${EXIT_CODE}"
       fi
       # Verify clone is success by reading readme file.
       cat ${CHECKOUT_DIR}/README.md

apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  name: github-repo-clone-task-run-git-alpine
spec:
  workspaces:
   - name: clonedDirectoryFolder
     volumeClaimTemplate:
       spec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 1Gi
   - name: githubSshFolder
     secret:
       secretName: github-repo-credentials-secret
  params:
    - name: repoUrl
      value: "git@github.com:tektoncd/website.git"  #git ssh clone Url
    - name: revision
      value: "main"
    - name: userHome
      value: "/root"
    - name: gitInitImage
      value: "alpine/git:latest"
  taskRef:
    name: github-repo-clone-task-git-alpine

Note that this image uses the root user, there is another image with a non root user available : gcr.io/tekton-releases/dogfooding/alpine-git-nonroot:latest, to use this image in these Yaml files, just the gitInitImage parameter value in TaskRun and also set the userHome to /home/nonroot .

Additional information can found at this github page: https://github.com/tektoncd/pipeline/blob/main/examples/v1beta1/taskruns/authenticating-git-commands.yaml

S_Passing
  • 21
  • 2