Skip to content

Commit

Permalink
Merge pull request #1202 from equinor/master
Browse files Browse the repository at this point in the history
Release Filter puplic ingress traffic, ServicePrincipals Auth
  • Loading branch information
Richard87 authored Sep 26, 2024
2 parents bd0b209 + 5ed2b4d commit 506d53d
Show file tree
Hide file tree
Showing 45 changed files with 927 additions and 350 deletions.
4 changes: 2 additions & 2 deletions charts/radix-operator/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: v2
name: radix-operator
version: 1.39.2
appVersion: 1.59.3
version: 1.41.0
appVersion: 1.61.0
kubeVersion: ">=1.24.0"
description: Radix Operator
keywords:
Expand Down
44 changes: 44 additions & 0 deletions charts/radix-operator/templates/radixapplication.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,29 @@ spec:
Enabled or disables collection of custom Prometheus metrics.
More info: https://www.radix.equinor.com/references/reference-radix-config/#monitoring
type: boolean
network:
description: Environment specific network settings.
properties:
ingress:
description: Ingress defines settings for ingress
traffic.
properties:
public:
description: Public defines settings for public
traffic.
properties:
allow:
description: |-
Allow defines a list of public IP addresses or CIDRs which are allowed to access the component.
All IP addresses are allowed if this field is empty or not set.
items:
description: IP address or CIDR.
pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\/([0-9]|[1-2][0-9]|3[0-2]))?$
type: string
type: array
type: object
type: object
type: object
node:
description: |-
Environment specific GPU requirements for the component.
Expand Down Expand Up @@ -1406,6 +1429,27 @@ spec:
minLength: 1
pattern: ^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$
type: string
network:
description: Network settings.
properties:
ingress:
description: Ingress defines settings for ingress traffic.
properties:
public:
description: Public defines settings for public traffic.
properties:
allow:
description: |-
Allow defines a list of public IP addresses or CIDRs which are allowed to access the component.
All IP addresses are allowed if this field is empty or not set.
items:
description: IP address or CIDR.
pattern: ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\/([0-9]|[1-2][0-9]|3[0-2]))?$
type: string
type: array
type: object
type: object
type: object
node:
description: |-
Defines GPU requirements for the component.
Expand Down
54 changes: 54 additions & 0 deletions json-schema/radixapplication.json
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,33 @@
"description": "Enabled or disables collection of custom Prometheus metrics.\nMore info: https://www.radix.equinor.com/references/reference-radix-config/#monitoring",
"type": "boolean"
},
"network": {
"description": "Environment specific network settings.",
"properties": {
"ingress": {
"description": "Ingress defines settings for ingress traffic.",
"properties": {
"public": {
"description": "Public defines settings for public traffic.",
"properties": {
"allow": {
"description": "Allow defines a list of public IP addresses or CIDRs which are allowed to access the component.\nAll IP addresses are allowed if this field is empty or not set.",
"items": {
"description": "IP address or CIDR.",
"pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\/([0-9]|[1-2][0-9]|3[0-2]))?$",
"type": "string"
},
"type": "array"
}
},
"type": "object"
}
},
"type": "object"
}
},
"type": "object"
},
"node": {
"description": "Environment specific GPU requirements for the component.\nMore info: https://www.radix.equinor.com/references/reference-radix-config/#node",
"properties": {
Expand Down Expand Up @@ -1394,6 +1421,33 @@
"pattern": "^(([a-z0-9][-a-z0-9]*)?[a-z0-9])?$",
"type": "string"
},
"network": {
"description": "Network settings.",
"properties": {
"ingress": {
"description": "Ingress defines settings for ingress traffic.",
"properties": {
"public": {
"description": "Public defines settings for public traffic.",
"properties": {
"allow": {
"description": "Allow defines a list of public IP addresses or CIDRs which are allowed to access the component.\nAll IP addresses are allowed if this field is empty or not set.",
"items": {
"description": "IP address or CIDR.",
"pattern": "^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\/([0-9]|[1-2][0-9]|3[0-2]))?$",
"type": "string"
},
"type": "array"
}
},
"type": "object"
}
},
"type": "object"
}
},
"type": "object"
},
"node": {
"description": "Defines GPU requirements for the component.\nMore info: https://www.radix.equinor.com/references/reference-radix-config/#node",
"properties": {
Expand Down
23 changes: 19 additions & 4 deletions pkg/apis/alert/alert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,14 +248,15 @@ func (s *alertTestSuite) Test_OnSync_Rbac_UpdateWithOwnerReference() {

func (s *alertTestSuite) Test_OnSync_Rbac_ConfiguredCorrectly() {
namespace, appName := "any-ns", "any-app"
adminGroups, readerGroups := []string{"admin1", "admin2"}, []string{"reader1", "reader2"}
adminGroups, adminUsers := []string{"admin1", "admin2"}, []string{"adminUser1", "adminUser2"}
readerGroups, readerUsers := []string{"reader1", "reader2"}, []string{"readerUser1", "readerUser2"}
alertName, alertUID := "alert", types.UID("alertuid")
radixalert := &radixv1.RadixAlert{
ObjectMeta: metav1.ObjectMeta{Name: alertName, UID: alertUID, Labels: map[string]string{kube.RadixAppLabel: appName}},
Spec: radixv1.RadixAlertSpec{},
}
radixalert, _ = s.radixClient.RadixV1().RadixAlerts(namespace).Create(context.Background(), radixalert, metav1.CreateOptions{})
rr := &radixv1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}, Spec: radixv1.RadixRegistrationSpec{AdGroups: adminGroups, ReaderAdGroups: readerGroups}}
rr := &radixv1.RadixRegistration{ObjectMeta: metav1.ObjectMeta{Name: appName}, Spec: radixv1.RadixRegistrationSpec{AdGroups: adminGroups, AdUsers: adminUsers, ReaderAdGroups: readerGroups, ReaderAdUsers: readerUsers}}
_, err := s.radixClient.RadixV1().RadixRegistrations().Create(context.Background(), rr, metav1.CreateOptions{})
s.Require().NoError(err)

Expand All @@ -272,7 +273,14 @@ func (s *alertTestSuite) Test_OnSync_Rbac_ConfiguredCorrectly() {
actualAdminRoleBinding, _ := s.kubeClient.RbacV1().RoleBindings(namespace).Get(context.Background(), getAlertConfigSecretAdminRoleName(alertName), metav1.GetOptions{})
s.Equal(actualAdminRole.Name, actualAdminRoleBinding.RoleRef.Name, "rolebinding role reference not as expected")
s.Equal("Role", actualAdminRoleBinding.RoleRef.Kind, "rolebinding role kind not as expected")
s.ElementsMatch([]rbacv1.Subject{{APIGroup: "rbac.authorization.k8s.io", Kind: rbacv1.GroupKind, Name: "admin1"}, {APIGroup: "rbac.authorization.k8s.io", Kind: rbacv1.GroupKind, Name: "admin2"}}, actualAdminRoleBinding.Subjects)
s.ElementsMatch(
[]rbacv1.Subject{
{APIGroup: "rbac.authorization.k8s.io", Kind: rbacv1.GroupKind, Name: "admin1"},
{APIGroup: "rbac.authorization.k8s.io", Kind: rbacv1.GroupKind, Name: "admin2"},
{APIGroup: "rbac.authorization.k8s.io", Kind: rbacv1.UserKind, Name: "adminUser1"},
{APIGroup: "rbac.authorization.k8s.io", Kind: rbacv1.UserKind, Name: "adminUser2"},
},
actualAdminRoleBinding.Subjects)

actualReaderRole, _ := s.kubeClient.RbacV1().Roles(namespace).Get(context.Background(), getAlertConfigSecretReaderRoleName(alertName), metav1.GetOptions{})
s.Len(actualReaderRole.Rules, 1, "role rules not as expected")
Expand All @@ -283,7 +291,14 @@ func (s *alertTestSuite) Test_OnSync_Rbac_ConfiguredCorrectly() {
actualReaderRoleBinding, _ := s.kubeClient.RbacV1().RoleBindings(namespace).Get(context.Background(), getAlertConfigSecretReaderRoleName(alertName), metav1.GetOptions{})
s.Equal(actualReaderRole.Name, actualReaderRoleBinding.RoleRef.Name, "rolebinding role reference not as expected")
s.Equal("Role", actualReaderRoleBinding.RoleRef.Kind, "rolebinding role kind not as expected")
s.ElementsMatch([]rbacv1.Subject{{APIGroup: "rbac.authorization.k8s.io", Kind: rbacv1.GroupKind, Name: "reader1"}, {APIGroup: "rbac.authorization.k8s.io", Kind: rbacv1.GroupKind, Name: "reader2"}}, actualReaderRoleBinding.Subjects)
s.ElementsMatch(
[]rbacv1.Subject{
{APIGroup: "rbac.authorization.k8s.io", Kind: rbacv1.GroupKind, Name: "reader1"},
{APIGroup: "rbac.authorization.k8s.io", Kind: rbacv1.GroupKind, Name: "reader2"},
{APIGroup: "rbac.authorization.k8s.io", Kind: rbacv1.UserKind, Name: "readerUser1"},
{APIGroup: "rbac.authorization.k8s.io", Kind: rbacv1.UserKind, Name: "readerUser2"},
},
actualReaderRoleBinding.Subjects)
}

func (s *alertTestSuite) Test_OnSync_Secret_RemoveOrphanedKeys() {
Expand Down
6 changes: 2 additions & 4 deletions pkg/apis/alert/rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,10 @@ func (syncer *alertSyncer) grantAdminAccessToAlertConfigSecret(ctx context.Conte
}

// create rolebinding
adGroups, err := utils.GetAdGroups(rr)
subjects, err := utils.GetAppAdminRbacSubjects(rr)
if err != nil {
return err
}

subjects := kube.GetRoleBindingGroups(adGroups)
rolebinding := kube.GetRolebindingToRoleWithLabelsForSubjects(roleName, subjects, role.Labels)
rolebinding.OwnerReferences = syncer.getOwnerReference()
return syncer.kubeUtil.ApplyRoleBinding(ctx, namespace, rolebinding)
Expand All @@ -105,7 +103,7 @@ func (syncer *alertSyncer) grantReaderAccessToAlertConfigSecret(ctx context.Cont
return err
}

subjects := kube.GetRoleBindingGroups(rr.Spec.ReaderAdGroups)
subjects := utils.GetAppReaderRbacSubjects(rr)
rolebinding := kube.GetRolebindingToRoleWithLabelsForSubjects(roleName, subjects, role.Labels)
rolebinding.OwnerReferences = syncer.getOwnerReference()
return syncer.kubeUtil.ApplyRoleBinding(ctx, namespace, rolebinding)
Expand Down
9 changes: 3 additions & 6 deletions pkg/apis/application/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,17 @@ func TestOnSync_CorrectRoleBindings_AppNamespace(t *testing.T) {
appName := "any-app"
rr, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration().
WithName(appName))
assert.NoError(t, err)
require.NoError(t, err)

roleBindings, _ := client.RbacV1().RoleBindings(utils.GetAppNamespace(appName)).List(context.Background(), metav1.ListOptions{})
assert.ElementsMatch(t,
[]string{defaults.RadixTektonAppRoleName, defaults.PipelineAppRoleName, defaults.AppAdminRoleName, defaults.AppReaderRoleName, "git-ssh-keys"},
getRoleBindingNames(roleBindings),
)

require.Len(t, getRoleBindingByName(defaults.AppAdminRoleName, roleBindings).Subjects, 1)
assert.Equal(t, getRoleBindingByName(defaults.PipelineAppRoleName, roleBindings).Subjects[0].Name, defaults.PipelineServiceAccountName)
assert.Equal(t, getRoleBindingByName(defaults.AppAdminRoleName, roleBindings).Subjects[0].Name, rr.Spec.AdGroups[0])
assert.Len(t, getRoleBindingByName(defaults.AppAdminRoleName, roleBindings).Subjects, 1)
assert.Equal(t, getRoleBindingByName(defaults.RadixTektonAppRoleName, roleBindings).Subjects[0].Name, defaults.RadixTektonServiceAccountName)
assert.Equal(t, getRoleBindingByName(defaults.AppReaderRoleName, roleBindings).Subjects[0].Name, rr.Spec.ReaderAdGroups[0])
assert.Equal(t, getRoleBindingByName("git-ssh-keys", roleBindings).Subjects[0].Name, rr.Spec.AdGroups[0])
Expand Down Expand Up @@ -205,10 +205,7 @@ func TestOnSync_NoUserGroupDefined_DefaultUserGroupSet(t *testing.T) {
os.Setenv(defaults.OperatorDefaultUserGroupEnvironmentVariable, defaultRole)

// Test
_, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration().
WithName("any-app").
WithAdGroups([]string{}).
WithReaderAdGroups([]string{}))
_, err := applyRegistrationWithSync(tu, client, kubeUtil, radixClient, utils.ARadixRegistration().WithName("any-app").WithAdGroups([]string{}).WithReaderAdGroups([]string{}))
require.NoError(t, err)

rolebindings, _ := client.RbacV1().RoleBindings("any-app-app").List(context.Background(), metav1.ListOptions{})
Expand Down
8 changes: 3 additions & 5 deletions pkg/apis/application/rolebinding.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@ func (app *Application) applyRbacAppNamespace(ctx context.Context) error {
registration := app.registration

appNamespace := utils.GetAppNamespace(registration.Name)
adGroups, err := utils.GetAdGroups(registration)
subjects, err := utils.GetAppAdminRbacSubjects(registration)
if err != nil {
return err
}
subjects := kube.GetRoleBindingGroups(adGroups)
adminRoleBinding := kube.GetRolebindingToClusterRoleForSubjects(registration.Name, defaults.AppAdminRoleName, subjects)

readerAdGroups := registration.Spec.ReaderAdGroups
readerSubjects := kube.GetRoleBindingGroups(readerAdGroups)
readerSubjects := utils.GetAppReaderRbacSubjects(registration)
readerRoleBinding := kube.GetRolebindingToClusterRoleForSubjects(registration.Name, defaults.AppReaderRoleName, readerSubjects)

for _, roleBinding := range []*rbacv1.RoleBinding{adminRoleBinding, readerRoleBinding} {
Expand Down Expand Up @@ -56,7 +54,7 @@ func (app *Application) applyRbacRadixRegistration(ctx context.Context) error {
// Reader RBAC
clusterRoleReaderName := fmt.Sprintf("radix-platform-user-rr-reader-%s", appName)
readerClusterRole := app.buildRRClusterRole(ctx, clusterRoleReaderName, []string{"get", "list", "watch"})
appReaderSubjects := kube.GetRoleBindingGroups(rr.Spec.ReaderAdGroups)
appReaderSubjects := utils.GetAppReaderRbacSubjects(rr)
readerClusterRoleBinding := app.rrClusterRoleBinding(ctx, readerClusterRole, appReaderSubjects)

// Apply roles and bindings
Expand Down
15 changes: 11 additions & 4 deletions pkg/apis/applicationconfig/applicationconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package applicationconfig_test
import (
"context"
"fmt"
"slices"
"testing"

"github.com/equinor/radix-common/utils/pointers"
Expand Down Expand Up @@ -409,10 +410,16 @@ func Test_AppReaderBuildSecretsRoleAndRoleBindingExists(t *testing.T) {
func Test_AppReaderPrivateImageHubRoleAndRoleBindingExists(t *testing.T) {
tu, client, kubeUtil, radixClient := setupTest(t)

adminGroups, readerGroups := []string{"admin1", "admin2"}, []string{"reader1", "reader2"}
adminGroups, adminUsers := []string{"admin1", "admin2"}, []string{"adminUser1", "adminUser2"}
readerGroups, readerUsers := []string{"reader1", "reader2"}, []string{"readerUser1", "readerUser2"}
err := applyApplicationWithSync(tu, client, kubeUtil, radixClient,
utils.ARadixApplication().
WithRadixRegistration(utils.ARadixRegistration().WithAdGroups(adminGroups).WithReaderAdGroups(readerGroups)).
WithRadixRegistration(
utils.ARadixRegistration().
WithAdGroups(adminGroups).
WithAdUsers(adminUsers).
WithReaderAdGroups(readerGroups).
WithReaderAdUsers(readerUsers)).
WithAppName("any-app").
WithEnvironment("dev", "master"))
require.NoError(t, err)
Expand All @@ -423,8 +430,8 @@ func Test_AppReaderPrivateImageHubRoleAndRoleBindingExists(t *testing.T) {
expectedSubjects []string
}
tests := []testSpec{
{roleName: "radix-private-image-hubs-reader", expectedVerbs: []string{"get", "list", "watch"}, expectedSubjects: readerGroups},
{roleName: "radix-private-image-hubs", expectedVerbs: []string{"get", "list", "watch", "update", "patch", "delete"}, expectedSubjects: adminGroups},
{roleName: "radix-private-image-hubs-reader", expectedVerbs: []string{"get", "list", "watch"}, expectedSubjects: slices.Concat(readerGroups, readerUsers)},
{roleName: "radix-private-image-hubs", expectedVerbs: []string{"get", "list", "watch", "update", "patch", "delete"}, expectedSubjects: slices.Concat(adminGroups, adminUsers)},
}

roles, _ := client.RbacV1().Roles("any-app-app").List(context.Background(), metav1.ListOptions{})
Expand Down
6 changes: 2 additions & 4 deletions pkg/apis/applicationconfig/rolebinding.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ import (
)

func rolebindingAppReaderToBuildSecrets(registration *radixv1.RadixRegistration, role *auth.Role) *auth.RoleBinding {
readerAdGroups := registration.Spec.ReaderAdGroups
subjects := kube.GetRoleBindingGroups(readerAdGroups)
subjects := utils.GetAppReaderRbacSubjects(registration)
roleName := role.ObjectMeta.Name
return kube.GetRolebindingToRoleWithLabelsForSubjects(roleName, subjects, role.Labels)
}
func rolebindingAppAdminToBuildSecrets(registration *radixv1.RadixRegistration, role *auth.Role) *auth.RoleBinding {
adGroups, _ := utils.GetAdGroups(registration)
subjects := kube.GetRoleBindingGroups(adGroups)
subjects, _ := utils.GetAppAdminRbacSubjects(registration)
roleName := role.ObjectMeta.Name
return kube.GetRolebindingToRoleWithLabelsForSubjects(roleName, subjects, role.Labels)
}
Expand Down
Loading

0 comments on commit 506d53d

Please sign in to comment.