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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package disruptionexternalapiserver
import (
"context"
"fmt"
"path"
"time"

"github.com/openshift/origin/pkg/monitor/backenddisruption"
Expand All @@ -14,6 +15,8 @@ import (
exutil "github.com/openshift/origin/test/extended/util"
"github.com/sirupsen/logrus"

configv1 "github.com/openshift/api/config/v1"
configclient "github.com/openshift/client-go/config/clientset/versioned"
imagev1 "github.com/openshift/client-go/image/clientset/versioned/typed/image/v1"
oauthv1 "github.com/openshift/client-go/oauth/clientset/versioned/typed/oauth/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -89,6 +92,44 @@ func createOauthApiChecker(adminRESTConfig *rest.Config, url string, cache bool)
return createApiServerChecker(adminRESTConfig, disruptionBackendName, "oauth-apiserver", url)
}

func createOauthApiCheckerForOAuthClient(adminRESTConfig *rest.Config, baseURL string, cache bool) (*disruptionlibrary.Availability, error) {
oauthClient, err := oauthv1.NewForConfig(adminRESTConfig)
if err != nil {
return nil, fmt.Errorf("unable to create oauth client for oauth-apiserver api checker: %v", err)
}
oauthclients, err := oauthClient.OAuthClients().List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("unable to list oauth for oauth-apiserver api checker: %v", err)
}
if len(oauthclients.Items) == 0 {
return nil, fmt.Errorf("found no suitable imagestream for oauth-apiserver api checker: %v", err)
}
oauthClientName := oauthclients.Items[0].Name
oauthClientRevision := oauthclients.Items[0].ResourceVersion

url := path.Join(baseURL, fmt.Sprintf("%s?resourceVersion=%s", oauthClientName, oauthClientRevision))
return createOauthApiChecker(adminRESTConfig, url, cache)
}

func oauthAvailable(ctx context.Context, adminRESTConfig *rest.Config) (bool, error) {
configClient, err := configclient.NewForConfig(adminRESTConfig)
if err != nil {
return false, err
}

authn, err := configClient.ConfigV1().Authentications().Get(ctx, "cluster", metav1.GetOptions{})
if err != nil {
return false, err
}

switch authn.Spec.Type {
case "", configv1.AuthenticationTypeIntegratedOAuth:
return true, nil
}

return false, nil
}

func (i *InvariantExternalDisruption) PrepareCollection(ctx context.Context, adminRESTConfig *rest.Config, recorder monitorapi.RecorderWriter) error {
return nil
}
Expand Down Expand Up @@ -140,20 +181,6 @@ func (i *InvariantExternalDisruption) StartCollection(ctx context.Context, admin
imageStreamName := imagestreams.Items[0].Name
imageStreamRevision := imagestreams.Items[0].ResourceVersion

oauthClient, err := oauthv1.NewForConfig(i.adminRESTConfig)
if err != nil {
return fmt.Errorf("unable to create oauth client for oauth-apiserver api checker: %v", err)
}
oauthclients, err := oauthClient.OAuthClients().List(context.TODO(), metav1.ListOptions{})
if err != nil {
return fmt.Errorf("unable to list oauth for oauth-apiserver api checker: %v", err)
}
if len(oauthclients.Items) == 0 {
return fmt.Errorf("found no suitable imagestream for oauth-apiserver api checker: %v", err)
}
oauthClientName := oauthclients.Items[0].Name
oauthClientRevision := oauthclients.Items[0].ResourceVersion

kubeApiChecker, err := createKubeApiChecker(i.adminRESTConfig, "/api/v1/namespaces/default", false)
if err != nil {
return fmt.Errorf("unable to create kube api checker: %v", err)
Expand All @@ -178,18 +205,22 @@ func (i *InvariantExternalDisruption) StartCollection(ctx context.Context, admin
}
i.disruptionCheckers = append(i.disruptionCheckers, openshiftApiCachedChecker)

oauthApiChecker, err := createOauthApiChecker(i.adminRESTConfig, "/apis/oauth.openshift.io/v1/oauthclients", false)
if err != nil {
return fmt.Errorf("unable to create oauth api checker: %v", err)
}
if oauthAvailable, err := oauthAvailable(ctx, i.adminRESTConfig); err != nil {
return fmt.Errorf("unable to check authentication type: %v", err)

i.disruptionCheckers = append(i.disruptionCheckers, oauthApiChecker)
} else if oauthAvailable {
oauthApiChecker, err := createOauthApiChecker(i.adminRESTConfig, "/apis/oauth.openshift.io/v1/oauthclients", false)
if err != nil {
return fmt.Errorf("unable to create oauth api checker: %v", err)
}
i.disruptionCheckers = append(i.disruptionCheckers, oauthApiChecker)

oauthApiCachedChecker, err := createOauthApiChecker(i.adminRESTConfig, fmt.Sprintf("/apis/oauth.openshift.io/v1/oauthclients/%s?resourceVersion=%s", oauthClientName, oauthClientRevision), true)
if err != nil {
return fmt.Errorf("unable to create cached openshift api checker: %v", err)
oauthApiCachedChecker, err := createOauthApiCheckerForOAuthClient(i.adminRESTConfig, "/apis/oauth.openshift.io/v1/oauthclients", true)
if err != nil {
return fmt.Errorf("unable to create cached openshift api checker: %v", err)
}
i.disruptionCheckers = append(i.disruptionCheckers, oauthApiCachedChecker)
}
i.disruptionCheckers = append(i.disruptionCheckers, oauthApiCachedChecker)

for n := range i.disruptionCheckers {
if err := i.disruptionCheckers[n].StartCollection(ctx, adminRESTConfig, recorder); err != nil {
Expand Down
26 changes: 22 additions & 4 deletions test/extended/authorization/authorization_rbac_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package authorization
import (
"context"
"fmt"
"regexp"
"strings"
"time"

Expand Down Expand Up @@ -639,7 +640,9 @@ func RunLegacyEndpointConfirmNoEscalation(t g.GinkgoTInterface, clusterAdminAuth
Name: userName,
},
}
escalationFormat := `%s %q is forbidden: user %q (groups=["system:authenticated:oauth" "system:authenticated"]) is attempting to grant RBAC permissions not currently held:`
// the two groups appear in different order in different cases
escalationFormatRegex := `^%s %q is forbidden: user %q \(groups=\[([^\]]+)\]\) is attempting to grant RBAC permissions not currently held:`
expectedGroups := sets.New("system:authenticated", "system:authenticated:oauth")
escalatingRules := []authorizationv1.PolicyRule{
{
Verbs: []string{"hug"},
Expand Down Expand Up @@ -879,10 +882,25 @@ func RunLegacyEndpointConfirmNoEscalation(t g.GinkgoTInterface, clusterAdminAuth
t.Errorf("expected group resource %s got %s", wantGR, gotGR)
}

wantErr := fmt.Sprintf(escalationFormat, wantGR.String(), resourceName, userName)
wantErrRegex := regexp.MustCompile(fmt.Sprintf(escalationFormatRegex,
regexp.QuoteMeta(wantGR.String()),
regexp.QuoteMeta(resourceName),
regexp.QuoteMeta(userName),
))
gotErr := err.Error()
if !strings.HasPrefix(gotErr, wantErr) {
t.Errorf("expected escalation message prefix %q got %q", wantErr, gotErr)
matches := wantErrRegex.FindStringSubmatch(gotErr)
if len(matches) == 0 {
t.Errorf("expected escalation message to match pattern, got %q", gotErr)
} else {
// Parse groups from the string like `"system:authenticated" "system:authenticated:oauth"`
actualGroups := sets.New[string]()
for quotedGroup := range strings.FieldsSeq(matches[1]) {
group := strings.Trim(quotedGroup, "\"")
actualGroups.Insert(group)
}
if !expectedGroups.Equal(actualGroups) {
t.Errorf("expected groups %v, got %v", expectedGroups.UnsortedList(), actualGroups.UnsortedList())
}
}
})
}
Expand Down
3 changes: 2 additions & 1 deletion test/extended/operators/clusteroperators.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package operators

import (
"context"
"fmt"
"strings"

g "github.com/onsi/ginkgo/v2"
Expand Down Expand Up @@ -110,7 +111,7 @@ var _ = g.Describe("[sig-arch] ClusterOperators [apigroup:config.openshift.io]",
Group: relatedObj.Group,
Resource: relatedObj.Resource,
})
o.Expect(err).ToNot(o.HaveOccurred())
o.Expect(err).ToNot(o.HaveOccurred(), fmt.Sprintf("unexpected error while getting mapping for relatedObject of cluster operator '%s'", clusterOperator.Name))
o.Expect(len(resourceMatches)).To(o.BeNumerically(">", 0),
"No valid rest mapping found for cluster operator %s related object %s",
clusterOperator.Name, relatedObj.Resource)
Expand Down
87 changes: 58 additions & 29 deletions test/extended/operators/management_plane_operators.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (

g "github.com/onsi/ginkgo/v2"
o "github.com/onsi/gomega"
configv1 "github.com/openshift/api/config/v1"
operatorv1 "github.com/openshift/api/operator/v1"
"github.com/openshift/library-go/pkg/operator/v1helpers"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -18,64 +19,84 @@ import (
exutil "github.com/openshift/origin/test/extended/util"
)

type runtimeConfigConditionsFunc func(context.Context, *exutil.CLI) ([]string, error)

var (
// some conditions depend on cluster runtime configuration
operatorResourceToConditionalConditions = map[schema.GroupVersionResource]runtimeConfigConditionsFunc{
{Group: "operator.openshift.io", Version: "v1", Resource: "authentications"}: func(ctx context.Context, oc *exutil.CLI) ([]string, error) {
authn, err := oc.AdminConfigClient().ConfigV1().Authentications().Get(ctx, "cluster", metav1.GetOptions{})
if err != nil {
return nil, err
}

switch authn.Spec.Type {
case configv1.AuthenticationTypeOIDC:
return nil, nil

default:
return []string{
"APIServerDeploymentAvailable",
"APIServerDeploymentDegraded",
"APIServerDeploymentProgressing",
"APIServerWorkloadDegraded",
"AuthConfigDegraded",
"AuthenticatorCertKeyProgressing",
"IngressConfigDegraded",
"IngressStateEndpointsDegraded",
"IngressStatePodsDegraded",
"OAuthConfigDegraded",
"OAuthConfigIngressDegraded",
"OAuthConfigRouteDegraded",
"OAuthConfigServiceDegraded",
"OAuthServerDeploymentAvailable",
"OAuthServerDeploymentDegraded",
"OAuthServerDeploymentProgressing",
"OAuthServerRouteEndpointAccessibleControllerAvailable",
"OAuthServerServiceEndpointAccessibleControllerAvailable",
"OAuthServerServiceEndpointsEndpointAccessibleControllerAvailable",
"OAuthServerWorkloadDegraded",
"OAuthServiceDegraded",
"OAuthSessionSecretDegraded",
"OAuthSystemMetadataDegraded",
"ReadyIngressNodesAvailable",
"RouterCertsDegraded",
"SystemServiceCAConfigDegraded",
"WellKnownAvailable",
"WellKnownReadyControllerProgressing",
}, nil
}
},
}
operatorResourceToRequiredConditions = map[schema.GroupVersionResource][]string{
{Group: "operator.openshift.io", Version: "v1", Resource: "authentications"}: {
"APIServerDeploymentAvailable",
"APIServerDeploymentDegraded",
"APIServerDeploymentProgressing",
"APIServerStaticResourcesDegraded",
"APIServerWorkloadDegraded",
"APIServicesAvailable",
"APIServicesDegraded",
"AuditPolicyDegraded",
"AuthConfigDegraded",
"AuthenticatorCertKeyProgressing",
"CustomRouteControllerDegraded",
"Encrypted",
"EncryptionKeyControllerDegraded",
"EncryptionMigrationControllerDegraded",
"EncryptionMigrationControllerProgressing",
"EncryptionPruneControllerDegraded",
"EncryptionStateControllerDegraded",
"IngressConfigDegraded",
"IngressStateEndpointsDegraded",
"IngressStatePodsDegraded",
"ManagementStateDegraded",
"OAuthAPIServerConfigObservationDegraded",
"OAuthClientsControllerDegraded",
"OAuthConfigDegraded",
"OAuthConfigIngressDegraded",
"OAuthConfigRouteDegraded",
"OAuthConfigServiceDegraded",
"OAuthServerConfigObservationDegraded",
"OAuthServerDeploymentAvailable",
"OAuthServerDeploymentDegraded",
"OAuthServerDeploymentProgressing",
"OAuthServerRouteEndpointAccessibleControllerAvailable",
"OAuthServerRouteEndpointAccessibleControllerDegraded",
"OAuthServerServiceEndpointAccessibleControllerAvailable",
"OAuthServerServiceEndpointAccessibleControllerDegraded",
"OAuthServerServiceEndpointsEndpointAccessibleControllerAvailable",
"OAuthServerServiceEndpointsEndpointAccessibleControllerDegraded",
"OAuthServerWorkloadDegraded",
"OAuthServiceDegraded",
"OAuthSessionSecretDegraded",
"OAuthSystemMetadataDegraded",
"OpenshiftAuthenticationStaticResourcesDegraded",
"ProxyConfigControllerDegraded",
"ReadyIngressNodesAvailable",
"ResourceSyncControllerDegraded",
"RevisionControllerDegraded",
"RouterCertsDegraded",
"RouterCertsDomainValidationControllerDegraded",
"SystemServiceCAConfigDegraded",
"UnsupportedConfigOverridesUpgradeable",
"WebhookAuthenticatorCertApprover_OpenShiftAuthenticatorDegraded",
"WebhookAuthenticatorControllerDegraded",
"WellKnownAvailable",
"WellKnownReadyControllerDegraded",
"WellKnownReadyControllerProgressing",
},
//{Group: "operator.openshift.io", Version: "v1", Resource: "clustercsidrivers"}: {}, // TODO special names
{Group: "operator.openshift.io", Version: "v1", Resource: "configs"}: {
Expand Down Expand Up @@ -392,7 +413,15 @@ var _ = g.Describe("[sig-arch][Early] Operators", func() {
operatorStatus, err := getOperatorStatusFromUnstructured(uncastOperatorResource.Object)
o.Expect(err).NotTo(o.HaveOccurred())

for _, requiredCondition := range requiredConditions {
var runtimeConditions []string
if runtimeConditionsFunc := operatorResourceToConditionalConditions[gvr]; runtimeConditionsFunc != nil {
runtimeConditions, err = runtimeConditionsFunc(ctx, oc)
if err != nil {
failures = append(failures, fmt.Sprintf("could not determine runtime conditions for resource=%v: %v", gvr, err))
}
}

for _, requiredCondition := range append(requiredConditions, runtimeConditions...) {
condition := v1helpers.FindOperatorCondition(operatorStatus.Conditions, requiredCondition)
if condition == nil {
failures = append(failures, fmt.Sprintf("resource=%v is missing condition %q that was present in 4.17. If this is intentional, update the list in this test.", gvr, requiredCondition))
Expand Down