Skip to content

Commit

Permalink
Remove anyuid SCC requirement for OpenShift (#3813)
Browse files Browse the repository at this point in the history
Remove SCC requirement for anyuid for OpenShift
  • Loading branch information
curtbushko authored Apr 2, 2024
1 parent 5ccf1a3 commit 8da98ea
Show file tree
Hide file tree
Showing 25 changed files with 794 additions and 261 deletions.
3 changes: 3 additions & 0 deletions .changelog/3813.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
control-plane: Remove anyuid Security Context Constraints (SCC) requirement in OpenShift.
```
252 changes: 174 additions & 78 deletions acceptance/framework/consul/helm_cluster.go

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions acceptance/tests/api-gateway/api_gateway_kitchen_sink_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ func TestAPIGateway_KitchenSink(t *testing.T) {
checkStatusCondition(r, gateway.Status.Conditions, trueCondition("ConsulAccepted", "Accepted"))
require.Len(r, gateway.Status.Listeners, 2)

// http route checks
err = k8sClient.Get(context.Background(), types.NamespacedName{Name: "http-route", Namespace: "default"}, &httpRoute)
require.NoError(r, err)

require.EqualValues(r, int32(1), gateway.Status.Listeners[0].AttachedRoutes)
checkStatusCondition(r, gateway.Status.Listeners[0].Conditions, trueCondition("Accepted", "Accepted"))
checkStatusCondition(r, gateway.Status.Listeners[0].Conditions, falseCondition("Conflicted", "NoConflicts"))
Expand All @@ -152,10 +156,6 @@ func TestAPIGateway_KitchenSink(t *testing.T) {
// now we know we have an address, set it so we can use it
gatewayAddress = gateway.Status.Addresses[0].Value

// http route checks
err = k8sClient.Get(context.Background(), types.NamespacedName{Name: "http-route", Namespace: "default"}, &httpRoute)
require.NoError(r, err)

// check our finalizers
require.Len(r, httpRoute.Finalizers, 1)
require.EqualValues(r, gatewayFinalizer, httpRoute.Finalizers[0])
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ resources:
- secret.yaml
- serviceaccount.yaml
- psp-rolebinding.yaml
- anyuid-scc-rolebinding.yaml
- privileged-scc-rolebinding.yaml
- privileged-scc-rolebinding.yaml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,4 @@ resources:
- service.yaml
- serviceaccount.yaml
- psp-rolebinding.yaml
- anyuid-scc-rolebinding.yaml
- privileged-scc-rolebinding.yaml
- privileged-scc-rolebinding.yaml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ resources:
- service.yaml
- serviceaccount.yaml
- psp-rolebinding.yaml
- anyuid-scc-rolebinding.yaml
- privileged-scc-rolebinding.yaml
- privileged-scc-rolebinding.yaml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ resources:
- serviceaccount.yaml
- servicedefaults.yaml
- psp-rolebinding.yaml
- anyuid-scc-rolebinding.yaml
- privileged-scc-rolebinding.yaml
- privileged-scc-rolebinding.yaml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,4 @@ resources:
- service.yaml
- serviceaccount.yaml
- psp-rolebinding.yaml
- anyuid-scc-rolebinding.yaml
- privileged-scc-rolebinding.yaml
- privileged-scc-rolebinding.yaml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ resources:
- secret.yaml
- serviceaccount.yaml
- psp-rolebinding.yaml
- anyuid-scc-rolebinding.yaml
- privileged-scc-rolebinding.yaml
- privileged-scc-rolebinding.yaml
130 changes: 130 additions & 0 deletions control-plane/connect-inject/common/openshift.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

// Function copied from:
// https://github.com/openshift/apiserver-library-go/blob/release-4.17/pkg/securitycontextconstraints/sccmatching/matcher.go
// Apache 2.0 license: https://github.com/openshift/apiserver-library-go/blob/release-4.17/LICENSE

// A namespace in OpenShift has the following annotations:
// Annotations: openshift.io/sa.scc.mcs: s0:c27,c4
// openshift.io/sa.scc.uid-range: 1000710000/10000
// openshift.io/sa.scc.supplemental-groups: 1000710000/10000
//
// Note: Even though the annotation is named 'range', it is not a range but the ID you should use. All pods in a
// namespace should use the same UID/GID. (1000710000/1000710000 above)

package common

import (
"fmt"
"strconv"
"strings"

"github.com/hashicorp/consul-k8s/control-plane/connect-inject/constants"
corev1 "k8s.io/api/core/v1"
)

// GetOpenShiftUID gets the user id from the OpenShift annotation 'openshift.io/sa.scc.uid-range'.
func GetOpenShiftUID(ns *corev1.Namespace) (int64, error) {
annotation, ok := ns.Annotations[constants.AnnotationOpenShiftUIDRange]
if !ok {
return 0, fmt.Errorf("unable to find annotation %s", constants.AnnotationOpenShiftUIDRange)
}
if len(annotation) == 0 {
return 0, fmt.Errorf("found annotation %s but it was empty", constants.AnnotationOpenShiftUIDRange)
}

uid, err := parseOpenShiftUID(annotation)
if err != nil {
return 0, err
}

return uid, nil
}

// parseOpenShiftUID parses the UID "range" from the annotation string. The annotation can either have a '/' or '-'
// as a separator. '-' is the old style of UID from when it used to be an actual range.
// Example annotation value: "1000700000/100000".
func parseOpenShiftUID(val string) (int64, error) {
var uid int64
var err error
if strings.Contains(val, "/") {
str := strings.Split(val, "/")
uid, err = strconv.ParseInt(str[0], 10, 64)
if err != nil {
return 0, err
}
}
if strings.Contains(val, "-") {
str := strings.Split(val, "-")
uid, err = strconv.ParseInt(str[0], 10, 64)
if err != nil {
return 0, err
}
}

if !strings.Contains(val, "/") && !strings.Contains(val, "-") {
return 0, fmt.Errorf(
"annotation %s contains an invalid format for value %s",
constants.AnnotationOpenShiftUIDRange,
val,
)
}

return uid, nil
}

// GetOpenShiftGroup gets the group from OpenShift annotation 'openshift.io/sa.scc.supplemental-groups'
// Fall back to the UID annotation if the group annotation does not exist. The values should
// be the same.
func GetOpenShiftGroup(ns *corev1.Namespace) (int64, error) {
annotation, ok := ns.Annotations[constants.AnnotationOpenShiftGroups]
if !ok {
// fall back to UID annotation
annotation, ok = ns.Annotations[constants.AnnotationOpenShiftUIDRange]
if !ok {
return 0, fmt.Errorf(
"unable to find annotation %s or %s",
constants.AnnotationOpenShiftGroups,
constants.AnnotationOpenShiftUIDRange,
)
}
}
if len(annotation) == 0 {
return 0, fmt.Errorf("found annotation %s but it was empty", constants.AnnotationOpenShiftGroups)
}

uid, err := parseOpenShiftGroup(annotation)
if err != nil {
return 0, err
}

return uid, nil
}

// parseOpenShiftGroup parses the group from the annotation string. The annotation can either have a '/' or ','
// as a separator. ',' is the old style of UID from when it used to be an actual range.
func parseOpenShiftGroup(val string) (int64, error) {
var group int64
var err error
if strings.Contains(val, "/") {
str := strings.Split(val, "/")
group, err = strconv.ParseInt(str[0], 10, 64)
if err != nil {
return 0, err
}
}
if strings.Contains(val, ",") {
str := strings.Split(val, ",")
group, err = strconv.ParseInt(str[0], 10, 64)
if err != nil {
return 0, err
}
}

if !strings.Contains(val, "/") && !strings.Contains(val, ",") {
return 0, fmt.Errorf("annotation %s contains an invalid format for value %s", constants.AnnotationOpenShiftGroups, val)
}

return group, nil
}
Loading

0 comments on commit 8da98ea

Please sign in to comment.