Skip to content
Merged
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
4 changes: 1 addition & 3 deletions pkg/auth/roleTemplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ func (r *RoleTemplateResolver) RulesFromTemplate(roleTemplate *rancherv3.RoleTem
func (r *RoleTemplateResolver) gatherRules(roleTemplate *rancherv3.RoleTemplate, rules []rbacv1.PolicyRule, seen map[string]bool) ([]rbacv1.PolicyRule, error) {
seen[roleTemplate.Name] = true

// Rules from external RoleTemplate are granted by Rancher no matter what
// is the value of .context
if roleTemplate.External {
if roleTemplate.External && roleTemplate.Context == "cluster" {
cr, err := r.clusterRoles.Get(roleTemplate.Name)
if err != nil {
return nil, fmt.Errorf("failed to get clusterRoles '%s': %w", roleTemplate.Name, err)
Expand Down
199 changes: 16 additions & 183 deletions pkg/auth/roleTemplate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,14 @@ func (r Rules) Equal(r2 Rules) bool {

type RoleTemplateResolverSuite struct {
suite.Suite
adminRT *apisv3.RoleTemplate
readNodesRT *apisv3.RoleTemplate
writeNodesRT *apisv3.RoleTemplate
inheritedRT *apisv3.RoleTemplate
externalClusterRT *apisv3.RoleTemplate
externalProjectRT *apisv3.RoleTemplate
externalNoContextRT *apisv3.RoleTemplate
invalidInheritedRT *apisv3.RoleTemplate
externalClusterInheritedRT *apisv3.RoleTemplate
externalProjectInheritedRT *apisv3.RoleTemplate
externalNoContextInheritedRT *apisv3.RoleTemplate
adminRT *apisv3.RoleTemplate
readNodesRT *apisv3.RoleTemplate
writeNodesRT *apisv3.RoleTemplate
inheritedRT *apisv3.RoleTemplate
externalRT *apisv3.RoleTemplate
invalidInhertedRT *apisv3.RoleTemplate

readPodCR *rbacv1.ClusterRole
readServiceCR *rbacv1.ClusterRole
writeNodeCR *rbacv1.ClusterRole
}

func TestRoleTemplateResolver(t *testing.T) {
Expand Down Expand Up @@ -96,18 +89,10 @@ func (r *RoleTemplateResolverSuite) SetupSuite() {
APIGroups: []string{"*"},
Resources: []string{"*"},
}
r.readPodCR = &rbacv1.ClusterRole{
ObjectMeta: metav1.ObjectMeta{Name: "read-pods"},
Rules: []rbacv1.PolicyRule{ruleReadPods},
}
r.readServiceCR = &rbacv1.ClusterRole{
ObjectMeta: metav1.ObjectMeta{Name: "read-services"},
Rules: []rbacv1.PolicyRule{ruleReadServices},
}
r.writeNodeCR = &rbacv1.ClusterRole{
ObjectMeta: metav1.ObjectMeta{Name: "write-nodes"},
Rules: []rbacv1.PolicyRule{ruleWriteNodes},
}

r.readNodesRT = &apisv3.RoleTemplate{
ObjectMeta: metav1.ObjectMeta{
Expand Down Expand Up @@ -136,28 +121,12 @@ func (r *RoleTemplateResolverSuite) SetupSuite() {
Administrative: true,
Context: "cluster",
}
r.externalClusterRT = &apisv3.RoleTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: r.readPodCR.Name,
},
DisplayName: "External Cluster Role",
Context: "cluster",
External: true,
}
r.externalProjectRT = &apisv3.RoleTemplate{
r.externalRT = &apisv3.RoleTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: r.readServiceCR.Name,
},
DisplayName: "External Project Role",
Context: "project",
External: true,
}
r.externalNoContextRT = &apisv3.RoleTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: r.writeNodeCR.Name,
},
DisplayName: "External No Context Role",
Context: "",
DisplayName: "External Role",
Context: "cluster",
External: true,
}

Expand All @@ -170,43 +139,7 @@ func (r *RoleTemplateResolverSuite) SetupSuite() {
Context: "cluster",
RoleTemplateNames: []string{r.writeNodesRT.Name},
}
r.externalClusterInheritedRT = &apisv3.RoleTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: "external-cluster-inherited-role",
},
DisplayName: "External Cluster Inherited Role",
Context: "cluster",
RoleTemplateNames: []string{
r.externalClusterRT.Name,
r.externalProjectRT.Name,
r.externalNoContextRT.Name,
},
}
r.externalProjectInheritedRT = &apisv3.RoleTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: "external-project-inherited-role",
},
DisplayName: "External Project Inherited Role",
Context: "project",
RoleTemplateNames: []string{
r.externalClusterRT.Name,
r.externalProjectRT.Name,
r.externalNoContextRT.Name,
},
}
r.externalNoContextInheritedRT = &apisv3.RoleTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: "external-no-context-inherited-role",
},
DisplayName: "External No Context Inherited Role",
Context: "",
RoleTemplateNames: []string{
r.externalClusterRT.Name,
r.externalProjectRT.Name,
r.externalNoContextRT.Name,
},
}
r.invalidInheritedRT = &apisv3.RoleTemplate{
r.invalidInhertedRT = &apisv3.RoleTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: "invalid-inherited-role",
},
Expand Down Expand Up @@ -262,123 +195,23 @@ func (r *RoleTemplateResolverSuite) TestRoleTemplateResolver() {
want: append(r.inheritedRT.Rules, append(r.readNodesRT.Rules, r.writeNodesRT.Rules...)...),
wantErr: false,
},
// Get external cluster role
// Get external role
{
name: "Test external cluster role",
args: args{
caches: func() (v3.RoleTemplateCache, wranglerv1.ClusterRoleCache) {
ctrl := gomock.NewController(r.T())
roleTemplateCache := fake.NewMockNonNamespacedCacheInterface[*apisv3.RoleTemplate](ctrl)
roleTemplateCache.EXPECT().Get(r.externalClusterRT.Name).Return(r.externalClusterRT, nil)
clusterRoleCache := fake.NewMockNonNamespacedCacheInterface[*rbacv1.ClusterRole](ctrl)
clusterRoleCache.EXPECT().Get(r.readPodCR.Name).Return(r.readPodCR, nil)
return roleTemplateCache, clusterRoleCache
},
name: r.externalClusterRT.Name,
},
want: r.readPodCR.Rules,
wantErr: false,
},
// Get external project role
{
name: "Test external project role",
args: args{
caches: func() (v3.RoleTemplateCache, wranglerv1.ClusterRoleCache) {
ctrl := gomock.NewController(r.T())
roleTemplateCache := fake.NewMockNonNamespacedCacheInterface[*apisv3.RoleTemplate](ctrl)
roleTemplateCache.EXPECT().Get(r.externalProjectRT.Name).Return(r.externalProjectRT, nil)
roleTemplateCache.EXPECT().Get(r.externalRT.Name).Return(r.externalRT, nil)
clusterRoleCache := fake.NewMockNonNamespacedCacheInterface[*rbacv1.ClusterRole](ctrl)
clusterRoleCache.EXPECT().Get(r.readServiceCR.Name).Return(r.readServiceCR, nil)
return roleTemplateCache, clusterRoleCache
},
name: r.externalProjectRT.Name,
name: r.externalRT.Name,
},
want: r.readServiceCR.Rules,
wantErr: false,
},
// Get external no context role
{
name: "Test external no context role",
args: args{
caches: func() (v3.RoleTemplateCache, wranglerv1.ClusterRoleCache) {
ctrl := gomock.NewController(r.T())
roleTemplateCache := fake.NewMockNonNamespacedCacheInterface[*apisv3.RoleTemplate](ctrl)
roleTemplateCache.EXPECT().Get(r.externalNoContextRT.Name).Return(r.externalNoContextRT, nil)
clusterRoleCache := fake.NewMockNonNamespacedCacheInterface[*rbacv1.ClusterRole](ctrl)
clusterRoleCache.EXPECT().Get(r.writeNodeCR.Name).Return(r.writeNodeCR, nil)
return roleTemplateCache, clusterRoleCache
},
name: r.externalNoContextRT.Name,
},
want: r.writeNodeCR.Rules,
wantErr: false,
},
// Get inherited from an external cluster role
{
name: "Test external cluster inherited role",
args: args{
caches: func() (v3.RoleTemplateCache, wranglerv1.ClusterRoleCache) {
ctrl := gomock.NewController(r.T())
roleTemplateCache := fake.NewMockNonNamespacedCacheInterface[*apisv3.RoleTemplate](ctrl)
roleTemplateCache.EXPECT().Get(r.externalClusterRT.Name).Return(r.externalClusterRT, nil)
roleTemplateCache.EXPECT().Get(r.externalProjectRT.Name).Return(r.externalProjectRT, nil)
roleTemplateCache.EXPECT().Get(r.externalNoContextRT.Name).Return(r.externalNoContextRT, nil)
roleTemplateCache.EXPECT().Get(r.externalClusterInheritedRT.Name).Return(r.externalClusterInheritedRT, nil)
clusterRoleCache := fake.NewMockNonNamespacedCacheInterface[*rbacv1.ClusterRole](ctrl)
clusterRoleCache.EXPECT().Get(r.readPodCR.Name).Return(r.readPodCR, nil)
clusterRoleCache.EXPECT().Get(r.readServiceCR.Name).Return(r.readServiceCR, nil)
clusterRoleCache.EXPECT().Get(r.writeNodeCR.Name).Return(r.writeNodeCR, nil)
return roleTemplateCache, clusterRoleCache
},
name: r.externalClusterInheritedRT.Name,
},
want: append(r.readPodCR.Rules, append(r.readServiceCR.Rules, r.writeNodeCR.Rules...)...),
wantErr: false,
},
// Get inherited from an external project role
{
name: "Test external project inherited role",
args: args{
caches: func() (v3.RoleTemplateCache, wranglerv1.ClusterRoleCache) {
ctrl := gomock.NewController(r.T())
roleTemplateCache := fake.NewMockNonNamespacedCacheInterface[*apisv3.RoleTemplate](ctrl)
roleTemplateCache.EXPECT().Get(r.externalClusterRT.Name).Return(r.externalClusterRT, nil)
roleTemplateCache.EXPECT().Get(r.externalProjectRT.Name).Return(r.externalProjectRT, nil)
roleTemplateCache.EXPECT().Get(r.externalNoContextRT.Name).Return(r.externalNoContextRT, nil)
roleTemplateCache.EXPECT().Get(r.externalProjectInheritedRT.Name).Return(r.externalProjectInheritedRT, nil)
clusterRoleCache := fake.NewMockNonNamespacedCacheInterface[*rbacv1.ClusterRole](ctrl)
clusterRoleCache.EXPECT().Get(r.readPodCR.Name).Return(r.readPodCR, nil)
clusterRoleCache.EXPECT().Get(r.readServiceCR.Name).Return(r.readServiceCR, nil)
clusterRoleCache.EXPECT().Get(r.writeNodeCR.Name).Return(r.writeNodeCR, nil)
return roleTemplateCache, clusterRoleCache
},
name: r.externalProjectInheritedRT.Name,
},
want: append(r.readPodCR.Rules, append(r.readServiceCR.Rules, r.writeNodeCR.Rules...)...),
wantErr: false,
},
// Get inherited from an external no context role
{
name: "Test external no context inherited role",
args: args{
caches: func() (v3.RoleTemplateCache, wranglerv1.ClusterRoleCache) {
ctrl := gomock.NewController(r.T())
roleTemplateCache := fake.NewMockNonNamespacedCacheInterface[*apisv3.RoleTemplate](ctrl)
roleTemplateCache.EXPECT().Get(r.externalClusterRT.Name).Return(r.externalClusterRT, nil)
roleTemplateCache.EXPECT().Get(r.externalProjectRT.Name).Return(r.externalProjectRT, nil)
roleTemplateCache.EXPECT().Get(r.externalNoContextRT.Name).Return(r.externalNoContextRT, nil)
roleTemplateCache.EXPECT().Get(r.externalNoContextInheritedRT.Name).Return(r.externalNoContextInheritedRT, nil)
clusterRoleCache := fake.NewMockNonNamespacedCacheInterface[*rbacv1.ClusterRole](ctrl)
clusterRoleCache.EXPECT().Get(r.readPodCR.Name).Return(r.readPodCR, nil)
clusterRoleCache.EXPECT().Get(r.readServiceCR.Name).Return(r.readServiceCR, nil)
clusterRoleCache.EXPECT().Get(r.writeNodeCR.Name).Return(r.writeNodeCR, nil)
return roleTemplateCache, clusterRoleCache
},
name: r.externalNoContextInheritedRT.Name,
},
want: append(r.readPodCR.Rules, append(r.readServiceCR.Rules, r.writeNodeCR.Rules...)...),
wantErr: false,
},
// Get unknown role
{
name: "Test invalid template name",
Expand All @@ -397,17 +230,17 @@ func (r *RoleTemplateResolverSuite) TestRoleTemplateResolver() {
},
// get unknown inherited role
{
name: "Test invalid inherited template name",
name: "Test invalid inherted template name",
args: args{
caches: func() (v3.RoleTemplateCache, wranglerv1.ClusterRoleCache) {
ctrl := gomock.NewController(r.T())
roleTemplateCache := fake.NewMockNonNamespacedCacheInterface[*apisv3.RoleTemplate](ctrl)
roleTemplateCache.EXPECT().Get(r.invalidInheritedRT.Name).Return(r.invalidInheritedRT, nil)
roleTemplateCache.EXPECT().Get(r.invalidInhertedRT.Name).Return(r.invalidInhertedRT, nil)
roleTemplateCache.EXPECT().Get(invalidName).Return(nil, errExpected)
clusterRoleCache := fake.NewMockNonNamespacedCacheInterface[*rbacv1.ClusterRole](ctrl)
return roleTemplateCache, clusterRoleCache
},
name: r.invalidInheritedRT.Name,
name: r.invalidInhertedRT.Name,
},
want: nil,
wantErr: true,
Expand Down