Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion actions/auth/authprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
v3 "github.com/rancher/shepherd/clients/rancher/generated/management/v3"
"github.com/rancher/shepherd/extensions/defaults"
"github.com/rancher/shepherd/pkg/session"
rbacapi "github.com/rancher/tests/actions/kubeapi/rbac"
"github.com/rancher/tests/actions/rbac"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -218,7 +219,7 @@ func UpdateAccessMode(client *rancher.Client, providerName, accessMode string, a
// SetupRequiredAccessModePrincipals creates cluster role binding and prepares principal IDs for required access mode tests
func SetupRequiredAccessModePrincipals(authAdmin *rancher.Client, clusterID string, authConfig *AuthConfig, providerName, userSearchBase, groupSearchBase string) ([]string, error) {
groupPrincipalID := GetGroupPrincipalID(providerName, authConfig.Group, userSearchBase, groupSearchBase)
_, err := rbac.CreateGroupClusterRoleTemplateBinding(authAdmin, clusterID, groupPrincipalID, rbac.ClusterMember.String())
_, err := rbacapi.CreateGroupClusterRoleTemplateBinding(authAdmin, clusterID, groupPrincipalID, rbac.ClusterMember.String())
if err != nil {
return nil, fmt.Errorf("failed to create cluster role binding: %w", err)
}
Expand Down
7 changes: 5 additions & 2 deletions actions/kubeapi/clusters/clusters.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ package clusters
import (
"github.com/rancher/shepherd/clients/rancher"
"github.com/rancher/shepherd/pkg/wrangler"
rbacapi "github.com/rancher/tests/actions/kubeapi/rbac"
)

const (
LocalCluster = "local"
)

// GetClusterWranglerContext returns the context for the cluster
func GetClusterWranglerContext(client *rancher.Client, clusterID string) (*wrangler.Context, error) {
if clusterID == rbacapi.LocalCluster {
if clusterID == LocalCluster {
return client.WranglerContext, nil
}

Expand Down
4 changes: 2 additions & 2 deletions actions/kubeapi/projects/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import (

"github.com/rancher/shepherd/clients/rancher"
"github.com/rancher/shepherd/extensions/defaults"
rbacapi "github.com/rancher/tests/actions/kubeapi/rbac"
clusterapi "github.com/rancher/tests/actions/kubeapi/clusters"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kwait "k8s.io/apimachinery/pkg/util/wait"
)

// DeleteProject is a helper function that uses the dynamic client to delete a Project from a cluster.
func DeleteProject(client *rancher.Client, projectNamespace string, projectName string) error {
dynamicClient, err := client.GetDownStreamClusterClient(rbacapi.LocalCluster)
dynamicClient, err := client.GetDownStreamClusterClient(clusterapi.LocalCluster)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions actions/kubeapi/projects/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import (
v3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"
"github.com/rancher/shepherd/clients/rancher"
"github.com/rancher/shepherd/pkg/api/scheme"
rbacapi "github.com/rancher/tests/actions/kubeapi/rbac"
clusterapi "github.com/rancher/tests/actions/kubeapi/clusters"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// ListProjects is a helper function that uses the dynamic client to list projects in a cluster.
func ListProjects(client *rancher.Client, namespace string, listOpt metav1.ListOptions) (*v3.ProjectList, error) {
dynamicClient, err := client.GetDownStreamClusterClient(rbacapi.LocalCluster)
dynamicClient, err := client.GetDownStreamClusterClient(clusterapi.LocalCluster)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions actions/kubeapi/projects/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import (
"github.com/rancher/shepherd/clients/rancher"
"github.com/rancher/shepherd/extensions/unstructured"
"github.com/rancher/shepherd/pkg/api/scheme"
rbacapi "github.com/rancher/tests/actions/kubeapi/rbac"
clusterapi "github.com/rancher/tests/actions/kubeapi/clusters"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// UpdateProject is a helper function that uses the dynamic client to update a project in a cluster.
func UpdateProject(client *rancher.Client, existingProject *v3.Project, updatedProject *v3.Project) (*v3.Project, error) {
dynamicClient, err := client.GetDownStreamClusterClient(rbacapi.LocalCluster)
dynamicClient, err := client.GetDownStreamClusterClient(clusterapi.LocalCluster)
if err != nil {
return nil, err
}
Expand Down
201 changes: 165 additions & 36 deletions actions/kubeapi/rbac/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,20 @@ package rbac

import (
"context"
"fmt"

v3 "github.com/rancher/rancher/pkg/apis/management.cattle.io/v3"
"github.com/rancher/shepherd/clients/rancher"
management "github.com/rancher/shepherd/clients/rancher/generated/management/v3"
"github.com/rancher/shepherd/extensions/defaults"
extauthz "github.com/rancher/shepherd/extensions/kubeapi/authorization"
"github.com/rancher/shepherd/extensions/unstructured"
"github.com/rancher/shepherd/pkg/api/scheme"
namegen "github.com/rancher/shepherd/pkg/namegenerator"
clusterapi "github.com/rancher/tests/actions/kubeapi/clusters"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kwait "k8s.io/apimachinery/pkg/util/wait"
)

// CreateRole is a helper function that uses the dynamic client to create a role on a namespace for a specific cluster.
Expand Down Expand Up @@ -72,7 +79,7 @@ func CreateRoleBinding(client *rancher.Client, clusterName, roleBindingName, nam

// CreateGlobalRole is a helper function that uses the dynamic client to create a global role in the local cluster.
func CreateGlobalRole(client *rancher.Client, globalRole *v3.GlobalRole) (*v3.GlobalRole, error) {
dynamicClient, err := client.GetDownStreamClusterClient(LocalCluster)
dynamicClient, err := client.GetDownStreamClusterClient(clusterapi.LocalCluster)
if err != nil {
return nil, err
}
Expand All @@ -92,91 +99,213 @@ func CreateGlobalRole(client *rancher.Client, globalRole *v3.GlobalRole) (*v3.Gl
return newGlobalRole, nil
}

// CreateGlobalRoleBinding is a helper function that uses the dynamic client to create a global role binding for a specific user.
func CreateGlobalRoleBinding(client *rancher.Client, globalRoleBinding *v3.GlobalRoleBinding) (*v3.GlobalRoleBinding, error) {
dynamicClient, err := client.GetDownStreamClusterClient(LocalCluster)
// CreateGlobalRoleBinding creates a global role binding for the user with the provided global role using wrangler context
func CreateGlobalRoleBinding(client *rancher.Client, globalRoleName, userName, groupPrincipalName, userPrincipalName string) (*v3.GlobalRoleBinding, error) {
grbObj := &v3.GlobalRoleBinding{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "grb-",
},
UserName: userName,
GroupPrincipalName: groupPrincipalName,
UserPrincipalName: userPrincipalName,
GlobalRoleName: globalRoleName,
}

grb, err := client.WranglerContext.Mgmt.GlobalRoleBinding().Create(grbObj)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to create global role binding for global role %s: %w", globalRoleName, err)
}

globalRoleBindingResource := dynamicClient.Resource(GlobalRoleBindingGroupVersionResource)
unstructuredResp, err := globalRoleBindingResource.Create(context.TODO(), unstructured.MustToUnstructured(globalRoleBinding), metav1.CreateOptions{})
err = WaitForGrbExistence(client, grb.Name)
if err != nil {
return nil, err
}

newGlobalRoleBinding := &v3.GlobalRoleBinding{}
err = scheme.Scheme.Convert(unstructuredResp, newGlobalRoleBinding, unstructuredResp.GroupVersionKind())
return grb, nil
}

// WaitForGrbExistence waits until the GlobalRoleBinding exists based on the provided field (User, UserPrincipal, or Group)
func WaitForGrbExistence(client *rancher.Client, grbName string) error {
return kwait.PollUntilContextTimeout(context.TODO(), defaults.FiveSecondTimeout, defaults.OneMinuteTimeout, false, func(ctx context.Context) (bool, error) {
_, err := client.WranglerContext.Mgmt.GlobalRoleBinding().Get(grbName, metav1.GetOptions{})
if err != nil {
return false, nil
}
return true, nil
})
}

// CreateRoleTemplate creates a cluster or project role template with the provided rules using wrangler context
func CreateRoleTemplate(client *rancher.Client, context string, rules []rbacv1.PolicyRule, inheritedRoleTemplates []*v3.RoleTemplate, external, locked bool, externalRules []rbacv1.PolicyRule) (*v3.RoleTemplate, error) {
var roleTemplateNames []string
for _, inheritedRole := range inheritedRoleTemplates {
if inheritedRole != nil {
roleTemplateNames = append(roleTemplateNames, inheritedRole.Name)
}
}

displayName := namegen.AppendRandomString("role-template")

roleTemplate := &v3.RoleTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: displayName,
},
Context: context,
Rules: rules,
DisplayName: displayName,
RoleTemplateNames: roleTemplateNames,
External: external,
ExternalRules: externalRules,
Locked: locked,
}

createdRoleTemplate, err := client.WranglerContext.Mgmt.RoleTemplate().Create(roleTemplate)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to create RoleTemplate: %w", err)
}

return newGlobalRoleBinding, nil
return GetRoleTemplateByName(client, createdRoleTemplate.Name)
}

// CreateRoleTemplate is a helper function that uses the dynamic client to create a cluster/project role template for a specific user
func CreateRoleTemplate(client *rancher.Client, roleTemplate *v3.RoleTemplate) (*v3.RoleTemplate, error) {
dynamicClient, err := client.GetDownStreamClusterClient(LocalCluster)
// CreateClusterRoleTemplateBinding creates a cluster role template binding for the user with the provided role template using wrangler context
func CreateClusterRoleTemplateBinding(client *rancher.Client, clusterID string, user *management.User, roleTemplateID string) (*v3.ClusterRoleTemplateBinding, error) {
crtbObj := &v3.ClusterRoleTemplateBinding{
ObjectMeta: metav1.ObjectMeta{
Namespace: clusterID,
GenerateName: "crtb-",
},
ClusterName: clusterID,
UserName: user.ID,
RoleTemplateName: roleTemplateID,
}

crtb, err := client.WranglerContext.Mgmt.ClusterRoleTemplateBinding().Create(crtbObj)
if err != nil {
return nil, err
}

roleTemplateResource := dynamicClient.Resource(RoleTemplateGroupVersionResource)
unstructuredResp, err := roleTemplateResource.Create(context.Background(), unstructured.MustToUnstructured(roleTemplate), metav1.CreateOptions{})
err = WaitForCrtbStatus(client, crtb.Namespace, crtb.Name)
if err != nil {
return nil, err
}

newRoleTemplate := &v3.RoleTemplate{}
err = scheme.Scheme.Convert(unstructuredResp, newRoleTemplate, unstructuredResp.GroupVersionKind())
userClient, err := client.AsUser(user)
if err != nil {
return nil, fmt.Errorf("client as user %s: %w", user.Name, err)
}

err = extauthz.WaitForAllowed(userClient, clusterID, nil)
if err != nil {
return nil, err
}

return newRoleTemplate, nil
return crtb, nil
}

// CreateProjectRoleTemplateBinding is a helper function that uses the dynamic client to create a project role template binding in the local cluster.
func CreateProjectRoleTemplateBinding(client *rancher.Client, prtb *v3.ProjectRoleTemplateBinding) (*v3.ProjectRoleTemplateBinding, error) {
dynamicClient, err := client.GetDownStreamClusterClient(LocalCluster)
// CreateProjectRoleTemplateBinding creates a project role template binding for the user with the provided role template using wrangler context
func CreateProjectRoleTemplateBinding(client *rancher.Client, user *management.User, project *v3.Project, roleTemplateID string) (*v3.ProjectRoleTemplateBinding, error) {
projectName := fmt.Sprintf("%s:%s", project.Namespace, project.Name)

prtbNamespace := project.Name
if project.Status.BackingNamespace != "" {
prtbNamespace = fmt.Sprintf("%s-%s", project.Spec.ClusterName, project.Name)
}

prtbObj := &v3.ProjectRoleTemplateBinding{
ObjectMeta: metav1.ObjectMeta{
Namespace: prtbNamespace,
GenerateName: "prtb-",
},
ProjectName: projectName,
UserName: user.ID,
RoleTemplateName: roleTemplateID,
}

prtbObj, err := client.WranglerContext.Mgmt.ProjectRoleTemplateBinding().Create(prtbObj)
if err != nil {
return nil, err
}

projectRoleTemplateBindingResource := dynamicClient.Resource(ProjectRoleTemplateBindingGroupVersionResource).Namespace(prtb.Namespace)
unstructuredResp, err := projectRoleTemplateBindingResource.Create(context.TODO(), unstructured.MustToUnstructured(prtb), metav1.CreateOptions{})
prtb, err := WaitForPrtbExistence(client, project, prtbObj, user)

if err != nil {
return nil, err
}

newprtb := &v3.ProjectRoleTemplateBinding{}
err = scheme.Scheme.Convert(unstructuredResp, newprtb, unstructuredResp.GroupVersionKind())
userClient, err := client.AsUser(user)
if err != nil {
return nil, fmt.Errorf("client as user %s: %w", user.Name, err)
}

err = extauthz.WaitForAllowed(userClient, project.Namespace, nil)
if err != nil {
return nil, err
}

return newprtb, nil
return prtb, nil
}

// CreateClusterRoleTemplateBinding is a helper function that uses the dynamic client to create a cluster role template binding for a specific user
// in the given downstream cluster.
func CreateClusterRoleTemplateBinding(client *rancher.Client, crtb *v3.ClusterRoleTemplateBinding) (*v3.ClusterRoleTemplateBinding, error) {
dynamicClient, err := client.GetDownStreamClusterClient(LocalCluster)
// CreateGroupClusterRoleTemplateBinding creates Cluster Role Template bindings
func CreateGroupClusterRoleTemplateBinding(client *rancher.Client, clusterID string, groupPrincipalID string, roleTemplateID string) (*v3.ClusterRoleTemplateBinding, error) {
crtbObj := &v3.ClusterRoleTemplateBinding{
ObjectMeta: metav1.ObjectMeta{
Namespace: clusterID,
GenerateName: "crtb-",
Annotations: map[string]string{
"field.cattle.io/creatorId": client.UserID,
},
},
ClusterName: clusterID,
GroupPrincipalName: groupPrincipalID,
RoleTemplateName: roleTemplateID,
}

crtb, err := client.WranglerContext.Mgmt.ClusterRoleTemplateBinding().Create(crtbObj)
if err != nil {
return nil, err
}

clusterRoleTemplateBindingResource := dynamicClient.Resource(ClusterRoleTemplateBindingGroupVersionResource).Namespace(crtb.Namespace)
unstructuredResp, err := clusterRoleTemplateBindingResource.Create(context.Background(), unstructured.MustToUnstructured(crtb), metav1.CreateOptions{})
err = WaitForCrtbStatus(client, crtb.Namespace, crtb.Name)
if err != nil {
return nil, err
}

newClusterRoleTemplateBinding := &v3.ClusterRoleTemplateBinding{}
err = scheme.Scheme.Convert(unstructuredResp, newClusterRoleTemplateBinding, unstructuredResp.GroupVersionKind())
return crtb, nil
}

// CreateGroupProjectRoleTemplateBinding creates Project Role Template bindings for groups
func CreateGroupProjectRoleTemplateBinding(client *rancher.Client, projectID string, projectNamespace string, groupPrincipalID string, roleTemplateID string) (*v3.ProjectRoleTemplateBinding, error) {
prtbObj := &v3.ProjectRoleTemplateBinding{
ObjectMeta: metav1.ObjectMeta{
Namespace: projectNamespace,
GenerateName: "prtb-",
},
ProjectName: projectID,
GroupPrincipalName: groupPrincipalID,
RoleTemplateName: roleTemplateID,
}

prtb, err := client.WranglerContext.Mgmt.ProjectRoleTemplateBinding().Create(prtbObj)
if err != nil {
return nil, err
}

return newClusterRoleTemplateBinding, nil
return prtb, nil
}

// CreateGlobalRoleWithInheritedClusterRolesWrangler creates a global role with inherited cluster roles
func CreateGlobalRoleWithInheritedClusterRolesWrangler(client *rancher.Client, inheritedRoles []string) (*v3.GlobalRole, error) {
globalRole := v3.GlobalRole{
ObjectMeta: metav1.ObjectMeta{
Name: namegen.AppendRandomString("testgr"),
},
InheritedClusterRoles: inheritedRoles,
}

createdGlobalRole, err := client.WranglerContext.Mgmt.GlobalRole().Create(&globalRole)
if err != nil {
return nil, fmt.Errorf("failed to create global role with inherited cluster roles: %w", err)
}

return createdGlobalRole, nil
}
Loading