...

Source file src/github.com/chaos-mesh/chaos-mesh/e2e-test/e2e/chaos/httpchaos/http_tls.go

Documentation: github.com/chaos-mesh/chaos-mesh/e2e-test/e2e/chaos/httpchaos

     1  // Copyright 2022 Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  
    16  package httpchaos
    17  
    18  import (
    19  	"context"
    20  	"crypto/tls"
    21  	"crypto/x509"
    22  	"embed"
    23  	"encoding/json"
    24  	"fmt"
    25  	"net/http"
    26  	"os"
    27  	"os/exec"
    28  	"time"
    29  
    30  	. "github.com/onsi/ginkgo/v2"
    31  	v1 "k8s.io/api/core/v1"
    32  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    33  	"k8s.io/apimachinery/pkg/util/wait"
    34  	"k8s.io/client-go/kubernetes"
    35  	"k8s.io/kubernetes/test/e2e/framework"
    36  	"sigs.k8s.io/controller-runtime/pkg/client"
    37  
    38  	"github.com/chaos-mesh/chaos-mesh/api/v1alpha1"
    39  	"github.com/chaos-mesh/chaos-mesh/e2e-test/e2e/util"
    40  )
    41  
    42  //go:embed keys
    43  var content embed.FS
    44  
    45  type TLSServerKeys struct {
    46  	Cert []byte `json:"cert"`
    47  	Key  []byte `json:"key"`
    48  }
    49  
    50  func setupHTTPS(cli *http.Client, serverIP string) (TLSServerKeys, []byte) {
    51  	c, err := content.ReadDir("keys")
    52  	framework.ExpectNoError(err, "read key dir error")
    53  	var key []byte
    54  	var ca []byte
    55  	for _, f := range c {
    56  		if f.IsDir() {
    57  			continue
    58  		}
    59  		b, err := content.ReadFile("keys/" + f.Name())
    60  		framework.ExpectNoError(err, "read key file error")
    61  		switch f.Name() {
    62  		case "server.key":
    63  			key = b
    64  		case "ca.crt":
    65  			ca = b
    66  		}
    67  		err = os.WriteFile(f.Name(), b, 0644)
    68  		framework.ExpectNoError(err, "write key file error")
    69  	}
    70  
    71  	f, err := os.OpenFile("server.ext", os.O_APPEND|os.O_WRONLY, 0644)
    72  	if err != nil {
    73  		framework.ExpectNoError(err, "open server.ext file error")
    74  	}
    75  	if _, err = f.WriteString(fmt.Sprint("IP.1 = " + serverIP)); err != nil {
    76  		framework.ExpectNoError(err, "write server.ext file error")
    77  	}
    78  	err = f.Close()
    79  	framework.ExpectNoError(err, "close server.ext file error")
    80  
    81  	cmdStr := "openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650 -sha256 -extfile server.ext"
    82  	cmd := exec.Command("bash", "-c", cmdStr)
    83  	output, err := cmd.CombinedOutput()
    84  	if err != nil {
    85  		framework.ExpectNoError(err, "run openssl cmd error: "+string(output))
    86  	}
    87  	crt, err := os.ReadFile("server.crt")
    88  	framework.ExpectNoError(err, "read server.crt file error")
    89  
    90  	roots := x509.NewCertPool()
    91  	caPk, err := os.ReadFile("ca.crt")
    92  	if err != nil {
    93  		panic(err)
    94  	}
    95  	ok := roots.AppendCertsFromPEM(caPk)
    96  	framework.ExpectEqual(ok, true, "failed to parse root certificate")
    97  
    98  	cli.Transport = &http.Transport{
    99  		TLSClientConfig: &tls.Config{
   100  			RootCAs: roots,
   101  		},
   102  	}
   103  
   104  	return TLSServerKeys{
   105  		Cert: crt,
   106  		Key:  key,
   107  	}, ca
   108  }
   109  
   110  func TestcaseHttpTLSThenRecover(
   111  	ns string,
   112  	kubeCli kubernetes.Interface,
   113  	cli client.Client,
   114  	c HTTPE2EClient,
   115  	port uint16,
   116  	tlsPort uint16,
   117  ) {
   118  	serverKeys, ca := setupHTTPS(c.C, c.IP)
   119  	ctx, cancel := context.WithCancel(context.Background())
   120  	defer cancel()
   121  
   122  	By("waiting on e2e helper ready")
   123  	err := util.WaitHTTPE2EHelperReady(*c.C, c.IP, port)
   124  	framework.ExpectNoError(err, "wait e2e helper ready error")
   125  	By("create http delay chaos CRD objects")
   126  
   127  	body, err := json.Marshal(serverKeys)
   128  	framework.ExpectNoError(err, "marshal server keys error")
   129  	err = util.SetupHTTPE2EHelperTLSConfig(*c.C, c.IP, port, tlsPort, body)
   130  	framework.ExpectNoError(err, "setup e2e helper tls config error")
   131  	delay := "1ms"
   132  
   133  	_, err = kubeCli.CoreV1().Secrets(ns).Create(ctx, &v1.Secret{
   134  		ObjectMeta: metav1.ObjectMeta{
   135  			Name:      "http-tls",
   136  			Namespace: ns,
   137  		},
   138  		Data: map[string][]byte{
   139  			"ca.crt":     ca,
   140  			"server.crt": serverKeys.Cert,
   141  			"server.key": serverKeys.Key,
   142  		},
   143  	}, metav1.CreateOptions{})
   144  	framework.ExpectNoError(err, "create secret error")
   145  	caName := "ca.crt"
   146  	httpChaos := &v1alpha1.HTTPChaos{
   147  		ObjectMeta: metav1.ObjectMeta{
   148  			Name:      "http-chaos",
   149  			Namespace: ns,
   150  		},
   151  		Spec: v1alpha1.HTTPChaosSpec{
   152  			PodSelector: v1alpha1.PodSelector{
   153  				Selector: v1alpha1.PodSelectorSpec{
   154  					GenericSelectorSpec: v1alpha1.GenericSelectorSpec{
   155  						Namespaces:     []string{ns},
   156  						LabelSelectors: map[string]string{"app": "http"},
   157  					},
   158  				},
   159  				Mode: v1alpha1.OneMode,
   160  			},
   161  			Port:   8081,
   162  			Target: "Request",
   163  			PodHttpChaosActions: v1alpha1.PodHttpChaosActions{
   164  				Delay: &delay,
   165  			},
   166  			TLS: &v1alpha1.PodHttpChaosTLS{
   167  				SecretName:      "http-tls",
   168  				SecretNamespace: ns,
   169  				CertName:        "server.crt",
   170  				KeyName:         "server.key",
   171  				CAName:          &caName,
   172  			},
   173  		},
   174  	}
   175  	err = cli.Create(ctx, httpChaos)
   176  	framework.ExpectNoError(err, "create http chaos error")
   177  
   178  	By("waiting for HTTP pong")
   179  	err = wait.PollImmediate(1*time.Second, 1*time.Minute, func() (bool, error) {
   180  		err := util.WaitHTTPE2EHelperTLSReady(*c.C, c.IP, tlsPort)
   181  		if err != nil {
   182  			return false, err
   183  		}
   184  		return true, nil
   185  	})
   186  	framework.ExpectNoError(err, "http chaos doesn't work as expected")
   187  	By("apply http chaos successfully")
   188  
   189  	By("delete chaos CRD objects")
   190  	// delete chaos CRD
   191  	err = cli.Delete(ctx, httpChaos)
   192  	framework.ExpectNoError(err, "failed to delete http chaos")
   193  }
   194