Skip to content

Commit

Permalink
Add custom error for basic auth with HTTP
Browse files Browse the repository at this point in the history
Fixes: #1131

Ref: #1116

Check that basic auth is not used in combination with a HTTP endpoint.
  • Loading branch information
HeavyWombat committed Dec 22, 2022
1 parent be84adb commit 74fa43f
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 0 deletions.
7 changes: 7 additions & 0 deletions cmd/git/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,13 @@ func checkCredentials() (credentialType, error) {
case hasUsername && hasPassword && isHTTPSURL:
return typeUsernamePassword, nil

case hasUsername && hasPassword && !isHTTPSURL:
return typeUndef, &ExitError{
Code: 110,
Message: shpgit.AuthUnexpectedHTTP.ToMessage(),
Reason: shpgit.AuthUnexpectedHTTP,
}

case hasUsername && !hasPassword || !hasUsername && hasPassword:
return typeUndef, &ExitError{
Code: 110,
Expand Down
62 changes: 62 additions & 0 deletions cmd/git/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package main_test

import (
"context"
"fmt"
"io"
"log"
"net/http"
Expand All @@ -15,11 +16,54 @@ import (

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/types"

. "github.com/shipwright-io/build/cmd/git"
shpgit "github.com/shipwright-io/build/pkg/git"
)

type errorClassMatcher struct{ expected shpgit.ErrorClass }

func FailWith(expected shpgit.ErrorClass) types.GomegaMatcher {
return &errorClassMatcher{expected: expected}
}

func (m *errorClassMatcher) Match(actual interface{}) (success bool, err error) {
switch obj := actual.(type) {
case *ExitError:
return obj.Reason == m.expected, nil

case shpgit.ErrorClass:
return obj == m.expected, nil

default:
return false, fmt.Errorf("type mismatch: %T", actual)
}
}

func (m *errorClassMatcher) asStrings(actual interface{}) (string, string) {
switch obj := actual.(type) {
case *ExitError:
return obj.Reason.String(), m.expected.String()

case shpgit.ErrorClass:
return obj.String(), m.expected.String()

default:
return fmt.Sprintf("%v", obj), m.expected.String()
}
}

func (m *errorClassMatcher) FailureMessage(actual interface{}) string {
act, exp := m.asStrings(actual)
return fmt.Sprintf("Expected\n\t%s\nto equal\n\t%s", act, exp)
}

func (m *errorClassMatcher) NegatedFailureMessage(actual interface{}) string {
act, exp := m.asStrings(actual)
return fmt.Sprintf("Expected\n\t%s\nto not equal\n\t%s", act, exp)
}

var _ = Describe("Git Resource", func() {
var run = func(args ...string) error {
// discard log output
Expand Down Expand Up @@ -344,6 +388,24 @@ var _ = Describe("Git Resource", func() {
})
})
})

It("should fail in case basic auth credentials are used in conjunction with HTTP URI", func() {
withTempDir(func(secret string) {
withUsernamePassword(func(username, password string) {
// Mock the filesystem state of `kubernetes.io/basic-auth` type secret volume mount
file(filepath.Join(secret, "username"), 0400, []byte(username))
file(filepath.Join(secret, "password"), 0400, []byte(password))

withTempDir(func(target string) {
Expect(run(
"--url", "http://github.com/shipwright-io/sample-nodejs-private",
"--secret-path", secret,
"--target", target,
)).To(FailWith(shpgit.AuthUnexpectedHTTP))
})
})
})
})
})

Context("cloning repositories with submodules", func() {
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
Expand Down Expand Up @@ -402,6 +403,7 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
Expand Down
6 changes: 6 additions & 0 deletions pkg/git/error_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ const (
AuthUnexpectedSSH
// AuthBasicIncomplete expresses that either username or password is missing in basic auth credentials
AuthBasicIncomplete
// AuthUnexpectedHTTP expresses that basic auth username and password are used in combination with a HTTP endpoint
AuthUnexpectedHTTP
// AuthInvalidKey expresses that ssh authentication is not possible
AuthInvalidKey
// RevisionNotFound expresses that a remote branch does not exist.
Expand Down Expand Up @@ -96,6 +98,8 @@ func (class ErrorClass) String() string {
return "GitSSHAuthUnexpected"
case AuthExpectedSSH:
return "GitSSHAuthExpected"
case AuthUnexpectedHTTP:
return "AuthUnexpectedHTTP"
}

return "GitError"
Expand All @@ -120,6 +124,8 @@ func (class ErrorClass) ToMessage() string {
return "Credential/URL inconsistency: No SSH credentials provided, but URL is a SSH Git URL."
case AuthBasicIncomplete:
return "Basic Auth incomplete: Both username and password need to be configured."
case AuthUnexpectedHTTP:
return "Refusing to continue with basic authentication (username and password) over insecure HTTP connection"
}

return "Git encountered an unknown error."
Expand Down

0 comments on commit 74fa43f

Please sign in to comment.