mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
refactor: add auth interface and unit tests (#4518)
Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com> Signed-off-by: Charles-Edouard Brétéché <charled.breteche@gmail.com>
This commit is contained in:
parent
92e223b7ff
commit
2c86416900
3 changed files with 104 additions and 49 deletions
|
@ -11,7 +11,17 @@ import (
|
|||
)
|
||||
|
||||
// CanIOptions provides utility to check if user has authorization for the given operation
|
||||
type CanIOptions struct {
|
||||
type CanIOptions interface {
|
||||
// RunAccessCheck checks if the caller can perform the operation
|
||||
// - operation is a combination of namespace, kind, verb
|
||||
// - can only evaluate a single verb
|
||||
// - group version resource is determined from the kind using the discovery client REST mapper
|
||||
// - If disallowed, the reason and evaluationError is available in the logs
|
||||
// - each can generates a SelfSubjectAccessReview resource and response is evaluated for permissions
|
||||
RunAccessCheck() (bool, error)
|
||||
}
|
||||
|
||||
type canIOptions struct {
|
||||
namespace string
|
||||
verb string
|
||||
kind string
|
||||
|
@ -19,8 +29,8 @@ type CanIOptions struct {
|
|||
}
|
||||
|
||||
// NewCanI returns a new instance of operation access controller evaluator
|
||||
func NewCanI(client dclient.Interface, kind, namespace, verb string) *CanIOptions {
|
||||
return &CanIOptions{
|
||||
func NewCanI(client dclient.Interface, kind, namespace, verb string) CanIOptions {
|
||||
return &canIOptions{
|
||||
namespace: namespace,
|
||||
kind: kind,
|
||||
verb: verb,
|
||||
|
@ -34,7 +44,7 @@ func NewCanI(client dclient.Interface, kind, namespace, verb string) *CanIOption
|
|||
// - group version resource is determined from the kind using the discovery client REST mapper
|
||||
// - If disallowed, the reason and evaluationError is available in the logs
|
||||
// - each can generates a SelfSubjectAccessReview resource and response is evaluated for permissions
|
||||
func (o *CanIOptions) RunAccessCheck() (bool, error) {
|
||||
func (o *canIOptions) RunAccessCheck() (bool, error) {
|
||||
// get GroupVersionResource from RESTMapper
|
||||
// get GVR from kind
|
||||
gvr, err := o.client.Discovery().GetGVRFromKind(o.kind)
|
||||
|
|
|
@ -1,48 +1,92 @@
|
|||
package auth
|
||||
|
||||
// import (
|
||||
// "testing"
|
||||
// "time"
|
||||
import (
|
||||
"testing"
|
||||
|
||||
// "github.com/golang/glog"
|
||||
// "github.com/kyverno/kyverno/pkg/config"
|
||||
// dclient "github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
// "github.com/kyverno/kyverno/pkg/signal"
|
||||
// )
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// func Test_Auth_pass(t *testing.T) {
|
||||
// // needs running cluster
|
||||
// var kubeconfig string
|
||||
// stopCh := signal.SetupSignalHandler()
|
||||
// kubeconfig = "/Users/shivd/.kube/config"
|
||||
// clientConfig, err := config.CreateClientConfig(kubeconfig)
|
||||
// if err != nil {
|
||||
// glog.Fatalf("Error building kubeconfig: %v\n", err)
|
||||
// }
|
||||
func TestNewCanI(t *testing.T) {
|
||||
type args struct {
|
||||
client dclient.Interface
|
||||
kind string
|
||||
namespace string
|
||||
verb string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
}{{
|
||||
name: "deployments",
|
||||
args: args{
|
||||
client: dclient.NewEmptyFakeClient(),
|
||||
kind: "Deployment",
|
||||
namespace: "default",
|
||||
verb: "test",
|
||||
},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := NewCanI(tt.args.client, tt.args.kind, tt.args.namespace, tt.args.verb)
|
||||
assert.NotNil(t, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// // DYNAMIC CLIENT
|
||||
// // - client for all registered resources
|
||||
// // - invalidate local cache of registered resource every 10 seconds
|
||||
// client, err := dclient.NewClient(clientConfig, 10*time.Second, stopCh)
|
||||
// if err != nil {
|
||||
// glog.Fatalf("Error creating client: %v\n", err)
|
||||
// }
|
||||
|
||||
// // Can i authenticate
|
||||
|
||||
// kind := "Deployment"
|
||||
// namespace := "default"
|
||||
// verb := "test"
|
||||
// canI := NewCanI(client, kind, namespace, verb)
|
||||
// ok, err := canI.RunAccessCheck()
|
||||
// if err != nil {
|
||||
// t.Error(err)
|
||||
// }
|
||||
// if ok {
|
||||
// t.Log("allowed")
|
||||
// } else {
|
||||
// t.Log("notallowed")
|
||||
// }
|
||||
// t.FailNow()
|
||||
|
||||
// }
|
||||
func TestCanIOptions_RunAccessCheck(t *testing.T) {
|
||||
type fields struct {
|
||||
namespace string
|
||||
verb string
|
||||
kind string
|
||||
client dclient.Interface
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want bool
|
||||
wantErr bool
|
||||
}{{
|
||||
name: "deployments",
|
||||
fields: fields{
|
||||
client: dclient.NewEmptyFakeClient(),
|
||||
kind: "Deployment",
|
||||
namespace: "default",
|
||||
verb: "test",
|
||||
},
|
||||
want: false,
|
||||
wantErr: false,
|
||||
}, {
|
||||
name: "unknown",
|
||||
fields: fields{
|
||||
client: dclient.NewEmptyFakeClient(),
|
||||
kind: "Unknown",
|
||||
namespace: "default",
|
||||
verb: "test",
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
}, {
|
||||
name: "v2 pods",
|
||||
fields: fields{
|
||||
client: dclient.NewEmptyFakeClient(),
|
||||
kind: "v2/Pod",
|
||||
namespace: "default",
|
||||
verb: "test",
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
o := NewCanI(tt.fields.client, tt.fields.kind, tt.fields.namespace, tt.fields.verb)
|
||||
got, err := o.RunAccessCheck()
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,9 @@ func NewEmptyFakeClient() Interface {
|
|||
scheme := runtime.NewScheme()
|
||||
|
||||
return &client{
|
||||
client: fake.NewSimpleDynamicClientWithCustomListKinds(scheme, gvrToListKind, objects...),
|
||||
kclient: kubefake.NewSimpleClientset(objects...),
|
||||
client: fake.NewSimpleDynamicClientWithCustomListKinds(scheme, gvrToListKind, objects...),
|
||||
kclient: kubefake.NewSimpleClientset(objects...),
|
||||
discoveryClient: NewFakeDiscoveryClient(nil),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue