mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +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
|
// 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
|
namespace string
|
||||||
verb string
|
verb string
|
||||||
kind string
|
kind string
|
||||||
|
@ -19,8 +29,8 @@ type CanIOptions struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCanI returns a new instance of operation access controller evaluator
|
// NewCanI returns a new instance of operation access controller evaluator
|
||||||
func NewCanI(client dclient.Interface, kind, namespace, verb string) *CanIOptions {
|
func NewCanI(client dclient.Interface, kind, namespace, verb string) CanIOptions {
|
||||||
return &CanIOptions{
|
return &canIOptions{
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
kind: kind,
|
kind: kind,
|
||||||
verb: verb,
|
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
|
// - 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
|
// - If disallowed, the reason and evaluationError is available in the logs
|
||||||
// - each can generates a SelfSubjectAccessReview resource and response is evaluated for permissions
|
// - 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 GroupVersionResource from RESTMapper
|
||||||
// get GVR from kind
|
// get GVR from kind
|
||||||
gvr, err := o.client.Discovery().GetGVRFromKind(o.kind)
|
gvr, err := o.client.Discovery().GetGVRFromKind(o.kind)
|
||||||
|
|
|
@ -1,48 +1,92 @@
|
||||||
package auth
|
package auth
|
||||||
|
|
||||||
// import (
|
import (
|
||||||
// "testing"
|
"testing"
|
||||||
// "time"
|
|
||||||
|
|
||||||
// "github.com/golang/glog"
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||||
// "github.com/kyverno/kyverno/pkg/config"
|
"github.com/stretchr/testify/assert"
|
||||||
// dclient "github.com/kyverno/kyverno/pkg/clients/dclient"
|
)
|
||||||
// "github.com/kyverno/kyverno/pkg/signal"
|
|
||||||
// )
|
|
||||||
|
|
||||||
// func Test_Auth_pass(t *testing.T) {
|
func TestNewCanI(t *testing.T) {
|
||||||
// // needs running cluster
|
type args struct {
|
||||||
// var kubeconfig string
|
client dclient.Interface
|
||||||
// stopCh := signal.SetupSignalHandler()
|
kind string
|
||||||
// kubeconfig = "/Users/shivd/.kube/config"
|
namespace string
|
||||||
// clientConfig, err := config.CreateClientConfig(kubeconfig)
|
verb string
|
||||||
// if err != nil {
|
}
|
||||||
// glog.Fatalf("Error building kubeconfig: %v\n", err)
|
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
|
func TestCanIOptions_RunAccessCheck(t *testing.T) {
|
||||||
// // - client for all registered resources
|
type fields struct {
|
||||||
// // - invalidate local cache of registered resource every 10 seconds
|
namespace string
|
||||||
// client, err := dclient.NewClient(clientConfig, 10*time.Second, stopCh)
|
verb string
|
||||||
// if err != nil {
|
kind string
|
||||||
// glog.Fatalf("Error creating client: %v\n", err)
|
client dclient.Interface
|
||||||
// }
|
}
|
||||||
|
tests := []struct {
|
||||||
// // Can i authenticate
|
name string
|
||||||
|
fields fields
|
||||||
// kind := "Deployment"
|
want bool
|
||||||
// namespace := "default"
|
wantErr bool
|
||||||
// verb := "test"
|
}{{
|
||||||
// canI := NewCanI(client, kind, namespace, verb)
|
name: "deployments",
|
||||||
// ok, err := canI.RunAccessCheck()
|
fields: fields{
|
||||||
// if err != nil {
|
client: dclient.NewEmptyFakeClient(),
|
||||||
// t.Error(err)
|
kind: "Deployment",
|
||||||
// }
|
namespace: "default",
|
||||||
// if ok {
|
verb: "test",
|
||||||
// t.Log("allowed")
|
},
|
||||||
// } else {
|
want: false,
|
||||||
// t.Log("notallowed")
|
wantErr: false,
|
||||||
// }
|
}, {
|
||||||
// t.FailNow()
|
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()
|
scheme := runtime.NewScheme()
|
||||||
|
|
||||||
return &client{
|
return &client{
|
||||||
client: fake.NewSimpleDynamicClientWithCustomListKinds(scheme, gvrToListKind, objects...),
|
client: fake.NewSimpleDynamicClientWithCustomListKinds(scheme, gvrToListKind, objects...),
|
||||||
kclient: kubefake.NewSimpleClientset(objects...),
|
kclient: kubefake.NewSimpleClientset(objects...),
|
||||||
|
discoveryClient: NewFakeDiscoveryClient(nil),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue