Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
29 changes: 16 additions & 13 deletions pkg/tenancy/tenancy.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ type AllowedCluster struct {

// TenanTeamRBAC defines the permissions of a tenant
type TenantTeamRBAC struct {
GroupName string `yaml:"groupName"`
Rules []rbacv1.PolicyRule `yaml:"rules"`
GroupNames []string `yaml:"groupNames"`
Rules []rbacv1.PolicyRule `yaml:"rules"`
}

// Config represents the structure of the Tenancy file.
Expand Down Expand Up @@ -95,8 +95,8 @@ func (t Tenant) Validate() error {
}

if t.TeamRBAC != nil {
if t.TeamRBAC.GroupName == "" || len(t.TeamRBAC.Rules) == 0 {
result = multierror.Append(result, errors.New("must provide group name and team rules in team RBAC"))
if len(t.TeamRBAC.GroupNames) == 0 || len(t.TeamRBAC.Rules) == 0 {
result = multierror.Append(result, errors.New("must provide group names and team rules in team RBAC"))
}
}

Expand Down Expand Up @@ -268,7 +268,7 @@ func GenerateTenantResources(config *Config) ([]client.Object, error) {
generated = append(generated, newRoleBinding(tenant.Name, namespace, serviceAccountName, tenant.ClusterRole, tenantLabels))
if tenant.TeamRBAC != nil {
generated = append(generated, newTeamRole(tenant.Name, namespace, tenant.Labels, tenant.TeamRBAC.Rules))
generated = append(generated, newTeamRoleBinding(tenant.Name, namespace, tenant.TeamRBAC.GroupName, tenant.Labels))
generated = append(generated, newTeamRoleBinding(tenant.Name, namespace, tenant.TeamRBAC.GroupNames, tenant.Labels))
}
}
if len(tenant.AllowedRepositories) != 0 {
Expand Down Expand Up @@ -344,7 +344,16 @@ func newRoleBinding(name, namespace, serviceAccountName, clusterRole string, lab
}
}

func newTeamRoleBinding(name, namespace, groupName string, labels map[string]string) *rbacv1.RoleBinding {
func newTeamRoleBinding(name, namespace string, groupNames []string, labels map[string]string) *rbacv1.RoleBinding {
subjects := []rbacv1.Subject{}
for _, groupName := range groupNames {
subjects = append(subjects, rbacv1.Subject{
APIGroup: "rbac.authorization.k8s.io",
Kind: "Group",
Name: groupName,
})
}

return &rbacv1.RoleBinding{
TypeMeta: roleBindingTypeMeta,
ObjectMeta: metav1.ObjectMeta{
Expand All @@ -357,13 +366,7 @@ func newTeamRoleBinding(name, namespace, groupName string, labels map[string]str
Kind: "Role",
Name: fmt.Sprintf("%s-team-role", name),
},
Subjects: []rbacv1.Subject{
{
APIGroup: "rbac.authorization.k8s.io",
Kind: "Group",
Name: groupName,
},
},
Subjects: subjects,
}
}

Expand Down
47 changes: 44 additions & 3 deletions pkg/tenancy/tenancy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,32 @@ func TestGenerateTenantResources_WithErrors(t *testing.T) {
},
errorMessages: []string{"invalid tenant name", "must provide at least one namespace"},
},
{
name: "tenant with empty teamRBAC rules list",
tenant: makeTestTenant(t, func(tenant *Tenant) {
tenant.TeamRBAC = &TenantTeamRBAC{
GroupNames: []string{"foo-group"},
Rules: []rbacv1.PolicyRule{},
}
}),
errorMessages: []string{"must provide group names and team rules in team RBAC"},
},
{
name: "tenant with empty teamRBAC groupNames list",
tenant: makeTestTenant(t, func(tenant *Tenant) {
tenant.TeamRBAC = &TenantTeamRBAC{
GroupNames: []string{},
Rules: []rbacv1.PolicyRule{
{
Verbs: []string{"get"},
APIGroups: []string{""},
Resources: []string{"pods"},
},
},
}
}),
errorMessages: []string{"must provide group names and team rules in team RBAC"},
},
}

for _, tt := range generationTests {
Expand Down Expand Up @@ -557,17 +583,17 @@ func Test_newTeamRoleBinding(t *testing.T) {
labels := map[string]string{
"toolkit.fluxcd.io/tenant": "test-tenant",
}
groupName := "test-group"
groupNames := []string{"test-group"}

subjects := []rbacv1.Subject{
{
APIGroup: "rbac.authorization.k8s.io",
Kind: "Group",
Name: groupName,
Name: groupNames[0],
},
}

rb := newTeamRoleBinding("test-tenant", "test-namespace", groupName, labels)
rb := newTeamRoleBinding("test-tenant", "test-namespace", groupNames, labels)
assert.Equal(t, rb.Name, "test-tenant-team-rolebinding")
assert.Equal(t, rb.Namespace, "test-namespace")
assert.Equal(t, rb.RoleRef.Name, "test-tenant-team-role")
Expand Down Expand Up @@ -801,6 +827,21 @@ func verifyPolicies(expected ...*pacv2beta1.Policy) func(t *testing.T, cl client

type verifyFunc func(t *testing.T, cl client.Client)

func makeTestTenant(t *testing.T, options ...func(*Tenant)) Tenant {
tenant := &Tenant{
Name: "foo",
Namespaces: []string{
"foo-ns",
},
}

for _, o := range options {
o(tenant)
}

return *tenant
}

func testNewAllowedReposPolicy(t *testing.T, tenantName string, namespaces []string, allowedRepositories []AllowedRepository, labels map[string]string) *pacv2beta1.Policy {
t.Helper()
p, err := newAllowedRepositoriesPolicy(tenantName, namespaces, allowedRepositories, labels)
Expand Down
4 changes: 3 additions & 1 deletion pkg/tenancy/testdata/example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ tenants:
- kubeConfig: cluster-1-kubeconfig
- kubeConfig: cluster-2-kubeconfig
teamRBAC:
groupName: bar-group
groupNames:
- foo-group
- bar-group
rules:
- apiGroups:
- ''
Expand Down
6 changes: 6 additions & 0 deletions pkg/tenancy/testdata/example.yaml.golden
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ roleRef:
kind: Role
name: bar-tenant-team-role
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: foo-group
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: bar-group
Expand Down Expand Up @@ -173,6 +176,9 @@ roleRef:
kind: Role
name: bar-tenant-team-role
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: foo-group
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: bar-group
Expand Down