Skip to content

Commit

Permalink
Validate credentials when performing a login (acorn-io#824)
Browse files Browse the repository at this point in the history
Signed-off-by: tylerslaton <mtslaton1@gmail.com>
  • Loading branch information
tylerslaton committed Nov 3, 2022
1 parent e6d97a9 commit 7e27f1c
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 19 deletions.
63 changes: 44 additions & 19 deletions integration/client/credentials/credentials_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ func TestCredentialCreate(t *testing.T) {
helper.StartController(t)
restConfig := helper.StartAPI(t)

reg, close := helper.StartRegistry(t)
reg1, close1 := helper.StartRegistry(t)
defer close()
defer close1()

ctx := helper.GetCTX(t)
kclient := helper.MustReturn(kclient.Default)
ns := helper.TempNamespace(t, kclient)
Expand All @@ -23,27 +28,27 @@ func TestCredentialCreate(t *testing.T) {
t.Fatal(err)
}

cred, err := c.CredentialCreate(ctx, "example.com:443", "user", "pass")
cred, err := c.CredentialCreate(ctx, reg, "user", "pass")
if err != nil {
t.Fatal(err)
}

assert.Equal(t, "example.com:443", cred.Name)
assert.Equal(t, "example.com:443", cred.ServerAddress)
assert.Equal(t, reg, cred.Name)
assert.Equal(t, reg, cred.ServerAddress)
assert.Equal(t, "user", cred.Username)
assert.Nil(t, cred.Password)

cred1, err := c.CredentialCreate(ctx, "two.example.com:443", "user2", "pass2")
cred1, err := c.CredentialCreate(ctx, reg1, "user2", "pass2")
if err != nil {
t.Fatal(err)
}

assert.Equal(t, "two.example.com:443", cred1.Name)
assert.Equal(t, "two.example.com:443", cred1.ServerAddress)
assert.Equal(t, reg1, cred1.Name)
assert.Equal(t, reg1, cred1.ServerAddress)
assert.Equal(t, "user2", cred1.Username)
assert.Nil(t, cred1.Password)

cred1New, err := c.CredentialGet(ctx, "two.example.com:443")
cred1New, err := c.CredentialGet(ctx, reg1)
if err != nil {
t.Fatal(err)
}
Expand All @@ -55,6 +60,11 @@ func TestCredentialList(t *testing.T) {
helper.StartController(t)
restConfig := helper.StartAPI(t)

reg, close := helper.StartRegistry(t)
reg1, close1 := helper.StartRegistry(t)
defer close()
defer close1()

ctx := helper.GetCTX(t)
kclient := helper.MustReturn(kclient.Default)
ns := helper.TempNamespace(t, kclient)
Expand All @@ -64,12 +74,12 @@ func TestCredentialList(t *testing.T) {
t.Fatal(err)
}

cred1, err := c.CredentialCreate(ctx, "example.com:443", "user", "pass")
cred1, err := c.CredentialCreate(ctx, reg, "user", "pass")
if err != nil {
t.Fatal(err)
}

cred2, err := c.CredentialCreate(ctx, "two.example.com:443", "user2", "pass2")
cred2, err := c.CredentialCreate(ctx, reg1, "user2", "pass2")
if err != nil {
t.Fatal(err)
}
Expand All @@ -91,6 +101,11 @@ func TestCredentialGet(t *testing.T) {
helper.StartController(t)
restConfig := helper.StartAPI(t)

reg, close := helper.StartRegistry(t)
reg1, close1 := helper.StartRegistry(t)
defer close()
defer close1()

ctx := helper.GetCTX(t)
kclient := helper.MustReturn(kclient.Default)
ns := helper.TempNamespace(t, kclient)
Expand All @@ -100,17 +115,17 @@ func TestCredentialGet(t *testing.T) {
t.Fatal(err)
}

_, err = c.CredentialCreate(ctx, "example.com:443", "user", "pass")
_, err = c.CredentialCreate(ctx, reg, "user", "pass")
if err != nil {
t.Fatal(err)
}

cred1, err := c.CredentialCreate(ctx, "two.example.com:443", "user2", "pass2")
cred1, err := c.CredentialCreate(ctx, reg1, "user2", "pass2")
if err != nil {
t.Fatal(err)
}

cred1New, err := c.CredentialGet(ctx, "two.example.com:443")
cred1New, err := c.CredentialGet(ctx, reg1)
if err != nil {
t.Fatal(err)
}
Expand All @@ -122,6 +137,11 @@ func TestCredentialUpdate(t *testing.T) {
helper.StartController(t)
restConfig := helper.StartAPI(t)

reg, close := helper.StartRegistry(t)
reg1, close1 := helper.StartRegistry(t)
defer close()
defer close1()

ctx := helper.GetCTX(t)
kclient := helper.MustReturn(kclient.Default)
ns := helper.TempNamespace(t, kclient)
Expand All @@ -131,22 +151,22 @@ func TestCredentialUpdate(t *testing.T) {
t.Fatal(err)
}

_, err = c.CredentialCreate(ctx, "example.com:443", "user", "pass")
_, err = c.CredentialCreate(ctx, reg, "user", "pass")
if err != nil {
t.Fatal(err)
}

_, err = c.CredentialCreate(ctx, "two.example.com:443", "user2", "pass2")
_, err = c.CredentialCreate(ctx, reg1, "user2", "pass2")
if err != nil {
t.Fatal(err)
}

cred1New, err := c.CredentialUpdate(ctx, "two.example.com:443", "user3", "pass3")
cred1New, err := c.CredentialUpdate(ctx, reg1, "user3", "pass3")
if err != nil {
t.Fatal(err)
}

cred1NewNew, err := c.CredentialGet(ctx, "two.example.com:443")
cred1NewNew, err := c.CredentialGet(ctx, reg1)
if err != nil {
t.Fatal(err)
}
Expand All @@ -160,6 +180,11 @@ func TestCredentialDelete(t *testing.T) {
helper.StartController(t)
restConfig := helper.StartAPI(t)

reg, close := helper.StartRegistry(t)
reg1, close1 := helper.StartRegistry(t)
defer close()
defer close1()

ctx := helper.GetCTX(t)
kclient := helper.MustReturn(kclient.Default)
ns := helper.TempNamespace(t, kclient)
Expand All @@ -169,12 +194,12 @@ func TestCredentialDelete(t *testing.T) {
t.Fatal(err)
}

_, err = c.CredentialCreate(ctx, "example.com:443", "user", "pass")
_, err = c.CredentialCreate(ctx, reg, "user", "pass")
if err != nil {
t.Fatal(err)
}

_, err = c.CredentialCreate(ctx, "two.example.com:443", "user2", "pass2")
_, err = c.CredentialCreate(ctx, reg1, "user2", "pass2")
if err != nil {
t.Fatal(err)
}
Expand All @@ -186,7 +211,7 @@ func TestCredentialDelete(t *testing.T) {

assert.Len(t, creds, 2)

_, err = c.CredentialDelete(ctx, "two.example.com:443")
_, err = c.CredentialDelete(ctx, reg1)
if err != nil {
t.Fatal(err)
}
Expand Down
32 changes: 32 additions & 0 deletions pkg/client/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,23 @@ package client

import (
"context"
"net/http"
"sort"

apiv1 "github.com/acorn-io/acorn/pkg/apis/api.acorn.io/v1"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kclient "sigs.k8s.io/controller-runtime/pkg/client"
)

func (c *client) CredentialCreate(ctx context.Context, serverAddress, username, password string) (*apiv1.Credential, error) {
if err := credentialValidate(ctx, username, password, serverAddress); err != nil {
return nil, err
}

credential := &apiv1.Credential{
ObjectMeta: metav1.ObjectMeta{
Name: serverAddress,
Expand All @@ -32,6 +40,10 @@ func (c *client) CredentialGet(ctx context.Context, serverAddress string) (*apiv
}

func (c *client) CredentialUpdate(ctx context.Context, serverAddress, username, password string) (*apiv1.Credential, error) {
if err := credentialValidate(ctx, username, password, serverAddress); err != nil {
return nil, err
}

credential := &apiv1.Credential{}
err := c.Client.Get(ctx, kclient.ObjectKey{
Name: serverAddress,
Expand Down Expand Up @@ -84,3 +96,23 @@ func (c *client) CredentialDelete(ctx context.Context, serverAddress string) (*a
}
return credential, err
}

// credentialValidate takes a username, password and serverAddress string to validate
// whether their combination is valid and will succeed login for pushes/pulls.
func credentialValidate(ctx context.Context, username, password, serverAddress string) error {
// Build a registry struct for the host
reg, err := name.NewRegistry(serverAddress)
if err != nil {
return err
}

// Build a new transport for the registry which validates authentication
scopes := []string{transport.PullScope, transport.PushScope}
auth := &authn.Basic{Username: username, Password: password}
_, err = transport.NewWithContext(ctx, reg, auth, http.DefaultTransport, scopes)
if err != nil {
return err
}

return nil
}

0 comments on commit 7e27f1c

Please sign in to comment.