package adapter import ( "strings" kapi "k8s.io/kubernetes/pkg/api" kauthorizer "k8s.io/kubernetes/pkg/auth/authorizer" "k8s.io/kubernetes/pkg/auth/user" oauthorizer "github.com/openshift/origin/pkg/authorization/authorizer" ) var _ = kauthorizer.Attributes(AdapterAttributes{}) // AdapterAttributes satisfies k8s authorizer.Attributes interfaces type AdapterAttributes struct { namespace string user user.Info authorizationAttributes oauthorizer.Action } // OriginAuthorizerAttributes adapts Kubernetes authorization attributes to Origin authorization attributes // Note that some info (like resourceName, apiVersion, apiGroup) is not available from the Kubernetes attributes func OriginAuthorizerAttributes(kattrs kauthorizer.Attributes) (kapi.Context, oauthorizer.Action) { // Build a context to hold the namespace and user info ctx := kapi.NewContext() ctx = kapi.WithNamespace(ctx, kattrs.GetNamespace()) ctx = kapi.WithUser(ctx, kattrs.GetUser()) // If we recognize the type, use the embedded type. Do NOT use it directly, because not all things that quack are ducks. if castAdapterAttributes, ok := kattrs.(AdapterAttributes); ok { return ctx, castAdapterAttributes.authorizationAttributes } // Otherwise build what we can oattrs := &oauthorizer.DefaultAuthorizationAttributes{ Verb: kattrs.GetVerb(), APIGroup: kattrs.GetAPIGroup(), APIVersion: kattrs.GetAPIVersion(), Resource: kattrs.GetResource(), ResourceName: kattrs.GetName(), NonResourceURL: kattrs.IsResourceRequest() == false, URL: kattrs.GetPath(), // TODO: add to kube authorizer attributes // RequestAttributes interface{} } if len(kattrs.GetSubresource()) > 0 { oattrs.Resource = kattrs.GetResource() + "/" + kattrs.GetSubresource() } return ctx, oattrs } // KubernetesAuthorizerAttributes adapts Origin authorization attributes to Kubernetes authorization attributes // The returned attributes can be passed to OriginAuthorizerAttributes to access extra information from the Origin attributes interface func KubernetesAuthorizerAttributes(namespace string, user user.Info, oattrs oauthorizer.Action) kauthorizer.Attributes { return AdapterAttributes{ namespace: namespace, user: user, authorizationAttributes: oattrs, } } func (a AdapterAttributes) GetVerb() string { return a.authorizationAttributes.GetVerb() } func (a AdapterAttributes) GetAPIGroup() string { return a.authorizationAttributes.GetAPIGroup() } func (a AdapterAttributes) GetAPIVersion() string { return a.authorizationAttributes.GetAPIVersion() } // GetNamespace satisfies the kubernetes authorizer.Attributes interface // origin gets this value from the request context func (a AdapterAttributes) GetNamespace() string { return a.namespace } func (a AdapterAttributes) GetName() string { return a.authorizationAttributes.GetResourceName() } func (a AdapterAttributes) GetSubresource() string { tokens := strings.SplitN(a.authorizationAttributes.GetResource(), "/", 2) if len(tokens) != 2 { return "" } return tokens[1] } func (a AdapterAttributes) GetResource() string { tokens := strings.SplitN(a.authorizationAttributes.GetResource(), "/", 2) if len(tokens) < 1 { return "" } return tokens[0] } // GetUserName satisfies the kubernetes authorizer.Attributes interface // origin gets this value from the request context func (a AdapterAttributes) GetUser() user.Info { return a.user } // IsReadOnly satisfies the kubernetes authorizer.Attributes interface based on the verb func (a AdapterAttributes) IsReadOnly() bool { v := a.GetVerb() return v == "get" || v == "list" || v == "watch" } // IsResourceRequest satisfies the kubernetes authorizer.Attributes interface func (a AdapterAttributes) IsResourceRequest() bool { return !a.authorizationAttributes.IsNonResourceURL() } // GetPath satisfies the kubernetes authorizer.Attributes interface func (a AdapterAttributes) GetPath() string { return a.authorizationAttributes.GetURL() }