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

Authentication failure error on pulling artifacts from private Git repository #1428

Closed
pravarag opened this issue Jun 14, 2019 · 10 comments
Closed
Labels
area/artifacts S3/GCP/OSS/Git/HDFS etc type/feature Feature request

Comments

@pravarag
Copy link

What happened:
I've been trying to pull resources from a private git repository so that to implement a build step in Argo workflow. Even upon creating respective secret in Kubernetes cluster with Github credentials(username/access token) I keep getting error like
authentication required\ngh.neting.cc/argoproj/argo/errors.Wrap\n\t/root/go/src/github.com/

  • Argo version:
$ argo version
argo: v2.2.1
  BuildDate: 2018-10-11T16:26:28Z
  GitCommit: 3b52b26190163d1f72f3aef1a39f9f291378dafb
  GitTreeState: clean
  GitTag: v2.2.1
  GoVersion: go1.10.3
  Compiler: gc
  Platform: linux/amd64

@bhavin192
Copy link

bhavin192 commented Jun 14, 2019

To investigate this further I built executor from latest master,
updated the controller to be on :latest and added some log
statements which print the username and password. Turns out that
usernameBytes and passwordBytes has trailing new line
characters (\n). So I ran bytes.TrimSpace over these two. Now I'm
getting weird error which is related to SSH.

error creating SSH agent: "SSH agent requested but SSH_AUTH_SOCK not-specified"
github.com/argoproj/argo/errors.Wrap
    /home/bhavin/work/go/src/github.com/argoproj/argo/errors/errors.go:88
github.com/argoproj/argo/errors.InternalWrapError
    /home/bhavin/work/go/src/github.com/argoproj/argo/errors/errors.go:71
github.com/argoproj/argo/workflow/artifacts/git.gitClone
    /home/bhavin/work/go/src/github.com/argoproj/argo/workflow/artifacts/git/git.go:93
github.com/argoproj/argo/workflow/artifacts/git.(*GitArtifactDriver).Load
    /home/bhavin/work/go/src/github.com/argoproj/argo/workflow/artifacts/git/git.go:46
github.com/argoproj/argo/workflow/executor.(*WorkflowExecutor).LoadArtifacts
    /home/bhavin/work/go/src/github.com/argoproj/argo/workflow/executor/executor.go:168
github.com/argoproj/argo/cmd/argoexec/commands.loadArtifacts
    /home/bhavin/work/go/src/github.com/argoproj/argo/cmd/argoexec/commands/init.go:34
github.com/argoproj/argo/cmd/argoexec/commands.NewInitCommand.func1
    /home/bhavin/work/go/src/github.com/argoproj/argo/cmd/argoexec/commands/init.go:14
github.com/argoproj/argo/vendor/github.com/spf13/cobra.(*Command).execute
    /home/bhavin/work/go/src/github.com/argoproj/argo/vendor/github.com/spf13/cobra/command.go:766
github.com/argoproj/argo/vendor/github.com/spf13/cobra.(*Command).ExecuteC
    /home/bhavin/work/go/src/github.com/argoproj/argo/vendor/github.com/spf13/cobra/command.go:852
github.com/argoproj/argo/vendor/github.com/spf13/cobra.(*Command).Execute
    /home/bhavin/work/go/src/github.com/argoproj/argo/vendor/github.com/spf13/cobra/command.go:800
main.main
    /home/bhavin/work/go/src/github.com/argoproj/argo/cmd/argoexec/main.go:17
runtime.main
    /usr/lib/golang/src/runtime/proc.go:200
runtime.goexit
    /usr/lib/golang/src/runtime/asm_amd64.s:1337

(Output is edited so that it can be viewed easily)

Workflow file

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  generateName: input-artifact-git-
spec:
  entrypoint: git-clone
  templates:
  - name: git-clone
    inputs:
      artifacts:
      - name: argo-source
        path: /src
        git:
          repo: https://github.com/some-org/private-repo.git
          revision: "develop"
          usernameSecret:
            name: github-creds
            key: username
          passwordSecret:
            name: github-creds
            key: password
          # sshPrivateKeySecret:
          #   name: github-ssh
          #   key: github_tavisca
    container:
      image: golang:1.10
      command: [sh, -c]
      args: ["git status && ls"]
      workingDir: /src

Output of workflow Pod

time="2019-06-14T06:44:25Z" level=info msg="Creating a docker executor"
time="2019-06-14T06:44:25Z" level=info msg="Executor (version: v2.4.0+96b9a40.dirty, build_date: 2019-06-14T06:38:12Z) initialized (pod: default/input-artifact-git-9g2dz) with template:\n{\"name\":\"git-clone\",\"inputs\":{\"artifacts\":[{\"name\":\"argo-source\",\"path\":\"/src\",\"git\":{\"repo\":\"https://github.com/some-org/private-repo.git\",\"revision\":\"develop\",\"usernameSecret\":{\"name\":\"github-creds\",\"key\":\"username\"},\"passwordSecret\":{\"name\":\"github-creds\",\"key\":\"password\"}}}]},\"outputs\":{},\"metadata\":{},\"container\":{\"name\":\"\",\"image\":\"golang:1.10\",\"command\":[\"sh\",\"-c\"],\"args\":[\"git status \\u0026\\u0026 ls\"],\"workingDir\":\"/src\",\"resources\":{}}}"
time="2019-06-14T06:44:25Z" level=info msg="Start loading input artifacts..."
time="2019-06-14T06:44:25Z" level=info msg="Downloading artifact: argo-source"
time="2019-06-14T06:44:25Z" level=info msg="InitDriver(): value of usernameBytes: bhavin192\n"
time="2019-06-14T06:44:25Z" level=info msg="InitDriver(): value of passwordBytes: token-value-here-is-masked\n"
time="2019-06-14T06:44:25Z" level=info msg="InitDriver(): gitDriver values: {Username:bhavin192 Password:token-value-here-is-masked SSHPrivateKey: InsecureIgnoreHostKey:false}"
time="2019-06-14T06:44:25Z" level=info msg="Load(): username: bhavin192, password: token-value-here-is-masked"
time="2019-06-14T06:44:25Z" level=info msg="Load(): BasicAuth object: http-basic-auth - bhavin192:*******"
time="2019-06-14T06:44:25Z" level=info msg="gitClone(): cloneoptions object {URL:https://github.com/some-org/private-repo.git Auth:http-basic-auth - bhavin192:******* RemoteName: ReferenceName: SingleBranch:false NoCheckout:false Depth:0 RecurseSubmodules:10 Progress:<nil> Tags:0}"
time="2019-06-14T06:44:33Z" level=error msg="executor error: error creating SSH agent: \"SSH agent requested but SSH_AUTH_SOCK not-specified\"\ngh.neting.cc/argoproj/argo/errors.Wrap\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/errors/errors.go:88\ngh.neting.cc/argoproj/argo/errors.InternalWrapError\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/errors/errors.go:71\ngh.neting.cc/argoproj/argo/workflow/artifacts/git.gitClone\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/workflow/artifacts/git/git.go:94\ngh.neting.cc/argoproj/argo/workflow/artifacts/git.(*GitArtifactDriver).Load\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/workflow/artifacts/git/git.go:47\ngh.neting.cc/argoproj/argo/workflow/executor.(*WorkflowExecutor).LoadArtifacts\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/workflow/executor/executor.go:168\ngh.neting.cc/argoproj/argo/cmd/argoexec/commands.loadArtifacts\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/cmd/argoexec/commands/init.go:34\ngh.neting.cc/argoproj/argo/cmd/argoexec/commands.NewInitCommand.func1\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/cmd/argoexec/commands/init.go:14\ngh.neting.cc/argoproj/argo/vendor/github.com/spf13/cobra.(*Command).execute\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/vendor/github.com/spf13/cobra/command.go:766\ngh.neting.cc/argoproj/argo/vendor/github.com/spf13/cobra.(*Command).ExecuteC\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/vendor/github.com/spf13/cobra/command.go:852\ngh.neting.cc/argoproj/argo/vendor/github.com/spf13/cobra.(*Command).Execute\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/vendor/github.com/spf13/cobra/command.go:800\nmain.main\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/cmd/argoexec/main.go:17\nruntime.main\n\t/usr/lib/golang/src/runtime/proc.go:200\nruntime.goexit\n\t/usr/lib/golang/src/runtime/asm_amd64.s:1337"
time="2019-06-14T06:44:33Z" level=info msg="Alloc=11212 TotalAlloc=782039 Sys=137986 NumGC=51 Goroutines=5"
time="2019-06-14T06:44:33Z" level=fatal msg="error creating SSH agent: \"SSH agent requested but SSH_AUTH_SOCK not-specified\"\ngh.neting.cc/argoproj/argo/errors.Wrap\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/errors/errors.go:88\ngh.neting.cc/argoproj/argo/errors.InternalWrapError\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/errors/errors.go:71\ngh.neting.cc/argoproj/argo/workflow/artifacts/git.gitClone\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/workflow/artifacts/git/git.go:94\ngh.neting.cc/argoproj/argo/workflow/artifacts/git.(*GitArtifactDriver).Load\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/workflow/artifacts/git/git.go:47\ngh.neting.cc/argoproj/argo/workflow/executor.(*WorkflowExecutor).LoadArtifacts\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/workflow/executor/executor.go:168\ngh.neting.cc/argoproj/argo/cmd/argoexec/commands.loadArtifacts\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/cmd/argoexec/commands/init.go:34\ngh.neting.cc/argoproj/argo/cmd/argoexec/commands.NewInitCommand.func1\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/cmd/argoexec/commands/init.go:14\ngh.neting.cc/argoproj/argo/vendor/github.com/spf13/cobra.(*Command).execute\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/vendor/github.com/spf13/cobra/command.go:766\ngh.neting.cc/argoproj/argo/vendor/github.com/spf13/cobra.(*Command).ExecuteC\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/vendor/github.com/spf13/cobra/command.go:852\ngh.neting.cc/argoproj/argo/vendor/github.com/spf13/cobra.(*Command).Execute\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/vendor/github.com/spf13/cobra/command.go:800\nmain.main\n\t/home/bhavin/work/go/src/github.com/argoproj/argo/cmd/argoexec/main.go:17\nruntime.main\n\t/usr/lib/golang/src/runtime/proc.go:200\nruntime.goexit\n\t/usr/lib/golang/src/runtime/asm_amd64.s:1337"

Link to the changes
bhavin192@231bdd9

@viaduct-bot
Copy link

viaduct-bot commented Nov 21, 2019

For any other folks who are debugging the same issue: as @bhavin192 mentioned, make sure that your remote git credentials in the kubernetes Secret are stripped of any newline (especially before base64 encoding them). Removing a newline from the base64 encoded password secret was the solution in my case.

@ntwrkguru
Copy link
Contributor

Doesn't work for me using ssh key.

$ kubectl logs input-artifact-git-bb7np --all-containers
time="2020-05-01T18:00:10Z" level=info msg="Starting Workflow Executor" version=v2.7.5+ede163e.dirty
time="2020-05-01T18:00:10Z" level=info msg="Creating a docker executor"
time="2020-05-01T18:00:10Z" level=info msg="Executor (version: v2.7.5+ede163e.dirty, build_date: 2020-04-21T01:12:08Z) initialized (pod: default/input-artifact-git-bb7np) with template:\n{\"name\":\"git-clone\",\"arguments\":{},\"inputs\":{\"artifacts\":[{\"name\":\"argo-source\",\"path\":\"/src\",\"git\":{\"repo\":\"git@repo\",\"revision\":\"master\",\"depth\":1,\"sshPrivateKeySecret\":{\"name\":\"ado-ssh-key\",\"key\":\"ssh_key\"}}}]},\"outputs\":{},\"metadata\":{},\"container\":{\"name\":\"\",\"image\":\"golang:1.10\",\"command\":[\"sh\",\"-c\"],\"args\":[\"git status \\u0026\\u0026 ls\"],\"workingDir\":\"/src\",\"resources\":{}}}"
time="2020-05-01T18:00:10Z" level=info msg="Start loading input artifacts..."
time="2020-05-01T18:00:10Z" level=info msg="Downloading artifact: argo-source"
time="2020-05-01T18:00:12Z" level=error msg="executor error: empty git-upload-pack given\ngh.neting.cc/argoproj/argo/errors.Wrap\n\t/go/src/github.com/argoproj/argo/errors/errors.go:88\ngh.neting.cc/argoproj/argo/errors.InternalWrapError\n\t/go/src/github.com/argoproj/argo/errors/errors.go:71\ngh.neting.cc/argoproj/argo/workflow/artifacts/git.gitClone\n\t/go/src/github.com/argoproj/argo/workflow/artifacts/git/git.go:96\ngh.neting.cc/argoproj/argo/workflow/artifacts/git.(*GitArtifactDriver).Load\n\t/go/src/github.com/argoproj/argo/workflow/artifacts/git/git.go:42\ngh.neting.cc/argoproj/argo/workflow/executor.(*WorkflowExecutor).LoadArtifacts\n\t/go/src/github.com/argoproj/argo/workflow/executor/executor.go:160\ngh.neting.cc/argoproj/argo/cmd/argoexec/commands.loadArtifacts\n\t/go/src/github.com/argoproj/argo/cmd/argoexec/commands/init.go:34\ngh.neting.cc/argoproj/argo/cmd/argoexec/commands.NewInitCommand.func1\n\t/go/src/github.com/argoproj/argo/cmd/argoexec/commands/init.go:14\ngh.neting.cc/spf13/cobra.(*Command).execute\n\t/go/pkg/mod/github.com/spf13/cobra@v0.0.4-0.20181021141114-fe5e611709b0/command.go:766\ngh.neting.cc/spf13/cobra.(*Command).ExecuteC\n\t/go/pkg/mod/github.com/spf13/cobra@v0.0.4-0.20181021141114-fe5e611709b0/command.go:852\ngh.neting.cc/spf13/cobra.(*Command).Execute\n\t/go/pkg/mod/github.com/spf13/cobra@v0.0.4-0.20181021141114-fe5e611709b0/command.go:800\nmain.main\n\t/go/src/github.com/argoproj/argo/cmd/argoexec/main.go:17\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:203\nruntime.goexit\n\t/usr/local/go/src/runtime/asm_amd64.s:1357"
time="2020-05-01T18:00:12Z" level=info msg="Alloc=4293 TotalAlloc=9664 Sys=70592 NumGC=3 Goroutines=4"
time="2020-05-01T18:00:12Z" level=fatal msg="empty git-upload-pack given\ngh.neting.cc/argoproj/argo/errors.Wrap\n\t/go/src/github.com/argoproj/argo/errors/errors.go:88\ngh.neting.cc/argoproj/argo/errors.InternalWrapError\n\t/go/src/github.com/argoproj/argo/errors/errors.go:71\ngh.neting.cc/argoproj/argo/workflow/artifacts/git.gitClone\n\t/go/src/github.com/argoproj/argo/workflow/artifacts/git/git.go:96\ngh.neting.cc/argoproj/argo/workflow/artifacts/git.(*GitArtifactDriver).Load\n\t/go/src/github.com/argoproj/argo/workflow/artifacts/git/git.go:42\ngh.neting.cc/argoproj/argo/workflow/executor.(*WorkflowExecutor).LoadArtifacts\n\t/go/src/github.com/argoproj/argo/workflow/executor/executor.go:160\ngh.neting.cc/argoproj/argo/cmd/argoexec/commands.loadArtifacts\n\t/go/src/github.com/argoproj/argo/cmd/argoexec/commands/init.go:34\ngh.neting.cc/argoproj/argo/cmd/argoexec/commands.NewInitCommand.func1\n\t/go/src/github.com/argoproj/argo/cmd/argoexec/commands/init.go:14\ngh.neting.cc/spf13/cobra.(*Command).execute\n\t/go/pkg/mod/github.com/spf13/cobra@v0.0.4-0.20181021141114-fe5e611709b0/command.go:766\ngh.neting.cc/spf13/cobra.(*Command).ExecuteC\n\t/go/pkg/mod/github.com/spf13/cobra@v0.0.4-0.20181021141114-fe5e611709b0/command.go:852\ngh.neting.cc/spf13/cobra.(*Command).Execute\n\t/go/pkg/mod/github.com/spf13/cobra@v0.0.4-0.20181021141114-fe5e611709b0/command.go:800\nmain.main\n\t/go/src/github.com/argoproj/argo/cmd/argoexec/main.go:17\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:203\nruntime.goexit\n\t/usr/local/go/src/runtime/asm_amd64.s:1357"
Error from server (BadRequest): container "wait" in pod "input-artifact-git-bb7np" is waiting to start: PodInitializing

and this error from the Argo CLI:

failed to load artifacts: empty git-upload-pack given

@alexec alexec added artifacts type/feature Feature request labels May 12, 2020
@alexec
Copy link
Contributor

alexec commented May 13, 2020

Someone with Git XP needs to sit down and test out all the authentication scenarios.

@ntwrkguru
Copy link
Contributor

@alexec I'm not sure I know Argo well enough to test. :-(

@ks4225
Copy link

ks4225 commented Sep 21, 2020

I haven't been able to get a private Azure Repo to work using PAT or SSH. Is this a scenario that is supported?

With PAT: message: failed to load artifacts: unexpected client error: unexpected requesting "https://dev.azure.com/<org>/<proj>/_git/<repo>/git-upload-pack" status code: 400
With SSH: message: failed to load artifacts: empty git-upload-pack given

@Siebjee
Copy link
Contributor

Siebjee commented Feb 9, 2021

@ks4225 in the particular way how Azure DevOps as made this fairly awkward i did find a way to work around this.

secret.yaml:

apiVersion: v1
kind: Secret
type: Opaque
metadata:
  namespace: argo
  name: ci-auth-keys
  labels:
    app.kubernetes.io/name: argo
data:
  GIT_AUTHKEY: <BASE64 ENCODED AUTH KEY (Azure DevOps PAT)>
  GIT_AUTHUSER: <BASE64 USER>

And within your workflow:

apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
  namespace: argo
  name: my-workflow
spec:
  serviceAccountName: argo
  entrypoint: my-entrypoint
  arguments:
    parameters:
    - name: repo
      value: dev.azure.com/org/project/_git/repository
    - name: revision
      value: my-branch
[..]
  template:
  - name: my-entrypoint
     steps:
      - - name: checkout
          template: checkout
[..]
  - name: checkout
    inputs:
      artifacts:
      - name: git-repo
        path: /src/.keep
        raw:
          data: |
            placeholder
    metadata:
      labels:
        app: argo
    container:
      image: alpine/git
      envFrom:
        - secretRef:
            name: ci-auth-keys
      command: [sh, -c]
      args:
        - |
          cd /src
          git clone \
            https://$(GIT_AUTHUSER):$(GIT_AUTHKEY)@{{workflow.parameters.repo}} \
            --branch {{workflow.parameters.revision}} repo
          (
            cd rpeo
            git rev-parse --short HEAD > /tmp/git-commit
          )
          ls -al
[..]

I hope this helps for those searching.

icecoffee531 pushed a commit to icecoffee531/argo-workflows that referenced this issue Jan 5, 2022
Signed-off-by: Michael Seiwald <michael.seiwald@smartify-it.de>
@alexec alexec added area/artifacts S3/GCP/OSS/Git/HDFS etc and removed help wanted labels Feb 7, 2022
@alexec
Copy link
Contributor

alexec commented Apr 13, 2022

I think this is fixed in :latest. Please let me know if not.

@alexec alexec closed this as completed Apr 13, 2022
@auswells
Copy link

auswells commented Apr 27, 2022

I'm seeing authentication errors when using the revision option:

        artifacts:
          - name: git-clone
            path: /terraform-gcp
            git:
              repo: "{{workflow.parameters.git-repository}}"
              revision: "{{workflow.parameters.git-revision}}"
              usernameSecret:
                name: '{{workflow.parameters.git-auth-secretname}}'
                key: username
              passwordSecret:
                name: '{{workflow.parameters.git-auth-secretname}}'
                key: password
time="2022-04-27T14:24:08.390Z" level=info msg="Load artifact" artifactName=git-clone duration=644.9982ms error="failed to fatch refs: authentication required" key=
time="2022-04-27T14:24:08.390Z" level=error msg="executor error: artifact git-clone failed to load: failed to fatch refs: authentication required"
time="2022-04-27T14:24:08.390Z" level=info msg="Alloc=8189 TotalAlloc=13543 Sys=19154 NumGC=4 Goroutines=4"
time="2022-04-27T14:24:08.390Z" level=fatal msg="artifact git-clone failed to load: failed to fatch refs: authentication required"

However, if I update it to use singleBranch + branch instead of revision it succeeds

        artifacts:
          - name: git-clone
            path: /terraform-gcp
            git:
              repo: "{{workflow.parameters.git-repository}}"
              singleBranch: true
              branch: "{{workflow.parameters.git-branch}}"
              usernameSecret:
                name: '{{workflow.parameters.git-auth-secretname}}'
                key: username
              passwordSecret:
                name: '{{workflow.parameters.git-auth-secretname}}'
                key: password
time="2022-04-27T14:50:54.003Z" level=info msg="Downloading artifact: git-clone"
time="2022-04-27T14:50:54.456Z" level=info msg="Load artifact" artifactName=git-clone duration=452.7255ms error="<nil>" key=
time="2022-04-27T14:50:54.456Z" level=info msg="Detecting if /argo/inputs/artifacts/git-clone.tmp is a tarball"
time="2022-04-27T14:50:54.456Z" level=info msg="Successfully download file: /argo/inputs/artifacts/git-clone"

This is using :latest with a private github repository using username + PAT

@FeiYing9
Copy link

make sure that your remote git credentials in the kubernetes Secret are stripped of any newline (especially before base64 encoding them)

It happens when use base64 command in linux(mine is Centos-7), all the base64 value is end with \n

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/artifacts S3/GCP/OSS/Git/HDFS etc type/feature Feature request
Projects
None yet
Development

No branches or pull requests

9 participants