Skip to content

Commit

Permalink
NE-310 E2E test for HSTS
Browse files Browse the repository at this point in the history
  • Loading branch information
candita committed Jul 28, 2021
1 parent 039e305 commit af9ce14
Show file tree
Hide file tree
Showing 77 changed files with 588 additions and 6,757 deletions.
8 changes: 4 additions & 4 deletions go.mod
Expand Up @@ -17,7 +17,7 @@ require (
github.com/go-logr/zapr v0.4.0
github.com/google/go-cmp v0.5.5
github.com/kevinburke/go-bindata v3.11.0+incompatible
github.com/openshift/api v0.0.0-20210722202039-91e26cfb36fc
github.com/openshift/api v0.0.0-20210726144523-6fcabc0010ca
github.com/openshift/build-machinery-go v0.0.0-20210712174854-1bb7fd1518d3
github.com/openshift/library-go v0.0.0-20210331235027-66936e2fcc52
github.com/pkg/errors v0.9.1
Expand All @@ -33,8 +33,8 @@ require (
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.21.1
k8s.io/apimachinery v0.21.1
k8s.io/apiserver v0.21.1
k8s.io/client-go v0.21.1
sigs.k8s.io/controller-runtime v0.9.0
k8s.io/apiserver v0.21.0
k8s.io/client-go v0.21.0
sigs.k8s.io/controller-runtime v0.9.0-alpha.1
sigs.k8s.io/controller-tools v0.4.1
)
205 changes: 163 additions & 42 deletions go.sum

Large diffs are not rendered by default.

108 changes: 108 additions & 0 deletions test/e2e/hsts_policy_test.go
@@ -0,0 +1,108 @@
// +build e2e

package e2e

import (
"context"
"testing"
"time"

configv1 "github.com/openshift/api/config/v1"
operatorv1 "github.com/openshift/api/operator/v1"
"github.com/openshift/cluster-ingress-operator/pkg/operator/controller"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
)

// Helper function for int32 pointers
func intPtr(s int32) *int32 {
return &s
}

func TestHstsPolicyWorks(t *testing.T) {
icName := types.NamespacedName{Namespace: operatorNamespace, Name: "hsts-policy"}
domain := icName.Name + "." + dnsConfig.Spec.BaseDomain

maxAgePolicy := configv1.MaxAgePolicy{LargestMaxAge: intPtr(99999), SmallestMaxAge: intPtr(1)}
hstsPolicy := []configv1.RequiredHSTSPolicy{
{
PreloadPolicy: configv1.RequirePreloadPolicy,
IncludeSubDomainsPolicy: configv1.RequireIncludeSubDomains,
MaxAge: maxAgePolicy,
},
}
ic := newPrivateIngress(icName, domain, hstsPolicy)
if err := kclient.Create(context.TODO(), ic); err != nil {
t.Fatalf("failed to create ingress config %s: %v", icName, err)
}
defer assertIngressConfigDeleted(t, kclient, ic)

conditions := []operatorv1.OperatorCondition{
{Type: operatorv1.IngressControllerAvailableConditionType, Status: operatorv1.ConditionTrue},
{Type: operatorv1.LoadBalancerManagedIngressConditionType, Status: operatorv1.ConditionFalse},
{Type: operatorv1.DNSManagedIngressConditionType, Status: operatorv1.ConditionFalse},
}
io := newPrivateController(icName, domain)
if err := kclient.Create(context.TODO(), io); err != nil {
t.Fatalf("failed to create ingresscontroller %s: %v", icName, err)
}
defer assertIngressControllerDeleted(t, kclient, io)
if err := waitForIngressControllerCondition(t, kclient, 5*time.Minute, icName, conditions...); err != nil {
t.Fatalf("failed to observe expected conditions: %v", err)
}

deployment := &appsv1.Deployment{}
if err := kclient.Get(context.TODO(), controller.RouterDeploymentName(io), deployment); err != nil {
t.Fatalf("failed to get ingresscontroller deployment: %v", err)
}

service := &corev1.Service{}
if err := kclient.Get(context.TODO(), controller.InternalIngressControllerServiceName(io), service); err != nil {
t.Fatalf("failed to get ingresscontroller service: %v", err)
}

echoPod := buildEchoPod("hsts-policy-echo", deployment.Namespace)
if err := kclient.Create(context.TODO(), echoPod); err != nil {
t.Fatalf("failed to create pod %s/%s: %v", echoPod.Namespace, echoPod.Name, err)
}
defer func() {
if err := kclient.Delete(context.TODO(), echoPod); err != nil {
t.Fatalf("failed to delete pod %s/%s: %v", echoPod.Namespace, echoPod.Name, err)
}
}()

echoService := buildEchoService(echoPod.Name, echoPod.Namespace, echoPod.ObjectMeta.Labels)
if err := kclient.Create(context.TODO(), echoService); err != nil {
t.Fatalf("failed to create service %s/%s: %v", echoService.Namespace, echoService.Name, err)
}
defer func() {
if err := kclient.Delete(context.TODO(), echoService); err != nil {
t.Fatalf("failed to delete service %s/%s: %v", echoService.Namespace, echoService.Name, err)
}
}()

echoRoute := buildRoute(echoPod.Name, echoPod.Namespace, echoService.Name)

// this should work
echoRoute.Annotations = map[string]string{
"haproxy.router.openshift.io/hsts_header": "max-age=99999",
}
if err := kclient.Create(context.TODO(), echoRoute); err != nil {
t.Fatalf("failed to create route %s/%s: %v", echoRoute.Namespace, echoRoute.Name, err)
}

// this should fail
echoRoute.Annotations = map[string]string{
"haproxy.router.openshift.io/hsts_header": "max-age=99999999",
}
if err := kclient.Create(context.TODO(), echoRoute); err == nil {
t.Fatalf("failed to reject route %s/%s, max-age 99999999", echoRoute.Namespace, echoRoute.Name)
}

defer func() {
if err := kclient.Delete(context.TODO(), echoRoute); err != nil {
t.Fatalf("failed to delete route %s/%s: %v", echoRoute.Namespace, echoRoute.Name, err)
}
}()
}
46 changes: 44 additions & 2 deletions test/e2e/operator_test.go
Expand Up @@ -2421,6 +2421,20 @@ func newPrivateController(name types.NamespacedName, domain string) *operatorv1.
}
}

func newPrivateIngress(name types.NamespacedName, domain string, hstsPolicy []configv1.RequiredHSTSPolicy) *configv1.Ingress {
return &configv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Namespace: name.Namespace,
Name: name.Name,
},
Spec: configv1.IngressSpec{
Domain: domain,
RequiredHSTSPolicies: hstsPolicy,
},
}
}


func waitForAvailableReplicas(t *testing.T, cl client.Client, ic *operatorv1.IngressController, timeout time.Duration, expectedReplicas int32) error {
ic = ic.DeepCopy()
name := types.NamespacedName{Namespace: ic.Namespace, Name: ic.Name}
Expand Down Expand Up @@ -2594,8 +2608,15 @@ func assertIngressControllerDeleted(t *testing.T, cl client.Client, ing *operato
}
}

func deleteIngressController(t *testing.T, cl client.Client, ic *operatorv1.IngressController, timeout time.Duration) error {
t.Helper()
func assertIngressConfigDeleted(t *testing.T, cl client.Client, ing *configv1.Ingress) {
if err := deleteIngressConfig(cl, ing, 2*time.Minute); err != nil {
t.Fatalf("WARNING: cloud resources may have been leaked! failed to delete ingressconfig %s: %v", ing.Name, err)
} else {
t.Logf("deleted ingressconfig %s", ing.Name)
}
}

func deleteIngressController(cl client.Client, ic *operatorv1.IngressController, timeout time.Duration) error {
name := types.NamespacedName{Namespace: ic.Namespace, Name: ic.Name}
if err := cl.Delete(context.TODO(), ic); err != nil {
return fmt.Errorf("failed to delete ingresscontroller: %v", err)
Expand All @@ -2617,6 +2638,27 @@ func deleteIngressController(t *testing.T, cl client.Client, ic *operatorv1.Ingr
return nil
}

func deleteIngressConfig(cl client.Client, ic *configv1.Ingress, timeout time.Duration) error {
name := types.NamespacedName{Namespace: ic.Namespace, Name: ic.Name}
if err := cl.Delete(context.TODO(), ic); err != nil {
return fmt.Errorf("failed to delete ingress config: %v", err)
}

err := wait.PollImmediate(1*time.Second, timeout, func() (bool, error) {
if err := cl.Get(context.TODO(), name, ic); err != nil {
if errors.IsNotFound(err) {
return true, nil
}
return false, nil
}
return false, nil
})
if err != nil {
return fmt.Errorf("timed out waiting for ingress config to be deleted: %v", err)
}
return nil
}

func createDefaultCertTestSecret(cl client.Client, name string) (*corev1.Secret, error) {
defaultCert := `-----BEGIN CERTIFICATE-----
MIIDIjCCAgqgAwIBAgIBBjANBgkqhkiG9w0BAQUFADCBoTELMAkGA1UEBhMCVVMx
Expand Down
19 changes: 19 additions & 0 deletions vendor/github.com/evanphx/json-patch/.travis.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 0 additions & 19 deletions vendor/github.com/evanphx/json-patch/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 15 additions & 18 deletions vendor/github.com/evanphx/json-patch/merge.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions vendor/github.com/evanphx/json-patch/patch.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions vendor/github.com/golang/protobuf/proto/registry.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit af9ce14

Please sign in to comment.