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

1/n] Adding entities and enum type for auth support #4248

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
77 changes: 77 additions & 0 deletions src/dbnode/auth/entities.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) 2023 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package auth

import (
"errors"
)

// InboundCredentials encapsulates credentials for inbound RPCs to dbnode.
type InboundCredentials struct {
Username string
Digest string
Type CredentialType
}

// Validate validates the InboundCredentials.
func (c *InboundCredentials) Validate() error {
if c.Username == "" {
return errors.New("username field is empty for inbound")
}

if c.Digest == "" {
return errors.New("digest field is empty for inbound")
}

if c.Type != CredentialClient {
return errors.New("incorrect cred type field for inbound")
}

return nil
}

// OutboundCredentials encapsulates credentials for outbound RPCs from dbnode.
type OutboundCredentials struct {
Username string
Password string
Zone string
Type CredentialType
}

// Validate validates the OutboundCredentials.
func (c *OutboundCredentials) Validate() error {
if c.Username == "" {
return errors.New("username field is empty for outbound")
}

if c.Password == "" {
return errors.New("password field is empty for outbound")
}

if c.Type == CredentialUnknown {
return errors.New("incorrect cred type field for outbound")
}

if c.Zone == "" {
return errors.New("zone field is not set for outbound")
}
return nil
}
134 changes: 134 additions & 0 deletions src/dbnode/auth/entities_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright (c) 2023 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package auth

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestInboundCredentials_Validate(t *testing.T) {
tests := []struct {
name string
userName string
digest string
credtype CredentialType
err string
}{
{
name: "no error",
userName: "abc",
digest: "xyz",
credtype: ClientCredential,
}, {
name: "username missing",
digest: "xyz",
err: "username field is empty",
}, {
name: "digest missing",
userName: "xyz",
credtype: ClientCredential,
err: "digest field is empty for inbound",
}, {
name: "cred type missing",
userName: "abc",
digest: "xyz",
err: "incorrect cred type field for inbound",
}, {
name: "incorrect cred type",
userName: "abc",
digest: "xyz",
credtype: EtcdCredential,
err: "incorrect cred type field for inbound",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
newCreds := &InboundCredentials{Username: tt.userName, Digest: tt.digest, Type: tt.credtype}
err := newCreds.Validate()
if tt.err != "" {
assert.Contains(t, err.Error(), tt.err)
} else {
assert.NoError(t, err)
}
})
}
}

func TestOutboundCredentials_Validate(t *testing.T) {
tests := []struct {
name string
userName string
password string
zone string
credtype CredentialType
err string
}{
{
name: "no error",
userName: "abc",
password: "xyz",
zone: "foo",
credtype: EtcdCredential,
}, {
name: "username missing",
password: "xyz",
zone: "foo",
err: "username field is empty",
}, {
name: "password missing",
userName: "xyz",
zone: "foo",
credtype: EtcdCredential,
err: "password field is empty",
}, {
name: "zone missing",
userName: "abc",
password: "xyz",
credtype: PeerCredential,
err: "zone field is not set",
}, {
name: "zone missing for dbnode - etcd",
userName: "abc",
password: "xyz",
credtype: EtcdCredential,
err: "zone field is not set",
}, {
name: "cred type missing",
userName: "abc",
password: "xyz",
zone: "foo",
err: "incorrect cred type field for outbound",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
newCreds := &OutboundCredentials{Username: tt.userName, Password: tt.password, Zone: tt.zone, Type: tt.credtype}
err := newCreds.Validate()
if tt.err != "" {
assert.Contains(t, err.Error(), tt.err)
} else {
assert.NoError(t, err)
}
})
}
}
57 changes: 57 additions & 0 deletions src/dbnode/auth/enum.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) 2023 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package auth

// CredentialType designates credentials for different connection edges.
type CredentialType int

const (
// CredentialUnknown defines unknown connection edge.
CredentialUnknown CredentialType = iota

// CredentialClient defines m3db client to dbnode connection credentials.
CredentialClient

// CredentialPeer defines dbnode to dbnode connections credentials.
CredentialPeer

// CredentialEtcd defines dbnode to etcd connections credentials.
CredentialEtcd
)

// Mode designates a type of authentication.
type Mode int

const (
// ModeUnknown is unknown authentication type case.
ModeUnknown Mode = iota

// ModeNoAuth is no authentication type case.
ModeNoAuth

// ModeShadow mode runs authentication in shadow mode. Credentials will be passed
// by respective peers/clients but will not be used to reject RPCs in case of auth failure.
ModeShadow

// ModeEnforced mode runs dbnode in enforced authentication mode. RPCs to dbnode will be rejected
// if auth fails.
ModeEnforced
)