未验证 提交 a3d3c8e4 编写于 作者: H hongming

update

Signed-off-by: Nhongming <talonwan@yunify.com>
上级 0e814bb5
......@@ -35,6 +35,7 @@ import (
controllerconfig "kubesphere.io/kubesphere/pkg/apiserver/config"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
"kubesphere.io/kubesphere/pkg/controller/namespace"
"kubesphere.io/kubesphere/pkg/controller/user"
"kubesphere.io/kubesphere/pkg/controller/workspace"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
......@@ -43,6 +44,7 @@ import (
"os"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
"sigs.k8s.io/controller-runtime/pkg/webhook"
)
func NewControllerManagerCommand() *cobra.Command {
......@@ -151,13 +153,13 @@ func Run(s *options.KubeSphereControllerManagerOptions, stopCh <-chan struct{})
// Start cache data after all informer is registered
informerFactory.Start(stopCh)
// Setup webhooks TODO enable webhook
//klog.Info("setting up webhook server")
//hookServer := mgr.GetWebhookServer()
//
//klog.Info("registering webhooks to the webhook server")
//hookServer.Register("//mutating-encrypt-password-iam-kubesphere-io-v1alpha2-user", &webhook.Admission{Handler: &user.PasswordCipher{Client: mgr.GetClient()}})
//hookServer.Register("/validate-email-iam-kubesphere-io-v1alpha2-user", &webhook.Admission{Handler: &user.EmailValidator{Client: mgr.GetClient()}})
// Setup webhooks
klog.Info("setting up webhook server")
hookServer := mgr.GetWebhookServer()
klog.Info("registering webhooks to the webhook server")
hookServer.Register("/mutating-encrypt-password-iam-kubesphere-io-v1alpha2-user", &webhook.Admission{Handler: &user.PasswordCipher{Client: mgr.GetClient()}})
hookServer.Register("/validate-email-iam-kubesphere-io-v1alpha2-user", &webhook.Admission{Handler: &user.EmailValidator{Client: mgr.GetClient()}})
klog.V(0).Info("Starting the controllers.")
if err = mgr.Start(stopCh); err != nil {
......
......@@ -8,6 +8,10 @@ metadata:
creationTimestamp: null
name: policyrules.iam.kubesphere.io
spec:
additionalPrinterColumns:
- JSONPath: .scope
name: Scope
type: string
group: iam.kubesphere.io
names:
categories:
......@@ -17,6 +21,7 @@ spec:
plural: policyrules
singular: policyrule
scope: Cluster
subresources: {}
validation:
openAPIV3Schema:
properties:
......@@ -30,15 +35,15 @@ spec:
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
level:
type: string
metadata:
type: object
rego:
type: string
scope:
type: string
required:
- level
- rego
- scope
type: object
version: v1alpha2
versions:
......
......@@ -8,6 +8,16 @@ metadata:
creationTimestamp: null
name: rolebindings.iam.kubesphere.io
spec:
additionalPrinterColumns:
- JSONPath: .scope
name: Scope
type: string
- JSONPath: .roleRef.name
name: RoleRef
type: string
- JSONPath: .subjects[*].name
name: Subjects
type: string
group: iam.kubesphere.io
names:
categories:
......@@ -17,6 +27,7 @@ spec:
plural: rolebindings
singular: rolebinding
scope: Cluster
subresources: {}
validation:
openAPIV3Schema:
description: RoleBinding is the Schema for the rolebindings API
......@@ -31,8 +42,6 @@ spec:
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
level:
type: string
metadata:
type: object
roleRef:
......@@ -53,6 +62,8 @@ spec:
- kind
- name
type: object
scope:
type: string
subjects:
description: Subjects holds references to the users the role applies to.
items:
......@@ -77,8 +88,8 @@ spec:
type: object
type: array
required:
- level
- roleRef
- scope
type: object
version: v1alpha2
versions:
......
......@@ -8,6 +8,13 @@ metadata:
creationTimestamp: null
name: roles.iam.kubesphere.io
spec:
additionalPrinterColumns:
- JSONPath: .target.scope
name: Scope
type: string
- JSONPath: .target.name
name: Target
type: string
group: iam.kubesphere.io
names:
categories:
......@@ -17,6 +24,7 @@ spec:
plural: roles
singular: role
scope: Cluster
subresources: {}
validation:
openAPIV3Schema:
properties:
......@@ -52,21 +60,19 @@ spec:
- name
type: object
type: array
scope:
target:
properties:
level:
name:
type: string
scope:
type: string
scopes:
items:
type: string
type: array
required:
- level
- scopes
- name
- scope
type: object
required:
- rules
- scope
- target
type: object
version: v1alpha2
versions:
......
......@@ -3,7 +3,53 @@ kind: PolicyRule
metadata:
labels:
controller-tools.k8s.io: "1.0"
name: policyrule-sample
spec:
# Add fields here
foo: bar
name: always-allow
scope: Global
rego: 'package authz\ndefault allow = true'
---
apiVersion: iam.kubesphere.io/v1alpha2
kind: PolicyRule
metadata:
labels:
controller-tools.k8s.io: "1.0"
name: always-deny
scope: Global
rego:
package authz
default allow = false
---
apiVersion: iam.kubesphere.io/v1alpha2
kind: PolicyRule
metadata:
labels:
controller-tools.k8s.io: "1.0"
name: cluster-manage
scope: Global
rego:
package authz
default allow = false
allow {
input.Resource == 'clusters'
}
---
apiVersion: iam.kubesphere.io/v1alpha2
kind: PolicyRule
metadata:
labels:
controller-tools.k8s.io: "1.0"
name: some-namespace-manage
scope: Namespace
rego:
package authz
default allow = false
allow {
input.Resource == 'clusters'
}
......@@ -3,7 +3,28 @@ kind: Role
metadata:
labels:
controller-tools.k8s.io: "1.0"
name: role-sample
spec:
# Add fields here
foo: bar
name: cluster-admin
target:
scope: Global
name: ''
rules:
- apiGroup: iam.kubesphere.io/v1alpha2
kind: PolicyRule
name: always-allow
---
apiVersion: iam.kubesphere.io/v1alpha2
kind: Role
metadata:
labels:
controller-tools.k8s.io: "1.0"
name: anonymous
target:
scope: Global
name: ''
rules:
- apiGroup: iam.kubesphere.io/v1alpha2
kind: PolicyRule
name: always-deny
......@@ -3,7 +3,13 @@ kind: RoleBinding
metadata:
labels:
controller-tools.k8s.io: "1.0"
name: rolebinding-sample
spec:
# Add fields here
foo: bar
name: cluster-admin
scope: Global
roleRef:
apiGroup: iam.kubesphere.io/v1alpha2
kind: Role
name: cluster-admin
subjects:
- apiGroup: iam.kubesphere.io/v1alpha2
kind: User
name: admin
......@@ -21,8 +21,8 @@ import (
)
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +k8s:openapi-gen=true
// User is the Schema for the users API
......@@ -125,30 +125,38 @@ type UserList struct {
Items []User `json:"items"`
}
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:printcolumn:name="Scope",type="string",JSONPath=".target.scope"
// +kubebuilder:printcolumn:name="Target",type="string",JSONPath=".target.name"
// +kubebuilder:resource:categories="iam",scope="Cluster"
type Role struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Scope Scope `json:"scope"`
Rules []RuleRef `json:"rules"`
Target Target `json:"target"`
Rules []RuleRef `json:"rules"`
}
type Scope struct {
Level Level `json:"level"`
Scopes []string `json:"scopes"`
type Target struct {
Scope Scope `json:"scope"`
Name string `json:"name"`
}
type Level string
type Scope string
const (
LevelGlobal Level = "Global"
LevelCluster Level = "Cluster"
LevelWorkspace Level = "Workspace"
LevelNamespace Level = "Namespace"
ScopeALL = "*"
GlobalScope Scope = "Global"
ClusterScope Scope = "Cluster"
WorkspaceScope Scope = "Workspace"
NamespaceScope Scope = "Namespace"
TargetAll = "*"
UserKind = "User"
PolicyRuleKind = "PolicyRule"
RoleKind = "Role"
RoleBindingKind = "RoleBinding"
)
// RuleRef contains information that points to the role being used
......@@ -170,14 +178,17 @@ type RoleList struct {
Items []Role `json:"items"`
}
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:printcolumn:name="Scope",type="string",JSONPath=".scope"
// +kubebuilder:resource:categories="iam",scope="Cluster"
type PolicyRule struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Level Level `json:"level"`
Scope Scope `json:"scope"`
Rego string `json:"rego"`
}
......@@ -190,15 +201,20 @@ type PolicyRuleList struct {
Items []PolicyRule `json:"items"`
}
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// RoleBinding is the Schema for the rolebindings API
// +kubebuilder:printcolumn:name="Scope",type="string",JSONPath=".scope"
// +kubebuilder:printcolumn:name="RoleRef",type="string",JSONPath=".roleRef.name"
// +kubebuilder:printcolumn:name="Subjects",type="string",JSONPath=".subjects[*].name"
// +kubebuilder:resource:categories="iam",scope="Cluster"
type RoleBinding struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Level Level `json:"level"`
Scope Scope `json:"scope"`
RoleRef RoleRef `json:"roleRef"`
// Subjects holds references to the users the role applies to.
// +optional
......@@ -234,3 +250,8 @@ type RoleBindingList struct {
metav1.ListMeta `json:"metadata,omitempty"`
Items []RoleBinding `json:"items"`
}
type UserDetail struct {
*User
GlobalRole *Role `json:"globalRole"`
}
......@@ -86,7 +86,7 @@ func (in *Role) DeepCopyInto(out *Role) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Scope.DeepCopyInto(&out.Scope)
out.Target = in.Target
if in.Rules != nil {
in, out := &in.Rules, &out.Rules
*out = make([]RuleRef, len(*in))
......@@ -238,36 +238,31 @@ func (in *RuleRef) DeepCopy() *RuleRef {
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Scope) DeepCopyInto(out *Scope) {
func (in *Subject) DeepCopyInto(out *Subject) {
*out = *in
if in.Scopes != nil {
in, out := &in.Scopes, &out.Scopes
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Scope.
func (in *Scope) DeepCopy() *Scope {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subject.
func (in *Subject) DeepCopy() *Subject {
if in == nil {
return nil
}
out := new(Scope)
out := new(Subject)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Subject) DeepCopyInto(out *Subject) {
func (in *Target) DeepCopyInto(out *Target) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subject.
func (in *Subject) DeepCopy() *Subject {
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Target.
func (in *Target) DeepCopy() *Target {
if in == nil {
return nil
}
out := new(Subject)
out := new(Target)
in.DeepCopyInto(out)
return out
}
......@@ -315,6 +310,31 @@ func (in *UserCondition) DeepCopy() *UserCondition {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UserDetail) DeepCopyInto(out *UserDetail) {
*out = *in
if in.User != nil {
in, out := &in.User, &out.User
*out = new(User)
(*in).DeepCopyInto(*out)
}
if in.GlobalRole != nil {
in, out := &in.GlobalRole, &out.GlobalRole
*out = new(Role)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserDetail.
func (in *UserDetail) DeepCopy() *UserDetail {
if in == nil {
return nil
}
out := new(UserDetail)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *UserList) DeepCopyInto(out *UserList) {
*out = *in
......
......@@ -144,7 +144,10 @@ func (s *APIServer) installKubeSphereAPIs() {
urlruntime.Must(resourcesv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.InformerFactory))
//urlruntime.Must(tenantv1alpha2.AddToContainer(s.container, s.KubernetesClient, s.InformerFactory, s.DBClient.Database()))
urlruntime.Must(terminalv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.KubernetesClient.Config()))
urlruntime.Must(iamv1alpha2.AddToContainer(s.container, s.KubernetesClient, s.InformerFactory, s.LdapClient, s.CacheClient, s.Config.AuthenticationOptions))
urlruntime.Must(iamv1alpha2.AddToContainer(s.container, im.NewOperator(s.KubernetesClient.KubeSphere(),
s.InformerFactory.KubeSphereSharedInformerFactory()),
am.NewAMOperator(s.KubernetesClient.KubeSphere(), s.InformerFactory.KubeSphereSharedInformerFactory()),
s.Config.AuthenticationOptions))
urlruntime.Must(oauth.AddToContainer(s.container, token.NewJwtTokenIssuer(token.DefaultIssuerName, s.Config.AuthenticationOptions, s.CacheClient), s.Config.AuthenticationOptions))
urlruntime.Must(servicemeshv1alpha2.AddToContainer(s.container))
}
......@@ -188,7 +191,7 @@ func (s *APIServer) buildHandlerChain() {
pathAuthorizer, _ := path.NewAuthorizer(excludedPaths)
// union authorizers are ordered, don't change the order here
authorizers := unionauthorizer.New(pathAuthorizer, authorizerfactory.NewOPAAuthorizer(am.NewFakeAMOperator()))
authorizers := unionauthorizer.New(pathAuthorizer, authorizerfactory.NewOPAAuthorizer(am.NewAMOperator(s.KubernetesClient.KubeSphere(), s.InformerFactory.KubeSphereSharedInformerFactory())))
handler = filters.WithAuthorization(handler, authorizers)
// authenticators are unordered
......@@ -274,6 +277,9 @@ func (s *APIServer) waitForResourceSync(stopCh <-chan struct{}) error {
ksGVRs := []schema.GroupVersionResource{
{Group: "tenant.kubesphere.io", Version: "v1alpha1", Resource: "workspaces"},
{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "users"},
{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "roles"},
{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "rolebindings"},
{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "policyrules"},
{Group: "tower.kubesphere.io", Version: "v1alpha1", Resource: "agents"},
}
......
......@@ -21,6 +21,9 @@ package authorizerfactory
import (
"context"
"github.com/open-policy-agent/opa/rego"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/klog"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
"kubesphere.io/kubesphere/pkg/models/iam/am"
)
......@@ -33,13 +36,16 @@ type opaAuthorizer struct {
func (o *opaAuthorizer) Authorize(attr authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
// Make decisions based on the authorization policy of different levels of roles
platformRole, err := o.am.GetPlatformRole(attr.GetUser().GetName())
globalRole, err := o.am.GetRoleOfUserInTargetScope(iamv1alpha2.GlobalScope, "", attr.GetUser().GetName())
if err != nil {
if errors.IsNotFound(err) {
return authorizer.DecisionDeny, err.Error(), nil
}
return authorizer.DecisionDeny, "", err
}
// check platform role policy rules
if authorized, reason, err = makeDecision(platformRole, attr); authorized == authorizer.DecisionAllow {
if authorized, reason, err = o.makeDecision(globalRole, attr); authorized == authorizer.DecisionAllow {
return authorized, reason, err
}
......@@ -48,13 +54,16 @@ func (o *opaAuthorizer) Authorize(attr authorizer.Attributes) (authorized author
return authorizer.DecisionDeny, "permission undefined", nil
}
clusterRole, err := o.am.GetClusterRole(attr.GetCluster(), attr.GetUser().GetName())
clusterRole, err := o.am.GetRoleOfUserInTargetScope(iamv1alpha2.ClusterScope, attr.GetCluster(), attr.GetUser().GetName())
if err != nil {
if errors.IsNotFound(err) {
return authorizer.DecisionDeny, err.Error(), nil
}
return authorizer.DecisionDeny, "", err
}
// check cluster role policy rules
if a, r, e := makeDecision(clusterRole, attr); a == authorizer.DecisionAllow {
if a, r, e := o.makeDecision(clusterRole, attr); a == authorizer.DecisionAllow {
return a, r, e
}
......@@ -63,13 +72,16 @@ func (o *opaAuthorizer) Authorize(attr authorizer.Attributes) (authorized author
return authorizer.DecisionDeny, "permission undefined", nil
}
workspaceRole, err := o.am.GetWorkspaceRole(attr.GetWorkspace(), attr.GetUser().GetName())
workspaceRole, err := o.am.GetRoleOfUserInTargetScope(iamv1alpha2.WorkspaceScope, attr.GetWorkspace(), attr.GetUser().GetName())
if err != nil {
if errors.IsNotFound(err) {
return authorizer.DecisionDeny, err.Error(), nil
}
return authorizer.DecisionDeny, "", err
}
// check workspace role policy rules
if a, r, e := makeDecision(workspaceRole, attr); a == authorizer.DecisionAllow {
if a, r, e := o.makeDecision(workspaceRole, attr); a == authorizer.DecisionAllow {
return a, r, e
}
......@@ -79,12 +91,15 @@ func (o *opaAuthorizer) Authorize(attr authorizer.Attributes) (authorized author
}
if attr.GetNamespace() != "" {
namespaceRole, err := o.am.GetNamespaceRole(attr.GetCluster(), attr.GetNamespace(), attr.GetUser().GetName())
namespaceRole, err := o.am.GetRoleOfUserInTargetScope(iamv1alpha2.NamespaceScope, attr.GetNamespace(), attr.GetUser().GetName())
if err != nil {
if errors.IsNotFound(err) {
return authorizer.DecisionDeny, err.Error(), nil
}
return authorizer.DecisionDeny, "", err
}
// check namespace role policy rules
if a, r, e := makeDecision(namespaceRole, attr); a == authorizer.DecisionAllow {
if a, r, e := o.makeDecision(namespaceRole, attr); a == authorizer.DecisionAllow {
return a, r, e
}
}
......@@ -93,48 +108,36 @@ func (o *opaAuthorizer) Authorize(attr authorizer.Attributes) (authorized author
}
// Make decision base on role
func makeDecision(role am.Role, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
func (o *opaAuthorizer) makeDecision(role *iamv1alpha2.Role, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) {
// Call the rego.New function to create an object that can be prepared or evaluated
// After constructing a new rego.Rego object you can call PrepareForEval() to obtain an executable query
query, err := rego.New(rego.Query("data.authz.allow"), rego.Module("authz.rego", role.GetRego())).PrepareForEval(context.Background())
for _, ruleRef := range role.Rules {
rule, err := o.am.GetPolicyRule(ruleRef.Name)
if err != nil {
if errors.IsNotFound(err) {
continue
}
return authorizer.DecisionDeny, "", err
}
// Call the rego.New function to create an object that can be prepared or evaluated
// After constructing a new rego.Rego object you can call PrepareForEval() to obtain an executable query
query, err := rego.New(rego.Query("data.authz.allow"), rego.Module("authz.rego", rule.Rego)).PrepareForEval(context.Background())
if err != nil {
return authorizer.DecisionDeny, "", err
}
if err != nil {
klog.Errorf("rule syntax error:%s", err)
continue
}
// data example
//{
// "User": {
// "Name": "admin",
// "UID": "0",
// "Groups": [
// "admin"
// ],
// "Extra": null
// },
// "Verb": "list",
// "Cluster": "cluster1",
// "Workspace": "",
// "Namespace": "",
// "APIGroup": "",
// "APIVersion": "v1",
// "Resource": "nodes",
// "Subresource": "",
// "Name": "",
// "KubernetesRequest": true,
// "ResourceRequest": true,
// "Path": "/api/v1/nodes"
//}
// The policy decision is contained in the results returned by the Eval() call. You can inspect the decision and handle it accordingly.
results, err := query.Eval(context.Background(), rego.EvalInput(a))
// The policy decision is contained in the results returned by the Eval() call. You can inspect the decision and handle it accordingly.
results, err := query.Eval(context.Background(), rego.EvalInput(a))
if err != nil {
return authorizer.DecisionDeny, "", err
}
if err != nil {
klog.Errorf("rule syntax error:%s", err)
continue
}
if len(results) > 0 && results[0].Expressions[0].Value == true {
return authorizer.DecisionAllow, "", nil
if len(results) > 0 && results[0].Expressions[0].Value == true {
return authorizer.DecisionAllow, "", nil
}
}
return authorizer.DecisionDeny, "permission undefined", nil
......
......@@ -19,22 +19,44 @@
package authorizerfactory
import (
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apiserver/pkg/authentication/user"
iamvealpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
"kubesphere.io/kubesphere/pkg/apiserver/authorization/authorizer"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/fake"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models/iam/am"
"testing"
)
func TestPlatformRole(t *testing.T) {
platformRoles := map[string]am.FakeRole{"admin": {
Name: "admin",
Rego: "package authz\ndefault allow = true",
}, "anonymous": {
Name: "anonymous",
Rego: "package authz\ndefault allow = false",
}, "tom": {
Name: "tom",
Rego: `package authz
func prepare() (am.AccessManagementInterface, error) {
rules := []*iamvealpha2.PolicyRule{
{
TypeMeta: metav1.TypeMeta{
Kind: iamvealpha2.PolicyRuleKind,
APIVersion: iamvealpha2.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "always-allow",
},
Rego: "package authz\ndefault allow = true",
}, {
TypeMeta: metav1.TypeMeta{
Kind: iamvealpha2.PolicyRuleKind,
APIVersion: iamvealpha2.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: "always-deny",
},
Rego: "package authz\ndefault allow = false",
}, {
TypeMeta: metav1.TypeMeta{
Kind: iamvealpha2.PolicyRuleKind,
APIVersion: iamvealpha2.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "manage-cluster1-resources",
},
Rego: `package authz
default allow = false
allow {
resources_in_cluster1
......@@ -42,11 +64,168 @@ allow {
resources_in_cluster1 {
input.Cluster == "cluster1"
}`,
},
},
}
roles := []*iamvealpha2.Role{
{
TypeMeta: metav1.TypeMeta{
Kind: iamvealpha2.RoleKind,
APIVersion: iamvealpha2.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "global-admin",
},
Target: iamvealpha2.Target{
Scope: iamvealpha2.GlobalScope,
Name: "",
},
Rules: []iamvealpha2.RuleRef{
{
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
Kind: iamvealpha2.PolicyRuleKind,
Name: "always-allow",
},
},
},
{
TypeMeta: metav1.TypeMeta{
Kind: iamvealpha2.RoleKind,
APIVersion: iamvealpha2.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "anonymous",
},
Target: iamvealpha2.Target{
Scope: iamvealpha2.GlobalScope,
Name: "",
},
Rules: []iamvealpha2.RuleRef{
{
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
Kind: iamvealpha2.PolicyRuleKind,
Name: "always-deny",
},
},
},
{
TypeMeta: metav1.TypeMeta{
Kind: iamvealpha2.RoleKind,
APIVersion: iamvealpha2.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "cluster1-admin",
},
Target: iamvealpha2.Target{
Scope: iamvealpha2.GlobalScope,
Name: "",
},
Rules: []iamvealpha2.RuleRef{
{
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
Kind: iamvealpha2.PolicyRuleKind,
Name: "manage-cluster1-resources",
},
},
},
}
roleBindings := []*iamvealpha2.RoleBinding{
{
TypeMeta: metav1.TypeMeta{
Kind: iamvealpha2.RoleBindingKind,
APIVersion: iamvealpha2.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "global-admin",
},
Scope: iamvealpha2.GlobalScope,
RoleRef: iamvealpha2.RoleRef{
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
Kind: iamvealpha2.RoleKind,
Name: "global-admin",
},
Subjects: []iamvealpha2.Subject{
{
Kind: iamvealpha2.UserKind,
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
Name: "admin",
},
},
},
{
TypeMeta: metav1.TypeMeta{
Kind: iamvealpha2.RoleBindingKind,
APIVersion: iamvealpha2.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "anonymous",
},
Scope: iamvealpha2.GlobalScope,
RoleRef: iamvealpha2.RoleRef{
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
Kind: iamvealpha2.RoleKind,
Name: "anonymous",
},
Subjects: []iamvealpha2.Subject{
{
Kind: iamvealpha2.UserKind,
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
Name: user.Anonymous,
},
},
},
{
TypeMeta: metav1.TypeMeta{
Kind: iamvealpha2.RoleBindingKind,
APIVersion: iamvealpha2.SchemeGroupVersion.String()},
ObjectMeta: metav1.ObjectMeta{
Name: "cluster1-admin",
},
Scope: iamvealpha2.GlobalScope,
RoleRef: iamvealpha2.RoleRef{
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
Kind: iamvealpha2.RoleKind,
Name: "cluster1-admin",
},
Subjects: []iamvealpha2.Subject{
{
Kind: iamvealpha2.UserKind,
APIGroup: iamvealpha2.SchemeGroupVersion.String(),
Name: "tom",
},
},
},
}
operator := am.NewFakeAMOperator()
operator.Prepare(platformRoles, nil, nil, nil)
ksClient := fake.NewSimpleClientset()
informerFactory := externalversions.NewSharedInformerFactory(ksClient, 0)
for _, rule := range rules {
err := informerFactory.Iam().V1alpha2().PolicyRules().Informer().GetIndexer().Add(rule)
if err != nil {
return nil, fmt.Errorf("add rule:%s", err)
}
}
for _, role := range roles {
err := informerFactory.Iam().V1alpha2().Roles().Informer().GetIndexer().Add(role)
if err != nil {
return nil, fmt.Errorf("add role:%s", err)
}
}
for _, roleBinding := range roleBindings {
err := informerFactory.Iam().V1alpha2().RoleBindings().Informer().GetIndexer().Add(roleBinding)
if err != nil {
return nil, fmt.Errorf("add role binding:%s", err)
}
}
operator := am.NewAMOperator(ksClient, informerFactory)
return operator, nil
}
func TestGlobalRole(t *testing.T) {
operator, err := prepare()
if err != nil {
t.Fatal(err)
}
opa := NewOPAAuthorizer(operator)
......
......@@ -10,7 +10,6 @@ const (
FieldLastUpdateTimestamp = "lastUpdateTimestamp"
FieldLabel = "label"
FieldAnnotation = "annotation"
FieldClusterName = "clusterName"
FieldNamespace = "namespace"
FieldStatus = "status"
FieldOwnerReference = "ownerReference"
......@@ -29,7 +28,6 @@ var ComparableFields = []Field{
FieldUID,
FieldLabel,
FieldAnnotation,
FieldClusterName,
FieldNamespace,
FieldStatus,
FieldOwnerReference,
......
......@@ -28,6 +28,18 @@ type FakeIamV1alpha2 struct {
*testing.Fake
}
func (c *FakeIamV1alpha2) PolicyRules() v1alpha2.PolicyRuleInterface {
return &FakePolicyRules{c}
}
func (c *FakeIamV1alpha2) Roles() v1alpha2.RoleInterface {
return &FakeRoles{c}
}
func (c *FakeIamV1alpha2) RoleBindings() v1alpha2.RoleBindingInterface {
return &FakeRoleBindings{c}
}
func (c *FakeIamV1alpha2) Users() v1alpha2.UserInterface {
return &FakeUsers{c}
}
......
/*
Copyright 2019 The KubeSphere authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
)
// FakePolicyRules implements PolicyRuleInterface
type FakePolicyRules struct {
Fake *FakeIamV1alpha2
}
var policyrulesResource = schema.GroupVersionResource{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "policyrules"}
var policyrulesKind = schema.GroupVersionKind{Group: "iam.kubesphere.io", Version: "v1alpha2", Kind: "PolicyRule"}
// Get takes name of the policyRule, and returns the corresponding policyRule object, and an error if there is any.
func (c *FakePolicyRules) Get(name string, options v1.GetOptions) (result *v1alpha2.PolicyRule, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootGetAction(policyrulesResource, name), &v1alpha2.PolicyRule{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.PolicyRule), err
}
// List takes label and field selectors, and returns the list of PolicyRules that match those selectors.
func (c *FakePolicyRules) List(opts v1.ListOptions) (result *v1alpha2.PolicyRuleList, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootListAction(policyrulesResource, policyrulesKind, opts), &v1alpha2.PolicyRuleList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha2.PolicyRuleList{ListMeta: obj.(*v1alpha2.PolicyRuleList).ListMeta}
for _, item := range obj.(*v1alpha2.PolicyRuleList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested policyRules.
func (c *FakePolicyRules) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewRootWatchAction(policyrulesResource, opts))
}
// Create takes the representation of a policyRule and creates it. Returns the server's representation of the policyRule, and an error, if there is any.
func (c *FakePolicyRules) Create(policyRule *v1alpha2.PolicyRule) (result *v1alpha2.PolicyRule, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootCreateAction(policyrulesResource, policyRule), &v1alpha2.PolicyRule{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.PolicyRule), err
}
// Update takes the representation of a policyRule and updates it. Returns the server's representation of the policyRule, and an error, if there is any.
func (c *FakePolicyRules) Update(policyRule *v1alpha2.PolicyRule) (result *v1alpha2.PolicyRule, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootUpdateAction(policyrulesResource, policyRule), &v1alpha2.PolicyRule{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.PolicyRule), err
}
// Delete takes name of the policyRule and deletes it. Returns an error if one occurs.
func (c *FakePolicyRules) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewRootDeleteAction(policyrulesResource, name), &v1alpha2.PolicyRule{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakePolicyRules) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewRootDeleteCollectionAction(policyrulesResource, listOptions)
_, err := c.Fake.Invokes(action, &v1alpha2.PolicyRuleList{})
return err
}
// Patch applies the patch and returns the patched policyRule.
func (c *FakePolicyRules) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.PolicyRule, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootPatchSubresourceAction(policyrulesResource, name, pt, data, subresources...), &v1alpha2.PolicyRule{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.PolicyRule), err
}
/*
Copyright 2019 The KubeSphere authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
)
// FakeRoles implements RoleInterface
type FakeRoles struct {
Fake *FakeIamV1alpha2
}
var rolesResource = schema.GroupVersionResource{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "roles"}
var rolesKind = schema.GroupVersionKind{Group: "iam.kubesphere.io", Version: "v1alpha2", Kind: "Role"}
// Get takes name of the role, and returns the corresponding role object, and an error if there is any.
func (c *FakeRoles) Get(name string, options v1.GetOptions) (result *v1alpha2.Role, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootGetAction(rolesResource, name), &v1alpha2.Role{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.Role), err
}
// List takes label and field selectors, and returns the list of Roles that match those selectors.
func (c *FakeRoles) List(opts v1.ListOptions) (result *v1alpha2.RoleList, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootListAction(rolesResource, rolesKind, opts), &v1alpha2.RoleList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha2.RoleList{ListMeta: obj.(*v1alpha2.RoleList).ListMeta}
for _, item := range obj.(*v1alpha2.RoleList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested roles.
func (c *FakeRoles) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewRootWatchAction(rolesResource, opts))
}
// Create takes the representation of a role and creates it. Returns the server's representation of the role, and an error, if there is any.
func (c *FakeRoles) Create(role *v1alpha2.Role) (result *v1alpha2.Role, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootCreateAction(rolesResource, role), &v1alpha2.Role{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.Role), err
}
// Update takes the representation of a role and updates it. Returns the server's representation of the role, and an error, if there is any.
func (c *FakeRoles) Update(role *v1alpha2.Role) (result *v1alpha2.Role, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootUpdateAction(rolesResource, role), &v1alpha2.Role{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.Role), err
}
// Delete takes name of the role and deletes it. Returns an error if one occurs.
func (c *FakeRoles) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewRootDeleteAction(rolesResource, name), &v1alpha2.Role{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeRoles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewRootDeleteCollectionAction(rolesResource, listOptions)
_, err := c.Fake.Invokes(action, &v1alpha2.RoleList{})
return err
}
// Patch applies the patch and returns the patched role.
func (c *FakeRoles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.Role, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootPatchSubresourceAction(rolesResource, name, pt, data, subresources...), &v1alpha2.Role{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.Role), err
}
/*
Copyright 2019 The KubeSphere authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package fake
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
)
// FakeRoleBindings implements RoleBindingInterface
type FakeRoleBindings struct {
Fake *FakeIamV1alpha2
}
var rolebindingsResource = schema.GroupVersionResource{Group: "iam.kubesphere.io", Version: "v1alpha2", Resource: "rolebindings"}
var rolebindingsKind = schema.GroupVersionKind{Group: "iam.kubesphere.io", Version: "v1alpha2", Kind: "RoleBinding"}
// Get takes name of the roleBinding, and returns the corresponding roleBinding object, and an error if there is any.
func (c *FakeRoleBindings) Get(name string, options v1.GetOptions) (result *v1alpha2.RoleBinding, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootGetAction(rolebindingsResource, name), &v1alpha2.RoleBinding{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.RoleBinding), err
}
// List takes label and field selectors, and returns the list of RoleBindings that match those selectors.
func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *v1alpha2.RoleBindingList, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootListAction(rolebindingsResource, rolebindingsKind, opts), &v1alpha2.RoleBindingList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha2.RoleBindingList{ListMeta: obj.(*v1alpha2.RoleBindingList).ListMeta}
for _, item := range obj.(*v1alpha2.RoleBindingList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested roleBindings.
func (c *FakeRoleBindings) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewRootWatchAction(rolebindingsResource, opts))
}
// Create takes the representation of a roleBinding and creates it. Returns the server's representation of the roleBinding, and an error, if there is any.
func (c *FakeRoleBindings) Create(roleBinding *v1alpha2.RoleBinding) (result *v1alpha2.RoleBinding, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootCreateAction(rolebindingsResource, roleBinding), &v1alpha2.RoleBinding{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.RoleBinding), err
}
// Update takes the representation of a roleBinding and updates it. Returns the server's representation of the roleBinding, and an error, if there is any.
func (c *FakeRoleBindings) Update(roleBinding *v1alpha2.RoleBinding) (result *v1alpha2.RoleBinding, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootUpdateAction(rolebindingsResource, roleBinding), &v1alpha2.RoleBinding{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.RoleBinding), err
}
// Delete takes name of the roleBinding and deletes it. Returns an error if one occurs.
func (c *FakeRoleBindings) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewRootDeleteAction(rolebindingsResource, name), &v1alpha2.RoleBinding{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeRoleBindings) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewRootDeleteCollectionAction(rolebindingsResource, listOptions)
_, err := c.Fake.Invokes(action, &v1alpha2.RoleBindingList{})
return err
}
// Patch applies the patch and returns the patched roleBinding.
func (c *FakeRoleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.RoleBinding, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootPatchSubresourceAction(rolebindingsResource, name, pt, data, subresources...), &v1alpha2.RoleBinding{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.RoleBinding), err
}
......@@ -18,4 +18,10 @@ limitations under the License.
package v1alpha2
type PolicyRuleExpansion interface{}
type RoleExpansion interface{}
type RoleBindingExpansion interface{}
type UserExpansion interface{}
......@@ -26,6 +26,9 @@ import (
type IamV1alpha2Interface interface {
RESTClient() rest.Interface
PolicyRulesGetter
RolesGetter
RoleBindingsGetter
UsersGetter
}
......@@ -34,6 +37,18 @@ type IamV1alpha2Client struct {
restClient rest.Interface
}
func (c *IamV1alpha2Client) PolicyRules() PolicyRuleInterface {
return newPolicyRules(c)
}
func (c *IamV1alpha2Client) Roles() RoleInterface {
return newRoles(c)
}
func (c *IamV1alpha2Client) RoleBindings() RoleBindingInterface {
return newRoleBindings(c)
}
func (c *IamV1alpha2Client) Users() UserInterface {
return newUsers(c)
}
......
/*
Copyright 2019 The KubeSphere authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1alpha2
import (
"time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
)
// PolicyRulesGetter has a method to return a PolicyRuleInterface.
// A group's client should implement this interface.
type PolicyRulesGetter interface {
PolicyRules() PolicyRuleInterface
}
// PolicyRuleInterface has methods to work with PolicyRule resources.
type PolicyRuleInterface interface {
Create(*v1alpha2.PolicyRule) (*v1alpha2.PolicyRule, error)
Update(*v1alpha2.PolicyRule) (*v1alpha2.PolicyRule, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*v1alpha2.PolicyRule, error)
List(opts v1.ListOptions) (*v1alpha2.PolicyRuleList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.PolicyRule, err error)
PolicyRuleExpansion
}
// policyRules implements PolicyRuleInterface
type policyRules struct {
client rest.Interface
}
// newPolicyRules returns a PolicyRules
func newPolicyRules(c *IamV1alpha2Client) *policyRules {
return &policyRules{
client: c.RESTClient(),
}
}
// Get takes name of the policyRule, and returns the corresponding policyRule object, and an error if there is any.
func (c *policyRules) Get(name string, options v1.GetOptions) (result *v1alpha2.PolicyRule, err error) {
result = &v1alpha2.PolicyRule{}
err = c.client.Get().
Resource("policyrules").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of PolicyRules that match those selectors.
func (c *policyRules) List(opts v1.ListOptions) (result *v1alpha2.PolicyRuleList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha2.PolicyRuleList{}
err = c.client.Get().
Resource("policyrules").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested policyRules.
func (c *policyRules) Watch(opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Resource("policyrules").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
// Create takes the representation of a policyRule and creates it. Returns the server's representation of the policyRule, and an error, if there is any.
func (c *policyRules) Create(policyRule *v1alpha2.PolicyRule) (result *v1alpha2.PolicyRule, err error) {
result = &v1alpha2.PolicyRule{}
err = c.client.Post().
Resource("policyrules").
Body(policyRule).
Do().
Into(result)
return
}
// Update takes the representation of a policyRule and updates it. Returns the server's representation of the policyRule, and an error, if there is any.
func (c *policyRules) Update(policyRule *v1alpha2.PolicyRule) (result *v1alpha2.PolicyRule, err error) {
result = &v1alpha2.PolicyRule{}
err = c.client.Put().
Resource("policyrules").
Name(policyRule.Name).
Body(policyRule).
Do().
Into(result)
return
}
// Delete takes name of the policyRule and deletes it. Returns an error if one occurs.
func (c *policyRules) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Resource("policyrules").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *policyRules) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Resource("policyrules").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched policyRule.
func (c *policyRules) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.PolicyRule, err error) {
result = &v1alpha2.PolicyRule{}
err = c.client.Patch(pt).
Resource("policyrules").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}
/*
Copyright 2019 The KubeSphere authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1alpha2
import (
"time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
)
// RolesGetter has a method to return a RoleInterface.
// A group's client should implement this interface.
type RolesGetter interface {
Roles() RoleInterface
}
// RoleInterface has methods to work with Role resources.
type RoleInterface interface {
Create(*v1alpha2.Role) (*v1alpha2.Role, error)
Update(*v1alpha2.Role) (*v1alpha2.Role, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*v1alpha2.Role, error)
List(opts v1.ListOptions) (*v1alpha2.RoleList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.Role, err error)
RoleExpansion
}
// roles implements RoleInterface
type roles struct {
client rest.Interface
}
// newRoles returns a Roles
func newRoles(c *IamV1alpha2Client) *roles {
return &roles{
client: c.RESTClient(),
}
}
// Get takes name of the role, and returns the corresponding role object, and an error if there is any.
func (c *roles) Get(name string, options v1.GetOptions) (result *v1alpha2.Role, err error) {
result = &v1alpha2.Role{}
err = c.client.Get().
Resource("roles").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of Roles that match those selectors.
func (c *roles) List(opts v1.ListOptions) (result *v1alpha2.RoleList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha2.RoleList{}
err = c.client.Get().
Resource("roles").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested roles.
func (c *roles) Watch(opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Resource("roles").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
// Create takes the representation of a role and creates it. Returns the server's representation of the role, and an error, if there is any.
func (c *roles) Create(role *v1alpha2.Role) (result *v1alpha2.Role, err error) {
result = &v1alpha2.Role{}
err = c.client.Post().
Resource("roles").
Body(role).
Do().
Into(result)
return
}
// Update takes the representation of a role and updates it. Returns the server's representation of the role, and an error, if there is any.
func (c *roles) Update(role *v1alpha2.Role) (result *v1alpha2.Role, err error) {
result = &v1alpha2.Role{}
err = c.client.Put().
Resource("roles").
Name(role.Name).
Body(role).
Do().
Into(result)
return
}
// Delete takes name of the role and deletes it. Returns an error if one occurs.
func (c *roles) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Resource("roles").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *roles) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Resource("roles").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched role.
func (c *roles) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.Role, err error) {
result = &v1alpha2.Role{}
err = c.client.Patch(pt).
Resource("roles").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}
/*
Copyright 2019 The KubeSphere authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1alpha2
import (
"time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
)
// RoleBindingsGetter has a method to return a RoleBindingInterface.
// A group's client should implement this interface.
type RoleBindingsGetter interface {
RoleBindings() RoleBindingInterface
}
// RoleBindingInterface has methods to work with RoleBinding resources.
type RoleBindingInterface interface {
Create(*v1alpha2.RoleBinding) (*v1alpha2.RoleBinding, error)
Update(*v1alpha2.RoleBinding) (*v1alpha2.RoleBinding, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*v1alpha2.RoleBinding, error)
List(opts v1.ListOptions) (*v1alpha2.RoleBindingList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.RoleBinding, err error)
RoleBindingExpansion
}
// roleBindings implements RoleBindingInterface
type roleBindings struct {
client rest.Interface
}
// newRoleBindings returns a RoleBindings
func newRoleBindings(c *IamV1alpha2Client) *roleBindings {
return &roleBindings{
client: c.RESTClient(),
}
}
// Get takes name of the roleBinding, and returns the corresponding roleBinding object, and an error if there is any.
func (c *roleBindings) Get(name string, options v1.GetOptions) (result *v1alpha2.RoleBinding, err error) {
result = &v1alpha2.RoleBinding{}
err = c.client.Get().
Resource("rolebindings").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of RoleBindings that match those selectors.
func (c *roleBindings) List(opts v1.ListOptions) (result *v1alpha2.RoleBindingList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha2.RoleBindingList{}
err = c.client.Get().
Resource("rolebindings").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested roleBindings.
func (c *roleBindings) Watch(opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Resource("rolebindings").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
// Create takes the representation of a roleBinding and creates it. Returns the server's representation of the roleBinding, and an error, if there is any.
func (c *roleBindings) Create(roleBinding *v1alpha2.RoleBinding) (result *v1alpha2.RoleBinding, err error) {
result = &v1alpha2.RoleBinding{}
err = c.client.Post().
Resource("rolebindings").
Body(roleBinding).
Do().
Into(result)
return
}
// Update takes the representation of a roleBinding and updates it. Returns the server's representation of the roleBinding, and an error, if there is any.
func (c *roleBindings) Update(roleBinding *v1alpha2.RoleBinding) (result *v1alpha2.RoleBinding, err error) {
result = &v1alpha2.RoleBinding{}
err = c.client.Put().
Resource("rolebindings").
Name(roleBinding.Name).
Body(roleBinding).
Do().
Into(result)
return
}
// Delete takes name of the roleBinding and deletes it. Returns an error if one occurs.
func (c *roleBindings) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Resource("rolebindings").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *roleBindings) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Resource("rolebindings").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched roleBinding.
func (c *roleBindings) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.RoleBinding, err error) {
result = &v1alpha2.RoleBinding{}
err = c.client.Patch(pt).
Resource("rolebindings").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}
......@@ -68,6 +68,12 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
return &genericInformer{resource: resource.GroupResource(), informer: f.Devops().V1alpha1().S2iRuns().Informer()}, nil
// Group=iam.kubesphere.io, Version=v1alpha2
case v1alpha2.SchemeGroupVersion.WithResource("policyrules"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Iam().V1alpha2().PolicyRules().Informer()}, nil
case v1alpha2.SchemeGroupVersion.WithResource("roles"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Iam().V1alpha2().Roles().Informer()}, nil
case v1alpha2.SchemeGroupVersion.WithResource("rolebindings"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Iam().V1alpha2().RoleBindings().Informer()}, nil
case v1alpha2.SchemeGroupVersion.WithResource("users"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Iam().V1alpha2().Users().Informer()}, nil
......
......@@ -24,6 +24,12 @@ import (
// Interface provides access to all the informers in this group version.
type Interface interface {
// PolicyRules returns a PolicyRuleInformer.
PolicyRules() PolicyRuleInformer
// Roles returns a RoleInformer.
Roles() RoleInformer
// RoleBindings returns a RoleBindingInformer.
RoleBindings() RoleBindingInformer
// Users returns a UserInformer.
Users() UserInformer
}
......@@ -39,6 +45,21 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// PolicyRules returns a PolicyRuleInformer.
func (v *version) PolicyRules() PolicyRuleInformer {
return &policyRuleInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}
// Roles returns a RoleInformer.
func (v *version) Roles() RoleInformer {
return &roleInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}
// RoleBindings returns a RoleBindingInformer.
func (v *version) RoleBindings() RoleBindingInformer {
return &roleBindingInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}
// Users returns a UserInformer.
func (v *version) Users() UserInformer {
return &userInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
......
/*
Copyright 2019 The KubeSphere authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha2
import (
time "time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces"
v1alpha2 "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2"
)
// PolicyRuleInformer provides access to a shared informer and lister for
// PolicyRules.
type PolicyRuleInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha2.PolicyRuleLister
}
type policyRuleInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewPolicyRuleInformer constructs a new informer for PolicyRule type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewPolicyRuleInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredPolicyRuleInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredPolicyRuleInformer constructs a new informer for PolicyRule type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredPolicyRuleInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.IamV1alpha2().PolicyRules().List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.IamV1alpha2().PolicyRules().Watch(options)
},
},
&iamv1alpha2.PolicyRule{},
resyncPeriod,
indexers,
)
}
func (f *policyRuleInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredPolicyRuleInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *policyRuleInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&iamv1alpha2.PolicyRule{}, f.defaultInformer)
}
func (f *policyRuleInformer) Lister() v1alpha2.PolicyRuleLister {
return v1alpha2.NewPolicyRuleLister(f.Informer().GetIndexer())
}
/*
Copyright 2019 The KubeSphere authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha2
import (
time "time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces"
v1alpha2 "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2"
)
// RoleInformer provides access to a shared informer and lister for
// Roles.
type RoleInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha2.RoleLister
}
type roleInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewRoleInformer constructs a new informer for Role type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewRoleInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredRoleInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredRoleInformer constructs a new informer for Role type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredRoleInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.IamV1alpha2().Roles().List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.IamV1alpha2().Roles().Watch(options)
},
},
&iamv1alpha2.Role{},
resyncPeriod,
indexers,
)
}
func (f *roleInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredRoleInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *roleInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&iamv1alpha2.Role{}, f.defaultInformer)
}
func (f *roleInformer) Lister() v1alpha2.RoleLister {
return v1alpha2.NewRoleLister(f.Informer().GetIndexer())
}
/*
Copyright 2019 The KubeSphere authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
package v1alpha2
import (
time "time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces"
v1alpha2 "kubesphere.io/kubesphere/pkg/client/listers/iam/v1alpha2"
)
// RoleBindingInformer provides access to a shared informer and lister for
// RoleBindings.
type RoleBindingInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha2.RoleBindingLister
}
type roleBindingInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewRoleBindingInformer constructs a new informer for RoleBinding type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewRoleBindingInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredRoleBindingInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredRoleBindingInformer constructs a new informer for RoleBinding type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredRoleBindingInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.IamV1alpha2().RoleBindings().List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.IamV1alpha2().RoleBindings().Watch(options)
},
},
&iamv1alpha2.RoleBinding{},
resyncPeriod,
indexers,
)
}
func (f *roleBindingInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredRoleBindingInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *roleBindingInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&iamv1alpha2.RoleBinding{}, f.defaultInformer)
}
func (f *roleBindingInformer) Lister() v1alpha2.RoleBindingLister {
return v1alpha2.NewRoleBindingLister(f.Informer().GetIndexer())
}
......@@ -18,6 +18,18 @@ limitations under the License.
package v1alpha2
// PolicyRuleListerExpansion allows custom methods to be added to
// PolicyRuleLister.
type PolicyRuleListerExpansion interface{}
// RoleListerExpansion allows custom methods to be added to
// RoleLister.
type RoleListerExpansion interface{}
// RoleBindingListerExpansion allows custom methods to be added to
// RoleBindingLister.
type RoleBindingListerExpansion interface{}
// UserListerExpansion allows custom methods to be added to
// UserLister.
type UserListerExpansion interface{}
/*
Copyright 2019 The KubeSphere authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha2
import (
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
)
// PolicyRuleLister helps list PolicyRules.
type PolicyRuleLister interface {
// List lists all PolicyRules in the indexer.
List(selector labels.Selector) (ret []*v1alpha2.PolicyRule, err error)
// Get retrieves the PolicyRule from the index for a given name.
Get(name string) (*v1alpha2.PolicyRule, error)
PolicyRuleListerExpansion
}
// policyRuleLister implements the PolicyRuleLister interface.
type policyRuleLister struct {
indexer cache.Indexer
}
// NewPolicyRuleLister returns a new PolicyRuleLister.
func NewPolicyRuleLister(indexer cache.Indexer) PolicyRuleLister {
return &policyRuleLister{indexer: indexer}
}
// List lists all PolicyRules in the indexer.
func (s *policyRuleLister) List(selector labels.Selector) (ret []*v1alpha2.PolicyRule, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha2.PolicyRule))
})
return ret, err
}
// Get retrieves the PolicyRule from the index for a given name.
func (s *policyRuleLister) Get(name string) (*v1alpha2.PolicyRule, error) {
obj, exists, err := s.indexer.GetByKey(name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1alpha2.Resource("policyrule"), name)
}
return obj.(*v1alpha2.PolicyRule), nil
}
/*
Copyright 2019 The KubeSphere authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha2
import (
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
)
// RoleLister helps list Roles.
type RoleLister interface {
// List lists all Roles in the indexer.
List(selector labels.Selector) (ret []*v1alpha2.Role, err error)
// Get retrieves the Role from the index for a given name.
Get(name string) (*v1alpha2.Role, error)
RoleListerExpansion
}
// roleLister implements the RoleLister interface.
type roleLister struct {
indexer cache.Indexer
}
// NewRoleLister returns a new RoleLister.
func NewRoleLister(indexer cache.Indexer) RoleLister {
return &roleLister{indexer: indexer}
}
// List lists all Roles in the indexer.
func (s *roleLister) List(selector labels.Selector) (ret []*v1alpha2.Role, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha2.Role))
})
return ret, err
}
// Get retrieves the Role from the index for a given name.
func (s *roleLister) Get(name string) (*v1alpha2.Role, error) {
obj, exists, err := s.indexer.GetByKey(name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1alpha2.Resource("role"), name)
}
return obj.(*v1alpha2.Role), nil
}
/*
Copyright 2019 The KubeSphere authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha2
import (
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
)
// RoleBindingLister helps list RoleBindings.
type RoleBindingLister interface {
// List lists all RoleBindings in the indexer.
List(selector labels.Selector) (ret []*v1alpha2.RoleBinding, err error)
// Get retrieves the RoleBinding from the index for a given name.
Get(name string) (*v1alpha2.RoleBinding, error)
RoleBindingListerExpansion
}
// roleBindingLister implements the RoleBindingLister interface.
type roleBindingLister struct {
indexer cache.Indexer
}
// NewRoleBindingLister returns a new RoleBindingLister.
func NewRoleBindingLister(indexer cache.Indexer) RoleBindingLister {
return &roleBindingLister{indexer: indexer}
}
// List lists all RoleBindings in the indexer.
func (s *roleBindingLister) List(selector labels.Selector) (ret []*v1alpha2.RoleBinding, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha2.RoleBinding))
})
return ret, err
}
// Get retrieves the RoleBinding from the index for a given name.
func (s *roleBindingLister) Get(name string) (*v1alpha2.RoleBinding, error) {
obj, exists, err := s.indexer.GetByKey(name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1alpha2.Resource("rolebinding"), name)
}
return obj.(*v1alpha2.RoleBinding), nil
}
......@@ -30,6 +30,10 @@ import (
"strconv"
)
const (
encryptedAnnotation = "iam.kubesphere.io/password-encrypted"
)
type EmailValidator struct {
Client client.Client
decoder *admission.Decoder
......@@ -51,7 +55,11 @@ func (a *EmailValidator) Handle(ctx context.Context, req admission.Request) admi
allUsers := v1alpha2.UserList{}
a.Client.List(ctx, &v1alpha2.UserList{}, &client.ListOptions{})
err = a.Client.List(ctx, &v1alpha2.UserList{}, &client.ListOptions{})
if err != nil {
return admission.Errored(http.StatusInternalServerError, err)
}
found := emailAlreadyExist(allUsers, email)
......@@ -78,7 +86,7 @@ func (a *PasswordCipher) Handle(ctx context.Context, req admission.Request) admi
return admission.Errored(http.StatusBadRequest, err)
}
encrypted, err := strconv.ParseBool(user.Annotations["iam.kubesphere.io/password-encrypted"])
encrypted, err := strconv.ParseBool(user.Annotations[encryptedAnnotation])
if err != nil || !encrypted {
password, err := hashPassword(user.Spec.EncryptedPassword)
......@@ -86,6 +94,7 @@ func (a *PasswordCipher) Handle(ctx context.Context, req admission.Request) admi
return admission.Errored(http.StatusInternalServerError, err)
}
user.Spec.EncryptedPassword = password
user.Annotations[encryptedAnnotation] = "true"
}
marshaledUser, err := json.Marshal(user)
......
......@@ -2,24 +2,24 @@ package v1alpha2
import (
"github.com/emicklei/go-restful"
"k8s.io/apimachinery/pkg/apis/meta/v1"
"kubesphere.io/kubesphere/pkg/api"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
authoptions "kubesphere.io/kubesphere/pkg/apiserver/authentication/options"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/iam/am"
"kubesphere.io/kubesphere/pkg/models/iam/im"
"kubesphere.io/kubesphere/pkg/simple/client/cache"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
ldappool "kubesphere.io/kubesphere/pkg/simple/client/ldap"
"strings"
)
type iamHandler struct {
amOperator am.AccessManagementInterface
imOperator im.IdentityManagementInterface
am am.AccessManagementInterface
im im.IdentityManagementInterface
}
func newIAMHandler(k8sClient k8s.Client, factory informers.InformerFactory, ldapClient ldappool.Interface, cacheClient cache.Interface, options *authoptions.AuthenticationOptions) *iamHandler {
func newIAMHandler(im im.IdentityManagementInterface, am am.AccessManagementInterface, options *authoptions.AuthenticationOptions) *iamHandler {
return &iamHandler{
amOperator: am.NewAMOperator(k8sClient.Kubernetes(), factory.KubernetesSharedInformerFactory()),
imOperator: im.NewLDAPOperator(ldapClient),
am: am,
im: im,
}
}
......@@ -36,7 +36,22 @@ func (h *iamHandler) ModifyUser(request *restful.Request, response *restful.Resp
}
func (h *iamHandler) DescribeUser(req *restful.Request, resp *restful.Response) {
panic("implement me")
username := req.PathParameter("user")
user, err := h.im.DescribeUser(username)
if err != nil {
api.HandleInternalError(resp, req, err)
return
}
globalRole, err := h.am.GetRoleOfUserInTargetScope(iamv1alpha2.GlobalScope, "", username)
if err != nil {
api.HandleInternalError(resp, req, err)
return
}
result := iamv1alpha2.UserDetail{User: user, GlobalRole: globalRole}
resp.WriteEntity(result)
}
func (h *iamHandler) ListUsers(req *restful.Request, resp *restful.Response) {
......@@ -48,9 +63,39 @@ func (h *iamHandler) ListUserRoles(req *restful.Request, resp *restful.Response)
}
func (h *iamHandler) ListRoles(req *restful.Request, resp *restful.Response) {
panic("implement me")
}
func (h *iamHandler) ListRolesOfUser(req *restful.Request, resp *restful.Response) {
username := req.PathParameter("user")
var roles []iamv1alpha2.Role
var err error
if strings.HasSuffix(req.Request.URL.Path, "workspaceroles") {
roles, err = h.am.ListRolesOfUser(iamv1alpha2.WorkspaceScope, username)
} else if strings.HasSuffix(req.Request.URL.Path, "clusterroles") {
roles, err = h.am.ListRolesOfUser(iamv1alpha2.ClusterScope, username)
} else if strings.HasSuffix(req.Request.URL.Path, "namespaceroles") {
roles, err = h.am.ListRolesOfUser(iamv1alpha2.NamespaceScope, username)
}
if err != nil {
api.HandleInternalError(resp, req, err)
return
}
result := iamv1alpha2.RoleList{
TypeMeta: v1.TypeMeta{
Kind: "List",
APIVersion: "v1",
},
ListMeta: v1.ListMeta{},
Items: roles,
}
resp.WriteEntity(result)
}
func (h *iamHandler) ListClusterRoles(req *restful.Request, resp *restful.Response) {
panic("implement me")
}
......
......@@ -22,15 +22,14 @@ import (
"github.com/emicklei/go-restful-openapi"
"k8s.io/apimachinery/pkg/runtime/schema"
"kubesphere.io/kubesphere/pkg/api"
iamvealpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
authoptions "kubesphere.io/kubesphere/pkg/apiserver/authentication/options"
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/iam/am"
"kubesphere.io/kubesphere/pkg/models/iam/im"
"kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/simple/client/cache"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
ldappool "kubesphere.io/kubesphere/pkg/simple/client/ldap"
"net/http"
)
......@@ -38,19 +37,38 @@ const groupName = "iam.kubesphere.io"
var GroupVersion = schema.GroupVersion{Group: groupName, Version: "v1alpha2"}
func AddToContainer(c *restful.Container, k8sClient k8s.Client, factory informers.InformerFactory, ldapClient ldappool.Interface, cacheClient cache.Interface, options *authoptions.AuthenticationOptions) error {
func AddToContainer(container *restful.Container, im im.IdentityManagementInterface, am am.AccessManagementInterface, options *authoptions.AuthenticationOptions) error {
ws := runtime.NewWebService(GroupVersion)
handler := newIAMHandler(k8sClient, factory, ldapClient, cacheClient, options)
handler := newIAMHandler(im, am, options)
// implemented by create CRD object.
//ws.Route(ws.POST("/users").To(handler.CreateUser))
//ws.Route(ws.DELETE("/users/{user}"))
//ws.Route(ws.PUT("/users/{user}"))
//ws.Route(ws.GET("/users/{user}"))
ws.Route(ws.GET("/users/{user}").
To(handler.DescribeUser).
Doc("Retrieve user details.").
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, iamvealpha2.UserDetail{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/users/{user}/workspaceroles").
To(handler.ListRolesOfUser).
Doc("Retrieve user roles in workspaces.").
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, iamvealpha2.RoleList{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
// TODO move to resources api
//ws.Route(ws.GET("/users"))
ws.Route(ws.GET("/users/{user}/clusterroles").
To(handler.ListRolesOfUser).
Doc("Retrieve user roles in clusters.").
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, iamvealpha2.RoleList{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/users/{user}/namespaceroles").
To(handler.ListRolesOfUser).
Doc("Retrieve user roles in namespaces.").
Param(ws.PathParameter("user", "username")).
Returns(http.StatusOK, api.StatusOK, iamvealpha2.RoleList{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
ws.Route(ws.GET("/namespaces/{namespace}/roles").
To(handler.ListRoles).
......@@ -104,6 +122,6 @@ func AddToContainer(c *restful.Container, k8sClient k8s.Client, factory informer
Returns(http.StatusOK, api.StatusOK, errors.Error{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.AccessManagementTag}))
c.Add(ws)
container.Add(ws)
return nil
}
package v1alpha2
import (
"errors"
"github.com/emicklei/go-restful"
v1 "k8s.io/api/core/v1"
k8serr "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/apiserver/request"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/iam/am"
"kubesphere.io/kubesphere/pkg/models/monitoring"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/tenant"
apierr "kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
"net/http"
)
type tenantHandler struct {
tenant tenant.Interface
am am.AccessManagementInterface
}
func newTenantHandler(k8sClient k8s.Client, factory informers.InformerFactory, db *mysql.Database) *tenantHandler {
func newTenantHandler(k8sClient k8s.Client, factory informers.InformerFactory) *tenantHandler {
return &tenantHandler{
tenant: tenant.New(k8sClient.Kubernetes(), factory.KubernetesSharedInformerFactory(), factory.KubeSphereSharedInformerFactory(), db),
am: am.NewAMOperator(k8sClient.Kubernetes(), factory.KubernetesSharedInformerFactory()),
tenant: tenant.New(k8sClient, factory),
}
}
func (h *tenantHandler) ListWorkspaces(req *restful.Request, resp *restful.Response) {
username := req.HeaderParameter(constants.UserNameHeader)
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, v1alpha2.CreateTime)
limit, offset := params.ParsePaging(req)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true)
conditions, err := params.ParseConditions(req)
user, ok := request.UserFrom(req.Request.Context())
if err != nil {
if !ok {
err := errors.New("cannot obtain user info")
klog.Errorln(err)
api.HandleBadRequest(resp, nil, err)
api.HandleForbidden(resp, nil, err)
return
}
result, err := h.tenant.ListWorkspaces(username, conditions, orderBy, reverse, limit, offset)
result, err := h.tenant.ListWorkspaces(user.GetName())
if err != nil {
api.HandleInternalError(resp, nil, err)
return
}
resp.WriteAsJson(result)
}
func (h *tenantHandler) DescribeWorkspace(req *restful.Request, resp *restful.Response) {
username := req.HeaderParameter(constants.UserNameHeader)
workspaceName := req.PathParameter("workspace")
result, err := h.tenant.DescribeWorkspace(username, workspaceName)
if err != nil {
if k8serr.IsNotFound(err) {
api.HandleNotFound(resp, nil, err)
} else {
api.HandleInternalError(resp, nil, err)
}
return
}
resp.WriteAsJson(result)
resp.WriteEntity(result)
}
func (h *tenantHandler) ListNamespaces(req *restful.Request, resp *restful.Response) {
workspace := req.PathParameter("workspace")
username := req.PathParameter("member")
// /workspaces/{workspace}/members/{username}/namespaces
if username == "" {
// /workspaces/{workspace}/namespaces
username = req.HeaderParameter(constants.UserNameHeader)
}
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, v1alpha2.CreateTime)
limit, offset := params.ParsePaging(req)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true)
conditions, err := params.ParseConditions(req)
if err != nil {
api.HandleBadRequest(resp, nil, err)
return
}
conditions.Match[constants.WorkspaceLabelKey] = workspace
result, err := h.tenant.ListNamespaces(username, conditions, orderBy, reverse, limit, offset)
if err != nil {
api.HandleInternalError(resp, nil, err)
return
}
namespaces := make([]*v1.Namespace, 0)
for _, item := range result.Items {
namespaces = append(namespaces, item.(*v1.Namespace).DeepCopy())
}
namespaces = monitoring.GetNamespacesWithMetrics(namespaces)
items := make([]interface{}, 0)
for _, item := range namespaces {
items = append(items, item)
}
result.Items = items
resp.WriteAsJson(result)
}
func (h *tenantHandler) CreateNamespace(req *restful.Request, resp *restful.Response) {
workspace := req.PathParameter("workspace")
username := req.HeaderParameter(constants.UserNameHeader)
var namespace v1.Namespace
err := req.ReadEntity(&namespace)
if err != nil {
api.HandleNotFound(resp, nil, err)
return
}
_, err = h.tenant.DescribeWorkspace("", workspace)
if err != nil {
if k8serr.IsNotFound(err) {
api.HandleForbidden(resp, nil, err)
} else {
api.HandleInternalError(resp, nil, err)
}
return
}
user, ok := request.UserFrom(req.Request.Context())
created, err := h.tenant.CreateNamespace(workspace, &namespace, username)
if err != nil {
if k8serr.IsAlreadyExists(err) {
resp.WriteHeaderAndEntity(http.StatusConflict, err)
} else {
api.HandleInternalError(resp, nil, err)
}
if !ok {
err := errors.New("cannot obtain user info")
klog.Errorln(err)
api.HandleForbidden(resp, nil, err)
return
}
resp.WriteAsJson(created)
}
func (h *tenantHandler) DeleteNamespace(req *restful.Request, resp *restful.Response) {
workspace := req.PathParameter("workspace")
namespace := req.PathParameter("namespace")
worksapceName := req.PathParameter("workspace")
err := h.tenant.DeleteNamespace(workspace, namespace)
if err != nil {
if k8serr.IsNotFound(err) {
api.HandleNotFound(resp, nil, err)
} else {
api.HandleInternalError(resp, nil, err)
}
return
}
resp.WriteAsJson(apierr.None)
}
func (h *tenantHandler) ListDevopsProjects(req *restful.Request, resp *restful.Response) {
workspace := req.PathParameter("workspace")
username := req.PathParameter("member")
if username == "" {
username = req.HeaderParameter(constants.UserNameHeader)
}
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, v1alpha2.CreateTime)
limit, offset := params.ParsePaging(req)
reverse := params.GetBoolValueWithDefault(req, params.ReverseParam, true)
conditions, err := params.ParseConditions(req)
if err != nil {
api.HandleBadRequest(resp, nil, err)
return
}
conditions.Match["workspace"] = workspace
result, err := h.tenant.ListDevopsProjects(username, conditions, orderBy, reverse, limit, offset)
result, err := h.tenant.ListNamespaces(worksapceName, user.GetName())
if err != nil {
api.HandleInternalError(resp, nil, err)
......@@ -199,41 +63,3 @@ func (h *tenantHandler) ListDevopsProjects(req *restful.Request, resp *restful.R
resp.WriteEntity(result)
}
func (h *tenantHandler) GetDevOpsProjectsCount(req *restful.Request, resp *restful.Response) {
username := req.HeaderParameter(constants.UserNameHeader)
result, err := h.tenant.ListDevopsProjects(username, nil, "", false, 1, 0)
if err != nil {
api.HandleInternalError(resp, nil, err)
return
}
resp.WriteEntity(struct {
Count int `json:"count"`
}{Count: result.TotalCount})
}
func (h *tenantHandler) DeleteDevopsProject(req *restful.Request, resp *restful.Response) {
projectId := req.PathParameter("devops")
workspace := req.PathParameter("workspace")
username := req.HeaderParameter(constants.UserNameHeader)
_, err := h.tenant.DescribeWorkspace("", workspace)
if err != nil {
api.HandleInternalError(resp, req, err)
return
}
err = h.tenant.DeleteDevOpsProject(username, projectId)
if err != nil {
api.HandleInternalError(resp, nil, err)
return
}
resp.WriteEntity(apierr.None)
}
func (h *tenantHandler) CreateDevopsProject(req *restful.Request, resp *restful.Response) {
}
......@@ -23,17 +23,11 @@ import (
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"kubesphere.io/kubesphere/pkg/api"
devopsv1alpha2 "kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
"net/http"
)
......@@ -43,95 +37,28 @@ const (
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
func AddToContainer(c *restful.Container, k8sClient k8s.Client, factory informers.InformerFactory, db *mysql.Database) error {
func AddToContainer(c *restful.Container, k8sClient k8s.Client, factory informers.InformerFactory) error {
ws := runtime.NewWebService(GroupVersion)
handler := newTenantHandler(k8sClient, factory, db)
handler := newTenantHandler(k8sClient, factory)
ws.Route(ws.GET("/workspaces").
To(handler.ListWorkspaces).
Returns(http.StatusOK, api.StatusOK, models.PageableResponse{}).
Doc("List all workspaces that belongs to the current user").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.GET("/workspaces/{workspace}").
To(handler.DescribeWorkspace).
Doc("Describe the specified workspace").
Param(ws.PathParameter("workspace", "workspace name")).
Returns(http.StatusOK, api.StatusOK, v1alpha1.Workspace{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.GET("/workspaces/{workspace}/namespaces").
To(handler.ListNamespaces).
Param(ws.PathParameter("workspace", "workspace name")).
Doc("List the namespaces of the specified workspace for the current user").
Returns(http.StatusOK, api.StatusOK, []v1.Namespace{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.GET("/workspaces/{workspace}/members/{member}/namespaces").
ws.Route(ws.GET("/workspaces/{workspace}/clusters").
To(handler.ListNamespaces).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("member", "workspace member's username")).
Doc("List the namespaces for the workspace member").
Returns(http.StatusOK, api.StatusOK, []v1.Namespace{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.POST("/workspaces/{workspace}/namespaces").
To(handler.CreateNamespace).
Param(ws.PathParameter("workspace", "workspace name")).
Doc("Create a namespace in the specified workspace").
Returns(http.StatusOK, api.StatusOK, []v1.Namespace{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.DELETE("/workspaces/{workspace}/namespaces/{namespace}").
To(handler.DeleteNamespace).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("namespace", "the name of the namespace")).
Doc("Delete the specified namespace from the workspace").
Returns(http.StatusOK, api.StatusOK, errors.Error{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.GET("/workspaces/{workspace}/devops").
To(handler.ListDevopsProjects).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.QueryParameter(params.PagingParam, "page").
Required(false).
DataFormat("limit=%d,page=%d").
DefaultValue("limit=10,page=1")).
Param(ws.QueryParameter(params.ConditionsParam, "query conditions").
Required(false).
DataFormat("key=%s,key~%s")).
Doc("List devops projects for the current user").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.GET("/workspaces/{workspace}/members/{member}/devops").
To(handler.ListDevopsProjects).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("member", "workspace member's username")).
Param(ws.QueryParameter(params.PagingParam, "page").
Required(false).
DataFormat("limit=%d,page=%d").
DefaultValue("limit=10,page=1")).
Param(ws.QueryParameter(params.ConditionsParam, "query conditions").
Required(false).
DataFormat("key=%s,key~%s")).
Returns(http.StatusOK, api.StatusOK, models.PageableResponse{}).
Doc("List the devops projects for the workspace member").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.GET("/devopscount").
To(handler.GetDevOpsProjectsCount).
Returns(http.StatusOK, api.StatusOK, struct {
Count uint32 `json:"count"`
}{}).
Doc("Get the devops projects count for the member").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.POST("/workspaces/{workspace}/devops").
To(handler.CreateDevopsProject).
Param(ws.PathParameter("workspace", "workspace name")).
Doc("Create a devops project in the specified workspace").
Reads(devopsv1alpha2.DevOpsProject{}).
Returns(http.StatusOK, api.StatusOK, devopsv1alpha2.DevOpsProject{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
ws.Route(ws.DELETE("/workspaces/{workspace}/devops/{devops}").
To(handler.DeleteDevopsProject).
Param(ws.PathParameter("workspace", "workspace name")).
Param(ws.PathParameter("devops", "devops project ID")).
Doc("Delete the specified devops project from the workspace").
Returns(http.StatusOK, api.StatusOK, devopsv1alpha2.DevOpsProject{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.TenantResourcesTag}))
c.Add(ws)
return nil
......
......@@ -18,61 +18,118 @@
package am
import (
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/clusterrole"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/resource"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/role"
)
const (
ClusterRoleKind = "ClusterRole"
NamespaceAdminRoleBindName = "admin"
NamespaceViewerRoleBindName = "viewer"
"fmt"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/klog"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
kubesphere "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"net/http"
)
type AccessManagementInterface interface {
GetPlatformRole(username string) (Role, error)
GetClusterRole(cluster, username string) (Role, error)
GetWorkspaceRole(workspace, username string) (Role, error)
GetNamespaceRole(cluster, namespace, username string) (Role, error)
}
type Role interface {
GetName() string
GetRego() string
ListRolesOfUser(scope iamv1alpha2.Scope, username string) ([]iamv1alpha2.Role, error)
GetRoleOfUserInTargetScope(scope iamv1alpha2.Scope, target string, username string) (*iamv1alpha2.Role, error)
GetPolicyRule(name string) (*iamv1alpha2.PolicyRule, error)
}
type amOperator struct {
informers informers.SharedInformerFactory
resources resource.ResourceGetter
kubeClient kubernetes.Interface
informers informers.SharedInformerFactory
ksClient kubesphere.Interface
}
func NewAMOperator(kubeClient kubernetes.Interface, informers informers.SharedInformerFactory) AccessManagementInterface {
resourceGetter := resource.ResourceGetter{}
resourceGetter.Add(v1alpha2.Role, role.NewRoleSearcher(informers))
resourceGetter.Add(v1alpha2.ClusterRoles, clusterrole.NewClusterRoleSearcher(informers))
func NewAMOperator(ksClient kubesphere.Interface, informers informers.SharedInformerFactory) AccessManagementInterface {
return &amOperator{
informers: informers,
resources: resourceGetter,
kubeClient: kubeClient,
informers: informers,
ksClient: ksClient,
}
}
func (am *amOperator) GetPlatformRole(username string) (Role, error) {
panic("implement me")
func containsUser(subjets []iamv1alpha2.Subject, username string) bool {
for _, sub := range subjets {
if sub.Kind == iamv1alpha2.UserKind && sub.Name == username {
return true
}
}
return false
}
func (am *amOperator) GetClusterRole(cluster, username string) (Role, error) {
panic("implement me")
func (am *amOperator) ListRolesOfUser(scope iamv1alpha2.Scope, username string) ([]iamv1alpha2.Role, error) {
lister := am.informers.Iam().V1alpha2().RoleBindings().Lister()
roleBindings, err := lister.List(labels.Everything())
if err != nil {
klog.Error(err)
return nil, err
}
roleBindingsInScope := filterRoleBindingByScope(roleBindings, scope)
roles := make([]iamv1alpha2.Role, 0)
for _, roleBinding := range roleBindingsInScope {
if containsUser(roleBinding.Subjects, username) {
role, err := am.informers.
Iam().V1alpha2().Roles().Lister().Get(roleBinding.RoleRef.Name)
if err != nil {
if errors.IsNotFound(err) {
continue
}
return nil, err
}
roles = append(roles, *role)
}
}
return roles, nil
}
func (am *amOperator) GetWorkspaceRole(workspace, username string) (Role, error) {
panic("implement me")
func filterRoleBindingByScope(roles []*iamv1alpha2.RoleBinding, scope iamv1alpha2.Scope) []*iamv1alpha2.RoleBinding {
result := make([]*iamv1alpha2.RoleBinding, 0)
for _, role := range roles {
if role.Scope == scope {
result = append(result, role)
}
}
return result
}
func (am *amOperator) GetNamespaceRole(cluster, namespace, username string) (Role, error) {
panic("implement me")
func (am *amOperator) GetPolicyRule(name string) (*iamv1alpha2.PolicyRule, error) {
lister := am.informers.Iam().V1alpha2().PolicyRules().Lister()
return lister.Get(name)
}
// Users can only bind one role at each level
func (am *amOperator) GetRoleOfUserInTargetScope(scope iamv1alpha2.Scope, target, username string) (*iamv1alpha2.Role, error) {
roles, err := am.ListRolesOfUser(scope, username)
if err != nil {
klog.Error(err)
return nil, err
}
for _, role := range roles {
if role.Target.Name == iamv1alpha2.TargetAll ||
role.Target.Name == target {
return &role, nil
}
}
err = &errors.StatusError{ErrStatus: metav1.Status{
Status: metav1.StatusFailure,
Code: http.StatusNotFound,
Reason: metav1.StatusReasonNotFound,
Details: &metav1.StatusDetails{
Group: iamv1alpha2.SchemeGroupVersion.Group,
Kind: iamv1alpha2.RoleBindingKind,
},
Message: fmt.Sprintf("role bind not found in %s %s scope", target, scope),
}}
klog.Error(err)
return nil, err
}
/*
*
* Copyright 2020 The KubeSphere Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* /
*/
package am
import (
"encoding/json"
"fmt"
"k8s.io/apiserver/pkg/authentication/user"
"kubesphere.io/kubesphere/pkg/simple/client/cache"
)
type FakeRole struct {
Name string
Rego string
}
type FakeOperator struct {
cache cache.Interface
}
func (f FakeOperator) queryFakeRole(cacheKey string) (Role, error) {
data, err := f.cache.Get(cacheKey)
if err != nil {
if err == cache.ErrNoSuchKey {
return &FakeRole{
Name: "DenyAll",
Rego: "package authz\ndefault allow = false",
}, nil
}
return nil, err
}
var role FakeRole
err = json.Unmarshal([]byte(data), &role)
if err != nil {
return nil, err
}
return role, nil
}
func (f FakeOperator) saveFakeRole(cacheKey string, role FakeRole) error {
data, err := json.Marshal(role)
if err != nil {
return err
}
return f.cache.Set(cacheKey, string(data), 0)
}
func (f FakeOperator) GetPlatformRole(username string) (Role, error) {
return f.queryFakeRole(platformRoleCacheKey(username))
}
func (f FakeOperator) GetClusterRole(cluster, username string) (Role, error) {
return f.queryFakeRole(clusterRoleCacheKey(cluster, username))
}
func (f FakeOperator) GetWorkspaceRole(workspace, username string) (Role, error) {
return f.queryFakeRole(workspaceRoleCacheKey(workspace, username))
}
func (f FakeOperator) GetNamespaceRole(cluster, namespace, username string) (Role, error) {
return f.queryFakeRole(namespaceRoleCacheKey(cluster, namespace, username))
}
func (f FakeOperator) Prepare(platformRoles map[string]FakeRole, clusterRoles map[string]map[string]FakeRole, workspaceRoles map[string]map[string]FakeRole, namespaceRoles map[string]map[string]map[string]FakeRole) {
for username, role := range platformRoles {
f.saveFakeRole(platformRoleCacheKey(username), role)
}
for cluster, roles := range clusterRoles {
for username, role := range roles {
f.saveFakeRole(clusterRoleCacheKey(cluster, username), role)
}
}
for workspace, roles := range workspaceRoles {
for username, role := range roles {
f.saveFakeRole(workspaceRoleCacheKey(workspace, username), role)
}
}
for cluster, nsRoles := range namespaceRoles {
for namespace, roles := range nsRoles {
for username, role := range roles {
f.saveFakeRole(namespaceRoleCacheKey(cluster, namespace, username), role)
}
}
}
}
func namespaceRoleCacheKey(cluster, namespace, username string) string {
return fmt.Sprintf("cluster.%s.namespaces.%s.roles.%s", cluster, namespace, username)
}
func clusterRoleCacheKey(cluster, username string) string {
return fmt.Sprintf("cluster.%s.roles.%s", cluster, username)
}
func workspaceRoleCacheKey(workspace, username string) string {
return fmt.Sprintf("workspace.%s.roles.%s", workspace, username)
}
func platformRoleCacheKey(username string) string {
return fmt.Sprintf("platform.roles.%s", username)
}
func (f FakeRole) GetName() string {
return f.Name
}
func (f FakeRole) GetRego() string {
return f.Rego
}
func NewFakeAMOperator() *FakeOperator {
operator := &FakeOperator{cache: cache.NewSimpleCache()}
operator.saveFakeRole(platformRoleCacheKey("admin"), FakeRole{
Name: "admin",
Rego: "package authz\ndefault allow = true",
})
operator.saveFakeRole(platformRoleCacheKey(user.Anonymous), FakeRole{
Name: "admin",
Rego: `package authz
default allow = false
`,
})
return operator
}
......@@ -46,11 +46,12 @@ func DefaultList(objects []runtime.Object, query *query.Query, compareFunc Compa
return compareFunc(filtered[i], filtered[j], query.SortBy)
})
start, end := query.Pagination.GetValidPagination(len(filtered))
total := len(filtered)
start, end := query.Pagination.GetValidPagination(total)
return &api.ListResult{
Items: objectsToInterfaces(filtered[start:end]),
TotalItems: len(filtered),
Items: objectsToInterfaces(filtered[start:end]),
}
}
......@@ -101,8 +102,6 @@ func DefaultObjectMetaFilter(item metav1.ObjectMeta, filter query.Filter) bool {
// /namespaces?page=1&limit=10&label=kubesphere.io/workspace:system-workspace
case query.FieldLabel:
return containsAnyValue(item.Labels, string(filter.Value))
case query.FieldClusterName:
return strings.Compare(item.ClusterName, string(filter.Value)) == 0
default:
return false
}
......
/*
Copyright 2019 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package tenant
import (
"fmt"
"github.com/emicklei/go-restful"
"github.com/gocraft/dbr"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api/devops/v1alpha2"
"kubesphere.io/kubesphere/pkg/db"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/devops"
"kubesphere.io/kubesphere/pkg/server/params"
dsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
"net/http"
)
type DevOpsProjectOperator interface {
ListDevOpsProjects(workspace, username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error)
CreateDevOpsProject(username string, workspace string, req *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error)
GetDevOpsProjectsCount(username string) (uint32, error)
DeleteDevOpsProject(projectId, username string) error
}
type devopsProjectOperator struct {
ksProjectOperator devops.ProjectOperator
db *mysql.Database
dsProject dsClient.ProjectOperator
}
func newProjectOperator(operator devops.ProjectOperator, db *mysql.Database, client dsClient.ProjectOperator) DevOpsProjectOperator {
return &devopsProjectOperator{
ksProjectOperator: operator,
db: db,
dsProject: client,
}
}
func (o *devopsProjectOperator) ListDevOpsProjects(workspace, username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error) {
query := o.db.Select(devops.GetColumnsFromStructWithPrefix(devops.DevOpsProjectTableName, v1alpha2.DevOpsProject{})...).
From(devops.DevOpsProjectTableName)
var sqconditions []dbr.Builder
sqconditions = append(sqconditions, db.Eq(devops.DevOpsProjectWorkSpaceColumn, workspace))
switch username {
case devops.KS_ADMIN:
default:
onCondition := fmt.Sprintf("%s = %s", devops.ProjectMembershipProjectIdColumn, devops.DevOpsProjectIdColumn)
query.Join(devops.ProjectMembershipTableName, onCondition)
sqconditions = append(sqconditions, db.Eq(devops.ProjectMembershipUsernameColumn, username))
sqconditions = append(sqconditions, db.Eq(
devops.ProjectMembershipTableName+"."+devops.StatusColumn, devops.StatusActive))
}
sqconditions = append(sqconditions, db.Eq(
devops.DevOpsProjectTableName+"."+devops.StatusColumn, devops.StatusActive))
if keyword := conditions.Match["keyword"]; keyword != "" {
sqconditions = append(sqconditions, db.Like(devops.DevOpsProjectNameColumn, keyword))
}
projects := make([]*v1alpha2.DevOpsProject, 0)
if len(sqconditions) > 0 {
query.Where(db.And(sqconditions...))
}
switch orderBy {
case "name":
if reverse {
query.OrderDesc(devops.DevOpsProjectNameColumn)
} else {
query.OrderAsc(devops.DevOpsProjectNameColumn)
}
default:
if reverse {
query.OrderAsc(devops.DevOpsProjectCreateTimeColumn)
} else {
query.OrderDesc(devops.DevOpsProjectCreateTimeColumn)
}
}
query.Limit(uint64(limit))
query.Offset(uint64(offset))
_, err := query.Load(&projects)
if err != nil {
klog.Errorf("%+v", err)
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
}
count, err := query.Count()
if err != nil {
klog.Errorf("%+v", err)
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
}
result := make([]interface{}, 0)
for _, v := range projects {
result = append(result, v)
}
return &models.PageableResponse{Items: result, TotalCount: int(count)}, nil
}
func (o *devopsProjectOperator) GetDevOpsProjectsCount(username string) (uint32, error) {
query := o.db.Select(devops.GetColumnsFromStructWithPrefix(devops.DevOpsProjectTableName, v1alpha2.DevOpsProject{})...).
From(devops.DevOpsProjectTableName)
var sqconditions []dbr.Builder
if username != devops.KS_ADMIN {
onCondition := fmt.Sprintf("%s = %s", devops.ProjectMembershipProjectIdColumn, devops.DevOpsProjectIdColumn)
query.Join(devops.ProjectMembershipTableName, onCondition)
sqconditions = append(sqconditions, db.Eq(devops.ProjectMembershipUsernameColumn, username))
sqconditions = append(sqconditions, db.Eq(
devops.ProjectMembershipTableName+"."+devops.StatusColumn, devops.StatusActive))
}
sqconditions = append(sqconditions, db.Eq(
devops.DevOpsProjectTableName+"."+devops.StatusColumn, devops.StatusActive))
if len(sqconditions) > 0 {
query.Where(db.And(sqconditions...))
}
count, err := query.Count()
if err != nil {
klog.Errorf("%+v", err)
return 0, restful.NewError(http.StatusInternalServerError, err.Error())
}
return count, nil
}
func (o *devopsProjectOperator) DeleteDevOpsProject(projectId, username string) error {
err := o.ksProjectOperator.CheckProjectUserInRole(username, projectId, []string{dsClient.ProjectOwner})
if err != nil {
klog.Errorf("%+v", err)
return restful.NewError(http.StatusForbidden, err.Error())
}
err = o.dsProject.DeleteDevOpsProject(projectId)
if err != nil {
klog.Errorf("%+v", err)
return err
}
_, err = o.db.DeleteFrom(devops.ProjectMembershipTableName).
Where(db.Eq(devops.ProjectMembershipProjectIdColumn, projectId)).Exec()
if err != nil {
klog.Errorf("%+v", err)
return err
}
_, err = o.db.Update(devops.DevOpsProjectTableName).
Set(devops.StatusColumn, devops.StatusDeleted).
Where(db.Eq(devops.DevOpsProjectIdColumn, projectId)).Exec()
if err != nil {
klog.Errorf("%+v", err)
return err
}
project := &v1alpha2.DevOpsProject{}
err = o.db.Select(devops.DevOpsProjectColumns...).
From(devops.DevOpsProjectTableName).
Where(db.Eq(devops.DevOpsProjectIdColumn, projectId)).
LoadOne(project)
if err != nil {
klog.Errorf("%+v", err)
return err
}
return nil
}
func (o *devopsProjectOperator) CreateDevOpsProject(username string, workspace string, req *v1alpha2.DevOpsProject) (*v1alpha2.DevOpsProject, error) {
project := devops.NewDevOpsProject(req.Name, req.Description, username, req.Extra, workspace)
_, err := o.dsProject.CreateDevOpsProject(username, project)
if err != nil {
klog.Error(err)
return nil, err
}
_, err = o.db.InsertInto(devops.DevOpsProjectTableName).
Columns(devops.DevOpsProjectColumns...).Record(project).Exec()
if err != nil {
klog.Errorf("%+v", err)
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
}
projectMembership := devops.NewDevOpsProjectMemberShip(username, project.ProjectId, dsClient.ProjectOwner, username)
_, err = o.db.InsertInto(devops.ProjectMembershipTableName).
Columns(devops.ProjectMembershipColumns...).Record(projectMembership).Exec()
if err != nil {
klog.Errorf("%+v", err)
return nil, restful.NewError(http.StatusInternalServerError, err.Error())
}
return project, nil
}
func (o *devopsProjectOperator) getProjectUserRole(username, projectId string) (string, error) {
if username == devops.KS_ADMIN {
return dsClient.ProjectOwner, nil
}
membership := &dsClient.ProjectMembership{}
err := o.db.Select(devops.ProjectMembershipColumns...).
From(devops.ProjectMembershipTableName).
Where(db.And(
db.Eq(devops.ProjectMembershipUsernameColumn, username),
db.Eq(devops.ProjectMembershipProjectIdColumn, projectId))).LoadOne(membership)
if err != nil {
return "", err
}
return membership.Role, nil
}
/*
Copyright 2019 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package tenant
import (
"k8s.io/api/core/v1"
k8sinformers "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/iam/am"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"strings"
)
type NamespaceInterface interface {
Search(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1.Namespace, error)
CreateNamespace(workspace string, namespace *v1.Namespace, username string) (*v1.Namespace, error)
}
type namespaceSearcher struct {
k8s kubernetes.Interface
informers k8sinformers.SharedInformerFactory
am am.AccessManagementInterface
}
func (s *namespaceSearcher) CreateNamespace(workspace string, namespace *v1.Namespace, username string) (*v1.Namespace, error) {
if namespace.Labels == nil {
namespace.Labels = make(map[string]string, 0)
}
if username != "" {
namespace.Annotations[constants.CreatorAnnotationKey] = username
}
namespace.Labels[constants.WorkspaceLabelKey] = workspace
return s.k8s.CoreV1().Namespaces().Create(namespace)
}
func newNamespaceOperator(k8s kubernetes.Interface, informers k8sinformers.SharedInformerFactory, am am.AccessManagementInterface) NamespaceInterface {
return &namespaceSearcher{k8s: k8s, informers: informers, am: am}
}
func (s *namespaceSearcher) match(match map[string]string, item *v1.Namespace) bool {
for k, v := range match {
switch k {
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !contains(item.Labels, "", v) && !contains(item.Annotations, "", v) {
return false
}
default:
// label not exist or value not equal
if val, ok := item.Labels[k]; !ok || val != v {
return false
}
}
}
return true
}
func (s *namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) bool {
for k, v := range fuzzy {
switch k {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
default:
return false
}
}
return true
}
func (s *namespaceSearcher) compare(a, b *v1.Namespace, orderBy string) bool {
switch orderBy {
case "createTime":
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case "name":
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *namespaceSearcher) GetNamespaces(username string) ([]*v1.Namespace, error) {
panic("implement me")
}
func (s *namespaceSearcher) Search(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1.Namespace, error) {
panic("implement me")
}
......@@ -18,97 +18,147 @@
package tenant
import (
"k8s.io/api/core/v1"
k8sinformers "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/models"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/iam/am"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
)
type Interface interface {
CreateNamespace(workspace string, namespace *v1.Namespace, username string) (*v1.Namespace, error)
DeleteNamespace(workspace, namespace string) error
DescribeWorkspace(username, workspace string) (*v1alpha1.Workspace, error)
ListWorkspaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error)
ListNamespaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error)
ListDevopsProjects(username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error)
CountDevOpsProjects(username string) (uint32, error)
DeleteDevOpsProject(username, projectId string) error
ListWorkspaces(username string) (*api.ListResult, error)
ListNamespaces(username, workspace string) (*api.ListResult, error)
}
type tenantOperator struct {
workspaces WorkspaceInterface
namespaces NamespaceInterface
am am.AccessManagementInterface
devops DevOpsProjectOperator
informers informers.InformerFactory
am am.AccessManagementInterface
}
func (t *tenantOperator) CountDevOpsProjects(username string) (uint32, error) {
return t.devops.GetDevOpsProjectsCount(username)
func New(k8sClient k8s.Client, informers informers.InformerFactory) Interface {
return &tenantOperator{
informers: informers,
am: am.NewAMOperator(k8sClient.KubeSphere(), informers.KubeSphereSharedInformerFactory()),
}
}
func (t *tenantOperator) DeleteDevOpsProject(username, projectId string) error {
return t.devops.DeleteDevOpsProject(projectId, username)
}
func (t *tenantOperator) ListWorkspaces(username string) (*api.ListResult, error) {
func (t *tenantOperator) GetUserDevopsSimpleRules(username string, projectId string) (interface{}, error) {
panic("implement me")
}
workspaceRoles, err := t.am.ListRolesOfUser(iamv1alpha2.WorkspaceScope, username)
if err != nil {
klog.Error(err)
return nil, err
}
func (t *tenantOperator) ListDevopsProjects(username string, conditions *params.Conditions, orderBy string, reverse bool, limit int, offset int) (*models.PageableResponse, error) {
return t.devops.ListDevOpsProjects(conditions.Match["workspace"], username, conditions, orderBy, reverse, limit, offset)
}
workspaces := make([]*tenantv1alpha1.Workspace, 0)
func (t *tenantOperator) DeleteNamespace(workspace, namespace string) error {
return t.workspaces.DeleteNamespace(workspace, namespace)
}
for _, role := range workspaceRoles {
func New(client kubernetes.Interface, informers k8sinformers.SharedInformerFactory, ksinformers ksinformers.SharedInformerFactory, db *mysql.Database) Interface {
amOperator := am.NewAMOperator(client, informers)
return &tenantOperator{
workspaces: newWorkspaceOperator(client, informers, ksinformers, amOperator, db),
namespaces: newNamespaceOperator(client, informers, amOperator),
am: amOperator,
// all workspaces are allowed
if role.Target.Name == iamv1alpha2.TargetAll {
workspaces, err = t.informers.KubeSphereSharedInformerFactory().
Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
break
}
workspace, err := t.informers.KubeSphereSharedInformerFactory().
Tenant().V1alpha1().Workspaces().Lister().Get(role.Target.Name)
if errors.IsNotFound(err) {
klog.Warningf("workspace role: %s found but workspace not exist", role.Target)
continue
}
if err != nil {
klog.Error(err)
return nil, err
}
if !containsWorkspace(workspaces, workspace) {
workspaces = append(workspaces, workspace)
}
}
}
func (t *tenantOperator) CreateNamespace(workspaceName string, namespace *v1.Namespace, username string) (*v1.Namespace, error) {
return t.namespaces.CreateNamespace(workspaceName, namespace, username)
return &api.ListResult{
TotalItems: len(workspaces),
Items: workspacesToInterfaces(workspaces),
}, nil
}
func (t *tenantOperator) DescribeWorkspace(username, workspaceName string) (*v1alpha1.Workspace, error) {
workspace, err := t.workspaces.GetWorkspace(workspaceName)
func (t *tenantOperator) ListNamespaces(username, workspace string) (*api.ListResult, error) {
namespaceRoles, err := t.am.ListRolesOfUser(iamv1alpha2.NamespaceScope, username)
if err != nil {
klog.Error(err)
return nil, err
}
return workspace, nil
}
namespaces := make([]*corev1.Namespace, 0)
func (t *tenantOperator) ListWorkspaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
panic("implement me")
}
for _, role := range namespaceRoles {
func (t *tenantOperator) ListNamespaces(username string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
// all workspaces are allowed
if role.Target.Name == iamv1alpha2.TargetAll {
namespaces, err = t.informers.KubernetesSharedInformerFactory().
Core().V1().Namespaces().Lister().List(labels.Everything())
break
}
namespaces, err := t.namespaces.Search(username, conditions, orderBy, reverse)
namespace, err := t.informers.KubernetesSharedInformerFactory().
Core().V1().Namespaces().Lister().Get(role.Target.Name)
if err != nil {
return nil, err
if errors.IsNotFound(err) {
klog.Warningf("workspace role: %s found but workspace not exist", role.Target)
continue
}
if err != nil {
klog.Error(err)
return nil, err
}
if !containsNamespace(namespaces, namespace) {
namespaces = append(namespaces, namespace)
}
}
return &api.ListResult{
TotalItems: len(namespaces),
Items: namespacesToInterfaces(namespaces),
}, nil
}
func containsWorkspace(workspaces []*tenantv1alpha1.Workspace, workspace *tenantv1alpha1.Workspace) bool {
for _, item := range workspaces {
if item.Name == workspace.Name {
return true
}
}
return false
}
// limit offset
result := make([]interface{}, 0)
for i, v := range namespaces {
if len(result) < limit && i >= offset {
result = append(result, v)
func containsNamespace(namespaces []*corev1.Namespace, namespace *corev1.Namespace) bool {
for _, item := range namespaces {
if item.Name == namespace.Name {
return true
}
}
return false
}
return &models.PageableResponse{Items: result, TotalCount: len(namespaces)}, nil
func workspacesToInterfaces(workspaces []*tenantv1alpha1.Workspace) []interface{} {
ret := make([]interface{}, len(workspaces))
for index, v := range workspaces {
ret[index] = v
}
return ret
}
func namespacesToInterfaces(namespaces []*corev1.Namespace) []interface{} {
ret := make([]interface{}, len(namespaces))
for index, v := range namespaces {
ret[index] = v
}
return ret
}
/*
*
* Copyright 2020 The KubeSphere Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* /
*/
package tenant
import (
core "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/apis/iam/v1alpha2"
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/db"
"kubesphere.io/kubesphere/pkg/models/devops"
"kubesphere.io/kubesphere/pkg/models/iam/am"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"strings"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
)
type InWorkspaceUser struct {
*iamv1alpha2.User
WorkspaceRole string `json:"workspaceRole"`
}
type WorkspaceInterface interface {
GetWorkspace(workspace string) (*v1alpha1.Workspace, error)
SearchWorkspace(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1alpha1.Workspace, error)
ListNamespaces(workspace string) ([]*core.Namespace, error)
DeleteNamespace(workspace, namespace string) error
RemoveUser(user, workspace string) error
AddUser(workspace string, user *InWorkspaceUser) error
CountDevopsProjectsInWorkspace(workspace string) (int, error)
CountUsersInWorkspace(workspace string) (int, error)
CountOrgRoles() (int, error)
CountWorkspaces() (int, error)
CountNamespacesInWorkspace(workspace string) (int, error)
}
type workspaceOperator struct {
client kubernetes.Interface
informers informers.SharedInformerFactory
ksInformers externalversions.SharedInformerFactory
am am.AccessManagementInterface
// TODO: use db interface instead of mysql client
// we can refactor this after rewrite devops using crd
db *mysql.Database
}
func newWorkspaceOperator(client kubernetes.Interface, informers informers.SharedInformerFactory, ksinformers externalversions.SharedInformerFactory, am am.AccessManagementInterface, db *mysql.Database) WorkspaceInterface {
return &workspaceOperator{
client: client,
informers: informers,
ksInformers: ksinformers,
am: am,
db: db,
}
}
func (w *workspaceOperator) ListNamespaces(workspace string) ([]*core.Namespace, error) {
namespaces, err := w.informers.Core().V1().Namespaces().Lister().List(labels.SelectorFromSet(labels.Set{constants.WorkspaceLabelKey: workspace}))
if err != nil {
return nil, err
}
return namespaces, nil
}
func (w *workspaceOperator) DeleteNamespace(workspace string, namespace string) error {
ns, err := w.informers.Core().V1().Namespaces().Lister().Get(namespace)
if err != nil {
return err
}
if ns.Labels[constants.WorkspaceLabelKey] == workspace {
deletePolicy := metav1.DeletePropagationBackground
return w.client.CoreV1().Namespaces().Delete(namespace, &metav1.DeleteOptions{PropagationPolicy: &deletePolicy})
} else {
return apierrors.NewNotFound(schema.GroupResource{Group: "", Resource: "workspace"}, workspace)
}
}
func (w *workspaceOperator) RemoveUser(workspace string, username string) error {
panic("implement me")
}
func (w *workspaceOperator) AddUser(workspaceName string, user *InWorkspaceUser) error {
panic("implement me")
}
func (w *workspaceOperator) CountDevopsProjectsInWorkspace(workspaceName string) (int, error) {
query := w.db.Select(devops.DevOpsProjectIdColumn).
From(devops.DevOpsProjectTableName).
Where(db.And(db.Eq(devops.DevOpsProjectWorkSpaceColumn, workspaceName),
db.Eq(devops.StatusColumn, devops.StatusActive)))
devOpsProjects := make([]string, 0)
if _, err := query.Load(&devOpsProjects); err != nil {
return 0, err
}
return len(devOpsProjects), nil
}
func (w *workspaceOperator) CountUsersInWorkspace(workspace string) (int, error) {
count, err := w.CountUsersInWorkspace(workspace)
if err != nil {
return 0, err
}
return count, nil
}
func (w *workspaceOperator) CountOrgRoles() (int, error) {
return len(constants.WorkSpaceRoles), nil
}
func (w *workspaceOperator) CountNamespacesInWorkspace(workspace string) (int, error) {
ns, err := w.ListNamespaces(workspace)
if err != nil {
return 0, err
}
return len(ns), nil
}
func (*workspaceOperator) match(match map[string]string, item *v1alpha1.Workspace) bool {
for k, v := range match {
switch k {
case v1alpha2.Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !contains(item.Labels, "", v) && !contains(item.Annotations, "", v) {
return false
}
default:
// label not exist or value not equal
if val, ok := item.Labels[k]; !ok || val != v {
return false
}
}
}
return true
}
func (*workspaceOperator) fuzzy(fuzzy map[string]string, item *v1alpha1.Workspace) bool {
for k, v := range fuzzy {
switch k {
case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
default:
return false
}
}
return true
}
func (*workspaceOperator) compare(a, b *v1alpha1.Workspace, orderBy string) bool {
switch orderBy {
case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case v1alpha2.Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (w *workspaceOperator) SearchWorkspace(username string, conditions *params.Conditions, orderBy string, reverse bool) ([]*v1alpha1.Workspace, error) {
panic("implement me")
}
func (w *workspaceOperator) GetWorkspace(workspaceName string) (*v1alpha1.Workspace, error) {
return w.ksInformers.Tenant().V1alpha1().Workspaces().Lister().Get(workspaceName)
}
func contains(m map[string]string, key, value string) bool {
for k, v := range m {
if key == "" {
if strings.Contains(k, value) || strings.Contains(v, value) {
return true
}
} else if k == key && strings.Contains(v, value) {
return true
}
}
return false
}
/*
// TODO: move to metrics package
func GetAllProjectNums() (int, error) {
namespaceLister := informers.SharedInformerFactory().Core().V1().Namespaces().Lister()
list, err := namespaceLister.List(labels.Everything())
if err != nil {
return 0, err
}
return len(list), nil
}
func GetAllDevOpsProjectsNums() (int, error) {
_, err := clientset.ClientSets().Devops()
if _, notEnabled := err.(clientset.ClientSetNotEnabledError); notEnabled {
return 0, err
}
dbconn, err := clientset.ClientSets().MySQL()
if err != nil {
return 0, err
}
query := dbconn.Select(devops.DevOpsProjectIdColumn).
From(devops.DevOpsProjectTableName).
Where(db.Eq(devops.StatusColumn, devops.StatusActive))
devOpsProjects := make([]string, 0)
if _, err := query.Load(&devOpsProjects); err != nil {
return 0, err
}
return len(devOpsProjects), nil
}
*/
func (w *workspaceOperator) CountWorkspaces() (int, error) {
ws, err := w.ksInformers.Tenant().V1alpha1().Workspaces().Lister().List(labels.Everything())
if err != nil {
return 0, err
}
return len(ws), nil
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册