diff --git a/Makefile b/Makefile index 8c62720b68..e86a2ef4ab 100644 --- a/Makefile +++ b/Makefile @@ -97,6 +97,10 @@ ifeq ($(E2E_SKIP_BUILD), 0) docker tag kennethreitz/httpbin $(LOCAL_REGISTRY)/kennethreitz/httpbin docker push $(LOCAL_REGISTRY)/kennethreitz/httpbin + docker build -t test-backend:$(IMAGE_TAG) --build-arg ENABLE_PROXY=true ./test/e2e/testbackend + docker tag test-backend:$(IMAGE_TAG) $(LOCAL_REGISTRY)/test-backend:$(IMAGE_TAG) + docker push $(LOCAL_REGISTRY)/test-backend:$(IMAGE_TAG) + docker build -t apache/apisix-ingress-controller:$(IMAGE_TAG) --build-arg ENABLE_PROXY=true . docker tag apache/apisix-ingress-controller:$(IMAGE_TAG) $(LOCAL_REGISTRY)/apache/apisix-ingress-controller:$(IMAGE_TAG) docker push $(LOCAL_REGISTRY)/apache/apisix-ingress-controller:$(IMAGE_TAG) diff --git a/go.sum b/go.sum index 8a8bfeda74..21ccedcc80 100644 --- a/go.sum +++ b/go.sum @@ -516,6 +516,7 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= diff --git a/pkg/kube/apisix/apis/config/v1/types.go b/pkg/kube/apisix/apis/config/v1/types.go index 5c212a57f5..ee5aa648ea 100644 --- a/pkg/kube/apisix/apis/config/v1/types.go +++ b/pkg/kube/apisix/apis/config/v1/types.go @@ -122,6 +122,11 @@ type ApisixUpstreamConfig struct { // The health check configurations for the upstream. // +optional HealthCheck *HealthCheck `json:"healthCheck,omitempty" yaml:"healthCheck,omitempty"` + + // Set the client certificate when connecting to TLS upstream. + // +optional + TLSSecret *ApisixSecret `json:"tlsSecret,omitempty" yaml:"tlsSecret,omitempty"` + // Subsets groups the service endpoints by their labels. Usually used to differentiate // service versions. // +optional diff --git a/pkg/kube/apisix/apis/config/v1/zz_generated.deepcopy.go b/pkg/kube/apisix/apis/config/v1/zz_generated.deepcopy.go index 577501776a..0d234e014e 100644 --- a/pkg/kube/apisix/apis/config/v1/zz_generated.deepcopy.go +++ b/pkg/kube/apisix/apis/config/v1/zz_generated.deepcopy.go @@ -362,6 +362,11 @@ func (in *ApisixUpstreamConfig) DeepCopyInto(out *ApisixUpstreamConfig) { *out = new(HealthCheck) (*in).DeepCopyInto(*out) } + if in.TLSSecret != nil { + in, out := &in.TLSSecret, &out.TLSSecret + *out = new(ApisixSecret) + **out = **in + } if in.Subsets != nil { in, out := &in.Subsets, &out.Subsets *out = make([]ApisixUpstreamSubset, len(*in)) diff --git a/pkg/kube/translation/apisix_upstream.go b/pkg/kube/translation/apisix_upstream.go index d0e5b872bb..3c7b72d0ce 100644 --- a/pkg/kube/translation/apisix_upstream.go +++ b/pkg/kube/translation/apisix_upstream.go @@ -15,6 +15,8 @@ package translation import ( + "fmt" + configv1 "github.com/apache/apisix-ingress-controller/pkg/kube/apisix/apis/config/v1" apisixv1 "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1" ) @@ -74,7 +76,7 @@ func (t *translator) translateUpstreamScheme(scheme string, ups *apisixv1.Upstre return nil } switch scheme { - case apisixv1.SchemeHTTP, apisixv1.SchemeGRPC: + case apisixv1.SchemeHTTP, apisixv1.SchemeGRPC, apisixv1.SchemeHTTPS, apisixv1.SchemeGRPCS: ups.Scheme = scheme return nil default: @@ -146,6 +148,31 @@ func (t *translator) translateUpstreamHealthCheck(config *configv1.HealthCheck, return nil } +func (t translator) translateClientTLS(config *configv1.ApisixSecret, ups *apisixv1.Upstream) error { + if config == nil { + return nil + } + s, err := t.SecretLister.Secrets(config.Namespace).Get(config.Name) + if err != nil { + return &translateError{ + field: "tlsSecret", + reason: fmt.Sprintf("get secret failed, %v", err), + } + } + cert, key, err := t.ExtractKeyPair(s, true) + if err != nil { + return &translateError{ + field: "tlsSecret", + reason: fmt.Sprintf("extract cert and key from secret failed, %v", err), + } + } + ups.TLS = &apisixv1.ClientTLS{ + Cert: string(cert), + Key: string(key), + } + return nil +} + func (t *translator) translateUpstreamActiveHealthCheck(config *configv1.ActiveHealthCheck) (*apisixv1.UpstreamActiveHealthCheck, error) { var active apisixv1.UpstreamActiveHealthCheck switch config.Type { diff --git a/pkg/kube/translation/translator.go b/pkg/kube/translation/translator.go index 10426365b3..26273233bb 100644 --- a/pkg/kube/translation/translator.go +++ b/pkg/kube/translation/translator.go @@ -137,6 +137,9 @@ func (t *translator) TranslateUpstreamConfig(au *configv1.ApisixUpstreamConfig) if err := t.translateUpstreamRetriesAndTimeout(au.Retries, au.Timeout, ups); err != nil { return nil, err } + if err := t.translateClientTLS(au.TLSSecret, ups); err != nil { + return nil, err + } return ups, nil } diff --git a/pkg/types/apisix/v1/types.go b/pkg/types/apisix/v1/types.go index 4e3465c610..d9e5566a9a 100644 --- a/pkg/types/apisix/v1/types.go +++ b/pkg/types/apisix/v1/types.go @@ -50,6 +50,10 @@ const ( SchemeHTTP = "http" // SchemeGRPC represents the GRPC protocol. SchemeGRPC = "grpc" + // SchemeHTTPS represents the HTTPS protocol. + SchemeHTTPS = "https" + // SchemeGRPCS represents the GRPCS protocol. + SchemeGRPCS = "grpcs" // HealthCheckHTTP represents the HTTP kind health check. HealthCheckHTTP = "http" @@ -184,6 +188,13 @@ type Upstream struct { Scheme string `json:"scheme,omitempty" yaml:"scheme,omitempty"` Retries *int `json:"retries,omitempty" yaml:"retries,omitempty"` Timeout *UpstreamTimeout `json:"timeout,omitempty" yaml:"timeout,omitempty"` + TLS *ClientTLS `json:"tls,omitempty" yaml:"tls,omitempty"` +} + +// ClientTLS is tls cert and key use in mTLS +type ClientTLS struct { + Cert string `json:"client_cert,omitempty" yaml:"client_cert,omitempty"` + Key string `json:"client_key,omitempty" yaml:"client_key,omitempty"` } // UpstreamTimeout represents the timeout settings on Upstream. diff --git a/pkg/types/apisix/v1/zz_generated.deepcopy.go b/pkg/types/apisix/v1/zz_generated.deepcopy.go index 7115b74872..a30ef8ac0b 100644 --- a/pkg/types/apisix/v1/zz_generated.deepcopy.go +++ b/pkg/types/apisix/v1/zz_generated.deepcopy.go @@ -448,6 +448,11 @@ func (in *Upstream) DeepCopyInto(out *Upstream) { *out = new(UpstreamTimeout) **out = **in } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(ClientTLS) + **out = **in + } return } diff --git a/samples/deploy/crd/v1/ApisixUpstream.yaml b/samples/deploy/crd/v1/ApisixUpstream.yaml index 23dabdf8ba..3e2b7a00f3 100644 --- a/samples/deploy/crd/v1/ApisixUpstream.yaml +++ b/samples/deploy/crd/v1/ApisixUpstream.yaml @@ -80,6 +80,8 @@ spec: enum: - http - grpc + - https + - grpcs retries: type: integer minimum: 0 @@ -92,6 +94,19 @@ spec: type: string send: type: string + tlsSecret: + description: ApisixSecret describes the Kubernetes Secret name and namespace. + type: object + required: + - name + - namespace + properties: + name: + type: string + minLength: 1 + namespace: + type: string + minLength: 1 healthCheck: type: object anyOf: diff --git a/test/e2e/features/scheme.go b/test/e2e/features/scheme.go index a37085b0d6..d95135296a 100644 --- a/test/e2e/features/scheme.go +++ b/test/e2e/features/scheme.go @@ -16,12 +16,15 @@ package features import ( + "fmt" + "io/ioutil" "time" "github.com/onsi/ginkgo" "github.com/stretchr/testify/assert" "github.com/apache/apisix-ingress-controller/test/e2e/scaffold" + "github.com/apache/apisix-ingress-controller/test/e2e/testbackend/client" ) var _ = ginkgo.Describe("choose scheme", func() { @@ -119,4 +122,68 @@ spec: //assert.Nil(ginkgo.GinkgoT(), err) //assert.Equal(ginkgo.GinkgoT(), resp.Message, "Alex") }) + + ginkgo.It("grpcs", func() { + grpcSecret := `grpc-secret` + f, err := ioutil.ReadFile("testbackend/tls/server.pem") + assert.NoError(ginkgo.GinkgoT(), err, "read server cert") + serverCert := string(f) + + f, err = ioutil.ReadFile("testbackend/tls/server.key") + assert.NoError(ginkgo.GinkgoT(), err, "read server key") + serverKey := string(f) + + err = s.NewSecret(grpcSecret, serverCert, serverKey) + assert.NoError(ginkgo.GinkgoT(), err, "create server cert secret") + + assert.NoError(ginkgo.GinkgoT(), s.CreateResourceFromString(` +apiVersion: apisix.apache.org/v1 +kind: ApisixUpstream +metadata: + name: test-backend-service-e2e-test +spec: + scheme: grpcs +`)) + + assert.NoError(ginkgo.GinkgoT(), s.CreateResourceFromString(` +apiVersion: apisix.apache.org/v2beta2 +kind: ApisixRoute +metadata: + name: grpcs-route +spec: + http: + - name: rule1 + match: + hosts: + - e2e.apisix.local + paths: + - /helloworld.Greeter/SayHello + backends: + - serviceName: test-backend-service-e2e-test + servicePort: 50052 +`)) + + assert.NoError(ginkgo.GinkgoT(), s.CreateResourceFromString(fmt.Sprintf(` +apiVersion: apisix.apache.org/v1 +kind: ApisixTls +metadata: + name: grpc-secret +spec: + hosts: + - "e2e.apisix.local" + secret: + name: grpc-secret + namespace: %s +`, s.Namespace()))) + + time.Sleep(2 * time.Second) + ups, err := s.ListApisixUpstreams() + assert.Nil(ginkgo.GinkgoT(), err) + assert.Len(ginkgo.GinkgoT(), ups, 1) + assert.Equal(ginkgo.GinkgoT(), ups[0].Scheme, "grpcs") + + ca, err := ioutil.ReadFile("testbackend/tls/ca.pem") + assert.NoError(ginkgo.GinkgoT(), err, "read ca cert") + assert.NoError(ginkgo.GinkgoT(), client.RequestHello(s.GetAPISIXHTTPSEndpoint(), ca), "request apisix using grpc protocol") + }) }) diff --git a/test/e2e/go.mod b/test/e2e/go.mod index 643a62b9dd..51c3d2ecd4 100644 --- a/test/e2e/go.mod +++ b/test/e2e/go.mod @@ -4,6 +4,7 @@ go 1.14 require ( github.com/apache/apisix-ingress-controller v0.0.0-20210105024109-72e53386de5a + github.com/apache/apisix-ingress-controller/test/e2e/testbackend v0.0.0 github.com/gavv/httpexpect/v2 v2.2.0 github.com/gorilla/websocket v1.4.2 github.com/gruntwork-io/terratest v0.32.8 @@ -15,3 +16,4 @@ require ( ) replace github.com/apache/apisix-ingress-controller => ../../ +replace github.com/apache/apisix-ingress-controller/test/e2e/testbackend => ./testbackend diff --git a/test/e2e/go.sum b/test/e2e/go.sum index a98a9e0791..026db0b1a1 100644 --- a/test/e2e/go.sum +++ b/test/e2e/go.sum @@ -84,6 +84,7 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= @@ -122,6 +123,12 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= @@ -178,7 +185,11 @@ github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8 github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -328,6 +339,7 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gruntwork-io/gruntwork-cli v0.7.0 h1:YgSAmfCj9c61H+zuvHwKfYUwlMhu5arnQQLM4RH+CYs= github.com/gruntwork-io/gruntwork-cli v0.7.0/go.mod h1:jp6Z7NcLF2avpY8v71fBx6hds9eOFPELSuD/VPv7w00= github.com/gruntwork-io/terratest v0.32.8 h1:ccIRFH+e6zhSB5difg7baJec4FeOZNXpeIFlZZlKW2M= @@ -570,6 +582,7 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= @@ -676,6 +689,7 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0 h1:OI5t8sDa1Or+q8AeE+yKeB/SDYioSHAgcVljj9JIETY= @@ -776,6 +790,7 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -976,7 +991,10 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4 google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98 h1:LCO0fg4kb6WwkXQXRQQgUYsFeFb5taTX5WAx5O/Vt28= +google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -987,9 +1005,16 @@ google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc/examples v0.0.0-20211119181224-d542bfcee46d h1:z7z5Rvhjj2iWjI70Hbu3xrLgU4rssmF+DYscCaiY7RU= +google.golang.org/grpc/examples v0.0.0-20211119181224-d542bfcee46d/go.mod h1:gID3PKrg7pWKntu9Ss6zTLJ0ttC0X9IHgREOCZwbCVU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1025,6 +1050,7 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/test/e2e/ingress/upstream_tls.go b/test/e2e/ingress/upstream_tls.go new file mode 100644 index 0000000000..f079745dd9 --- /dev/null +++ b/test/e2e/ingress/upstream_tls.go @@ -0,0 +1,143 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ingress + +import ( + "fmt" + "io/ioutil" + "net/http" + "time" + + "github.com/onsi/ginkgo" + "github.com/stretchr/testify/assert" + + "github.com/apache/apisix-ingress-controller/test/e2e/scaffold" + "github.com/apache/apisix-ingress-controller/test/e2e/testbackend/client" +) + +var _ = ginkgo.Describe("ApisixUpstreams mTLS test", func() { + clientSecret := `client-secret` + + f, err := ioutil.ReadFile("testbackend/tls/client.pem") + assert.NoError(ginkgo.GinkgoT(), err, "read client cert") + clientCert := string(f) + + f, err = ioutil.ReadFile("testbackend/tls/client.key") + assert.NoError(ginkgo.GinkgoT(), err, "read client key") + clientKey := string(f) + + s := scaffold.NewDefaultV2Scaffold() + ginkgo.It("create ApisixUpstreams with http mTLS", func() { + //create client secret + err := s.NewSecret(clientSecret, clientCert, clientKey) + assert.NoError(ginkgo.GinkgoT(), err, "create client cert secret") + + err = s.NewApisixUpstreamsWithMTLS("test-backend-service-e2e-test", "https", clientSecret) + assert.NoError(ginkgo.GinkgoT(), err, "create ApisixUpstreams with client secret") + err = s.CreateResourceFromString(` +apiVersion: apisix.apache.org/v2beta2 +kind: ApisixRoute +metadata: + name: upstream-is-mtls.httpbin.local +spec: + http: + - backends: + - serviceName: test-backend-service-e2e-test + servicePort: 8443 + match: + hosts: + - 'upstream-is-mtls.httpbin.local' + paths: + - /* + plugins: + - name: proxy-rewrite + enable: true + config: + host: 'e2e.apisix.local' + name: upstream-is-mtls +`) + assert.NoError(ginkgo.GinkgoT(), err, "create ApisixRoute for backend that require mTLS") + time.Sleep(10 * time.Second) + apisixRoutes, err := s.ListApisixRoutes() + assert.NoError(ginkgo.GinkgoT(), err, "list routes error") + assert.Len(ginkgo.GinkgoT(), apisixRoutes, 1, "route number not expect") + + s.NewAPISIXClient().GET("/hello").WithHeader("Host", "upstream-is-mtls.httpbin.local").Expect().Status(http.StatusOK).Body().Raw() + }) + + ginkgo.It("create ApisixUpstreams with grpc mTLS", func() { + //create grpc secret for apisix grpc route + grpcSecret := `grpc-secret` + f, err := ioutil.ReadFile("testbackend/tls/server.pem") + assert.NoError(ginkgo.GinkgoT(), err, "read server cert") + serverCert := string(f) + + f, err = ioutil.ReadFile("testbackend/tls/server.key") + assert.NoError(ginkgo.GinkgoT(), err, "read server key") + serverKey := string(f) + + err = s.NewSecret(grpcSecret, serverCert, serverKey) + assert.NoError(ginkgo.GinkgoT(), err, "create server cert secret") + + //create client secret + err = s.NewSecret(clientSecret, clientCert, clientKey) + assert.NoError(ginkgo.GinkgoT(), err, "create client cert secret") + + err = s.NewApisixUpstreamsWithMTLS("test-backend-service-e2e-test", "grpcs", clientSecret) + assert.NoError(ginkgo.GinkgoT(), err, "create ApisixUpstreams with client secret") + + assert.NoError(ginkgo.GinkgoT(), s.CreateResourceFromString(` +apiVersion: apisix.apache.org/v2beta2 +kind: ApisixRoute +metadata: + name: grpcs-route +spec: + http: + - name: rule1 + match: + hosts: + - e2e.apisix.local + paths: + - /helloworld.Greeter/SayHello + backends: + - serviceName: test-backend-service-e2e-test + servicePort: 50053 +`)) + + assert.NoError(ginkgo.GinkgoT(), s.CreateResourceFromString(fmt.Sprintf(` +apiVersion: apisix.apache.org/v1 +kind: ApisixTls +metadata: + name: grpc-secret +spec: + hosts: + - "e2e.apisix.local" + secret: + name: grpc-secret + namespace: %s +`, s.Namespace()))) + + assert.NoError(ginkgo.GinkgoT(), err, "create ApisixRoute for backend that require mTLS") + time.Sleep(10 * time.Second) + apisixRoutes, err := s.ListApisixRoutes() + assert.NoError(ginkgo.GinkgoT(), err, "list routes error") + assert.Len(ginkgo.GinkgoT(), apisixRoutes, 1, "route number not expect") + + ca, err := ioutil.ReadFile("testbackend/tls/ca.pem") + assert.NoError(ginkgo.GinkgoT(), err, "read ca cert") + assert.NoError(ginkgo.GinkgoT(), client.RequestHello(s.GetAPISIXHTTPSEndpoint(), ca), "request apisix using grpc protocol") + }) +}) diff --git a/test/e2e/plugins/uri_blocker.go b/test/e2e/plugins/uri_blocker.go index e42afae88d..a506e38205 100644 --- a/test/e2e/plugins/uri_blocker.go +++ b/test/e2e/plugins/uri_blocker.go @@ -17,6 +17,7 @@ package plugins import ( "fmt" "net/http" + "time" "github.com/stretchr/testify/assert" @@ -181,6 +182,7 @@ spec: assert.Nil(ginkgo.GinkgoT(), s.CreateResourceFromString(ar)) + time.Sleep(2 * time.Second) err := s.EnsureNumApisixUpstreamsCreated(1) assert.Nil(ginkgo.GinkgoT(), err, "Checking number of upstreams") err = s.EnsureNumApisixRoutesCreated(1) diff --git a/test/e2e/scaffold/scaffold.go b/test/e2e/scaffold/scaffold.go index 2007a9d725..73173f64ea 100644 --- a/test/e2e/scaffold/scaffold.go +++ b/test/e2e/scaffold/scaffold.go @@ -56,16 +56,17 @@ type Options struct { } type Scaffold struct { - opts *Options - kubectlOptions *k8s.KubectlOptions - namespace string - t testing.TestingT - nodes []corev1.Node - etcdService *corev1.Service - apisixService *corev1.Service - httpbinDeployment *appsv1.Deployment - httpbinService *corev1.Service - finializers []func() + opts *Options + kubectlOptions *k8s.KubectlOptions + namespace string + t testing.TestingT + nodes []corev1.Node + etcdService *corev1.Service + apisixService *corev1.Service + httpbinDeployment *appsv1.Deployment + httpbinService *corev1.Service + testBackendService *corev1.Service + finializers []func() apisixAdminTunnel *k8s.Tunnel apisixHttpTunnel *k8s.Tunnel @@ -192,6 +193,11 @@ func (s *Scaffold) NewAPISIXClient() *httpexpect.Expect { }) } +// GetAPISIXHTTPSEndpoint get apisix https endpoint from tunnel map +func (s *Scaffold) GetAPISIXHTTPSEndpoint() string { + return s.apisixHttpsTunnel.Endpoint() +} + // NewAPISIXClientWithTCPProxy creates the HTTP client but with the TCP proxy of APISIX. func (s *Scaffold) NewAPISIXClientWithTCPProxy() *httpexpect.Expect { u := url.URL{ @@ -316,6 +322,11 @@ func (s *Scaffold) beforeEach() { k8s.WaitUntilServiceAvailable(s.t, s.kubectlOptions, s.httpbinService.Name, 3, 2*time.Second) + s.testBackendService, err = s.newTestBackend() + assert.Nil(s.t, err, "initializing test backend") + + k8s.WaitUntilServiceAvailable(s.t, s.kubectlOptions, s.testBackendService.Name, 3, 2*time.Second) + if s.opts.EnableWebhooks { err := generateWebhookCert(s.namespace) assert.Nil(s.t, err, "generate certs and create webhook secret") diff --git a/test/e2e/scaffold/test_backend.go b/test/e2e/scaffold/test_backend.go new file mode 100644 index 0000000000..2a1f71932e --- /dev/null +++ b/test/e2e/scaffold/test_backend.go @@ -0,0 +1,136 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package scaffold + +import ( + "fmt" + + "github.com/gruntwork-io/terratest/modules/k8s" + corev1 "k8s.io/api/core/v1" +) + +var ( + _testBackendDeploymentTemplate = ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: test-backend-deployment-e2e-test +spec: + replicas: %d + selector: + matchLabels: + app: test-backend-deployment-e2e-test + strategy: + rollingUpdate: + maxSurge: 50%% + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + labels: + app: test-backend-deployment-e2e-test + spec: + terminationGracePeriodSeconds: 0 + containers: + - livenessProbe: + failureThreshold: 3 + initialDelaySeconds: 2 + periodSeconds: 5 + successThreshold: 1 + tcpSocket: + port: 80 + timeoutSeconds: 2 + readinessProbe: + failureThreshold: 3 + initialDelaySeconds: 2 + periodSeconds: 5 + successThreshold: 1 + tcpSocket: + port: 80 + timeoutSeconds: 2 + image: "localhost:5000/test-backend:dev" + imagePullPolicy: IfNotPresent + name: test-backend-deployment-e2e-test + ports: + - containerPort: 80 + name: "http" + protocol: "TCP" + - containerPort: 443 + name: "https" + protocol: "TCP" + - containerPort: 8443 + name: "http-mtls" + protocol: "TCP" + - containerPort: 50051 + name: "grpc" + protocol: "TCP" + - containerPort: 50052 + name: "grpcs" + protocol: "TCP" + - containerPort: 50053 + name: "grpc-mtls" + protocol: "TCP" +` + _testBackendService = ` +apiVersion: v1 +kind: Service +metadata: + name: test-backend-service-e2e-test +spec: + selector: + app: test-backend-deployment-e2e-test + ports: + - name: http + port: 80 + protocol: TCP + targetPort: 80 + - name: https + port: 443 + protocol: TCP + targetPort: 443 + - name: http-mtls + port: 8443 + protocol: TCP + targetPort: 8443 + - name: grpc + port: 50051 + protocol: TCP + targetPort: 50051 + - name: grpcs + port: 50052 + protocol: TCP + targetPort: 50052 + - name: grpc-mtls + port: 50053 + protocol: TCP + targetPort: 50053 + type: ClusterIP +` +) + +func (s *Scaffold) newTestBackend() (*corev1.Service, error) { + backendDeployment := fmt.Sprintf(_testBackendDeploymentTemplate, 1) + if err := k8s.KubectlApplyFromStringE(s.t, s.kubectlOptions, backendDeployment); err != nil { + return nil, err + } + if err := k8s.KubectlApplyFromStringE(s.t, s.kubectlOptions, _testBackendService); err != nil { + return nil, err + } + svc, err := k8s.GetServiceE(s.t, s.kubectlOptions, "test-backend-service-e2e-test") + if err != nil { + return nil, err + } + return svc, nil +} diff --git a/test/e2e/scaffold/upstream_tls.go b/test/e2e/scaffold/upstream_tls.go new file mode 100644 index 0000000000..5bcd0a46df --- /dev/null +++ b/test/e2e/scaffold/upstream_tls.go @@ -0,0 +1,47 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +// +package scaffold + +import ( + "fmt" + + "github.com/gruntwork-io/terratest/modules/k8s" +) + +var ( + _apisixUpstreamsWithMTLSTemplate = ` +apiVersion: apisix.apache.org/v1 +kind: ApisixUpstream +metadata: + name: %s +spec: + scheme: %s + tlsSecret: + name: %s + namespace: %s +` +) + +// NewApisixUpstreamsWithMTLS new a ApisixUpstreams CRD +func (s *Scaffold) NewApisixUpstreamsWithMTLS(name, scheme, secretName string) error { + tls := fmt.Sprintf(_apisixUpstreamsWithMTLSTemplate, name, scheme, secretName, s.Namespace()) + if err := k8s.KubectlApplyFromStringE(s.t, s.kubectlOptions, tls); err != nil { + return err + } + return nil +} diff --git a/test/e2e/testbackend/Dockerfile b/test/e2e/testbackend/Dockerfile new file mode 100644 index 0000000000..b9bc23444f --- /dev/null +++ b/test/e2e/testbackend/Dockerfile @@ -0,0 +1,40 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +FROM golang:1.13.8 AS build-env + +ARG ENABLE_PROXY=false + +WORKDIR /build +COPY go.mod . +COPY go.sum . + +RUN if [ "$ENABLE_PROXY" = "true" ] ; then go env -w GOPROXY=https://goproxy.cn,direct ; fi \ + && go mod download + +COPY . . +RUN go build \ + -o test-backend \ + main.go + +FROM centos:centos7 + +WORKDIR /ingress-apisix + +COPY --from=build-env /build/test-backend . +COPY ./tls ./tls + +ENTRYPOINT ["/ingress-apisix/test-backend"] diff --git a/test/e2e/testbackend/client/client.go b/test/e2e/testbackend/client/client.go new file mode 100644 index 0000000000..051d46e1c6 --- /dev/null +++ b/test/e2e/testbackend/client/client.go @@ -0,0 +1,57 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package client + +import ( + "context" + "crypto/tls" + "crypto/x509" + "errors" + "log" + "time" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + hwpb "google.golang.org/grpc/examples/helloworld/helloworld" +) + +// RequestHello request grpc method in addr use specific ca +func RequestHello(addr string, ca []byte) error { + var ( + creds credentials.TransportCredentials + tlsConf tls.Config + certPool = x509.NewCertPool() + ) + if ok := certPool.AppendCertsFromPEM(ca); !ok { + return errors.New("failed to append ca certs") + } + tlsConf.RootCAs = certPool + creds = credentials.NewTLS(&tlsConf) + conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(creds), grpc.WithAuthority("e2e.apisix.local")) + if err != nil { + return err + } + defer conn.Close() + c := hwpb.NewGreeterClient(conn) + + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + r, err := c.SayHello(ctx, &hwpb.HelloRequest{Name: "apisix-ingress"}) + if err != nil { + return err + } + log.Printf("Get response %s", r.GetMessage()) + return nil +} diff --git a/test/e2e/testbackend/go.mod b/test/e2e/testbackend/go.mod new file mode 100644 index 0000000000..c9ad2acf54 --- /dev/null +++ b/test/e2e/testbackend/go.mod @@ -0,0 +1,17 @@ +module github.com/apache/apisix-ingress-controller/test/e2e/testbackend + +go 1.17 + +require ( + google.golang.org/grpc v1.42.0 + google.golang.org/grpc/examples v0.0.0-20211119181224-d542bfcee46d +) + +require ( + github.com/golang/protobuf v1.4.3 // indirect + golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect + golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect + golang.org/x/text v0.3.0 // indirect + google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98 // indirect + google.golang.org/protobuf v1.25.0 // indirect +) diff --git a/test/e2e/testbackend/go.sum b/test/e2e/testbackend/go.sum new file mode 100644 index 0000000000..e09f1b7486 --- /dev/null +++ b/test/e2e/testbackend/go.sum @@ -0,0 +1,119 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98 h1:LCO0fg4kb6WwkXQXRQQgUYsFeFb5taTX5WAx5O/Vt28= +google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc/examples v0.0.0-20211119181224-d542bfcee46d h1:z7z5Rvhjj2iWjI70Hbu3xrLgU4rssmF+DYscCaiY7RU= +google.golang.org/grpc/examples v0.0.0-20211119181224-d542bfcee46d/go.mod h1:gID3PKrg7pWKntu9Ss6zTLJ0ttC0X9IHgREOCZwbCVU= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/test/e2e/testbackend/main.go b/test/e2e/testbackend/main.go new file mode 100644 index 0000000000..6bb53a5e1a --- /dev/null +++ b/test/e2e/testbackend/main.go @@ -0,0 +1,184 @@ +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package main + +import ( + "context" + "crypto/tls" + "crypto/x509" + "fmt" + "io/ioutil" + "log" + "net" + "net/http" + "os" + "os/signal" + "syscall" + + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + ecpb "google.golang.org/grpc/examples/features/proto/echo" + hwpb "google.golang.org/grpc/examples/helloworld/helloworld" + "google.golang.org/grpc/reflection" +) + +// hwServer is used to implement helloworld.GreeterServer. +type hwServer struct { + hwpb.UnimplementedGreeterServer +} + +// SayHello implements helloworld.GreeterServer +func (s *hwServer) SayHello(ctx context.Context, in *hwpb.HelloRequest) (*hwpb.HelloReply, error) { + return &hwpb.HelloReply{Message: "Hello " + in.Name}, nil +} + +type ecServer struct { + ecpb.UnimplementedEchoServer +} + +func (s *ecServer) UnaryEcho(ctx context.Context, req *ecpb.EchoRequest) (*ecpb.EchoResponse, error) { + return &ecpb.EchoResponse{Message: req.Message}, nil +} + +func hello(w http.ResponseWriter, req *http.Request) { + log.Printf("%s %s%s from %v", req.Method, req.Host, req.RequestURI, req.RemoteAddr) + _, _ = fmt.Fprintf(w, "Hello World\n") +} + +func newDefaultCACertPool() *x509.CertPool { + caCert, err := ioutil.ReadFile("tls/ca.pem") + if err != nil { + log.Fatalf("failed to load ca cert: %v", err) + } + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + return caCertPool +} + +func loadTLSCredentials(clientAuth bool) credentials.TransportCredentials { + serverCert, err := tls.LoadX509KeyPair("tls/server.pem", "tls/server.key") + if err != nil { + log.Fatalf("failed to load server cert: %v", err) + } + var config *tls.Config + if clientAuth { + // Create the credentials and return it + config = &tls.Config{ + Certificates: []tls.Certificate{serverCert}, + ClientCAs: newDefaultCACertPool(), + ClientAuth: tls.RequireAndVerifyClientCert, + } + } else { + // Create the credentials and return it + config = &tls.Config{ + Certificates: []tls.Certificate{serverCert}, + ClientAuth: tls.NoClientCert, + } + } + return credentials.NewTLS(config) +} + +func main() { + http.HandleFunc("/hello", hello) + + go func() { + // curl http://e2e.apisix.local:80/hello --resolve e2e.apisix.local:80:127.0.0.1 + log.Printf("starting http server in 80") + log.Fatalln(http.ListenAndServe(":80", nil)) + }() + + go func() { + // curl https://e2e.apisix.local:443/hello --resolve e2e.apisix.local:443:127.0.0.1 --cacert ca.pem + log.Printf("starting https server in 443") + log.Fatalln(http.ListenAndServeTLS(":443", "tls/server.pem", "tls/server.key", nil)) + }() + + go func() { + // curl https://e2e.apisix.local:8443/hello --resolve e2e.apisix.local:8443:127.0.0.1 --cacert ca.pem --cert client.pem --key client.key + log.Printf("starting mtls http server in 8443") + tlsConfig := &tls.Config{ + ClientCAs: newDefaultCACertPool(), + ClientAuth: tls.RequireAndVerifyClientCert, + } + server := &http.Server{ + Addr: ":8443", + TLSConfig: tlsConfig, + } + log.Fatalln(server.ListenAndServeTLS("tls/server.pem", "tls/server.key")) + }() + + go func() { + // grpcurl -plaintext -d '{"name": "apisix-ingress"}' 127.0.0.1:50051 helloworld.Greeter/SayHello + lis, err := net.Listen("tcp", ":50051") + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + log.Printf("starting grpc server in %v\n", lis.Addr()) + s := grpc.NewServer() + + hwpb.RegisterGreeterServer(s, &hwServer{}) + ecpb.RegisterEchoServer(s, &ecServer{}) + reflection.Register(s) + + if err := s.Serve(lis); err != nil { + log.Fatalf("failed to serve: %v", err) + } + }() + + go func() { + // grpcurl -cacert ca.pem -servername e2e.apisix.local -d '{"name": "apisix-ingress"}' 127.0.0.1:50052 helloworld.Greeter/SayHello + lis, err := net.Listen("tcp", ":50052") + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + + log.Printf("starting grpcs server in %v\n", lis.Addr()) + s := grpc.NewServer( + grpc.Creds(loadTLSCredentials(false))) + + hwpb.RegisterGreeterServer(s, &hwServer{}) + ecpb.RegisterEchoServer(s, &ecServer{}) + reflection.Register(s) + + if err := s.Serve(lis); err != nil { + log.Fatalf("failed to serve: %v", err) + } + }() + + go func() { + // grpcurl -key client.key -cert client.pem -cacert ca.pem -servername e2e.apisix.local -d '{"name": "apisix-ingress"}' 127.0.0.1:50053 helloworld.Greeter/SayHello + lis, err := net.Listen("tcp", ":50053") + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + log.Printf("starting mtls grpc server in %v\n", lis.Addr()) + s := grpc.NewServer( + grpc.Creds(loadTLSCredentials(true))) + + hwpb.RegisterGreeterServer(s, &hwServer{}) + ecpb.RegisterEchoServer(s, &ecServer{}) + reflection.Register(s) + + if err := s.Serve(lis); err != nil { + log.Fatalf("failed to serve: %v", err) + } + }() + + sigCh := make(chan os.Signal, 1) + signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) + + sig := <-sigCh + log.Printf("signal %d (%s) received\n", sig, sig.String()) +} diff --git a/test/e2e/testbackend/tls/ca.pem b/test/e2e/testbackend/tls/ca.pem new file mode 100644 index 0000000000..f15cbfeab8 --- /dev/null +++ b/test/e2e/testbackend/tls/ca.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDzTCCArWgAwIBAgIJAKS3/P2juXqaMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UEBwwISGFuZ3pob3UxDzAN +BgNVBAoMBkFQSVNJWDEPMA0GA1UECwwGQVBJU0lYMQ8wDQYDVQQDDAZBUElTSVgx +FTATBgkqhkiG9w0BCQEWBkFQSVNJWDAeFw0yMTExMjExMzU1NDVaFw0yNjExMjAx +MzU1NDVaMH0xCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UE +BwwISGFuZ3pob3UxDzANBgNVBAoMBkFQSVNJWDEPMA0GA1UECwwGQVBJU0lYMQ8w +DQYDVQQDDAZBUElTSVgxFTATBgkqhkiG9w0BCQEWBkFQSVNJWDCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAK0PqU4kDz2XtUMZ7sSbfmmPdWhVVujJZ2fB +Vc39EvbEhSYpf1heHn4Fi1JvKnqMQYbpBhh0o/KEi7jCInuEMFZg/N3RHLsvQsri +wUJwGiiaxrf4JwUR5CYQD/QqbZoMblZgYd6ktaPjbPJHaEoEU/InV8GNaMXEe+D6 +cKILuOfVu5Yo6GhSkG/Wa9bjf26P8Gk9hdPLUDmUhCJ9JPPkPJCejNLL+serbApq +NH2rQA20Ka6KbPJ1tBagPLrHu8GsUvu/VqhUS9cuwM/5IbvvRQhdsCZKQgXeik40 +ikI6yNa4Xk+hPdWuVzmJ7G4K29BGz7ctg53NQFQArziyC8kB4LkCAwEAAaNQME4w +HQYDVR0OBBYEFOJGVMCGMfWyb5vQ4a6QZYfDHGnzMB8GA1UdIwQYMBaAFOJGVMCG +MfWyb5vQ4a6QZYfDHGnzMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB +AE0f5JbZZ8VfDoPczMH4YT54LgwNbBETnxS0XB65QRhux4Pol+3pZr0tARJKo8lF +3OolScgBs46t+E8RWlAFZ8RSX93tLBxiZ+DfjkGNGPThfVLgDpuf+wjz6KMWZGPo +s0KXs5dMxL+HBvnxEXCH97jxS1yVsxg4LO2QyzyTdDW9jm1GlFZQ5eZ9krZcCj1v +YG+N2EjkG7WeCucC2/SJIoxma5lNgnnlj06Y0Mx4Kle3D6s38KeQr0gVqvBTDIXj +dUhPJdR6eJH2y/JzXTp2TtYf8Q07SMjwIA8BOoy/s8tKqwUu/8mAzdE1JwnCBWGa +tJCe2nAIwIHaDcGbH2SEAzE= +-----END CERTIFICATE----- diff --git a/test/e2e/testbackend/tls/client.key b/test/e2e/testbackend/tls/client.key new file mode 100644 index 0000000000..d8cf2d7a9c --- /dev/null +++ b/test/e2e/testbackend/tls/client.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAzraMSOx/boohJ5rE++FShQlGiuFK5ME2pT4DK3gl3jn2YYEk +1NwO0vgyIG8JHR+coSPi5swx7wmlbBPED+I+IgLQ/I3UAVJrlHZDnbNAtl5mQQRb +kkMiLo6H531rOpPVgVNG/9XWtTlDsZRooPq6kV/RAB224mEY7RLax0mnqwAM3ZKN +3bzDva6tQMx5rQ/HwGPhQ7XV6KEZ8kumlqS+H1VlHrEgm0PLdAR1WrzhmDfF30yv +0ui7845HkeiYqTQ0Ajx7FENrhRRFfZPRrxvVMf3hI9sjLZq4icSADSnx2d8mRml4 +2NnvXOi37rmwzCG4v7CaITQoK+RCBRg4dq7NIQIDAQABAoIBAHGCFghZLSRy3v/T +YcV6FgkNbdoHGkwAuNQF+FGfWRPtOhiShLoJ2G4KceQTdKq0WBq4DPl1ORosbtSp +Cek676lXaJC2BKtxKbfNNRXcf3Vk4rti/DGVgaiVBZWc7gutb/ji1MLZFlxPBJf3 +iXiUFWyMc8SfjHREox5TUyVJkbM4iC1VTd1J8CfZjcM0kXaQoT1/xpesYnN4OzcR +/uDJpzqRC1gQpflhpPLpp3k+5SGRzIHl9/3EKbAOEWz1quIZEpThHAd6MO/SMwjK +gUPkh7JysRL7YwbGrOD4bVmy/s9bt5IHiXwsqOwYyTzfaUi0S11H6+9k9KjECsGS +vZeoyH0CgYEA6YDNDbaCybKHk3OqHZxaVp7dkKaDs5Xl2cWko35KQZlA9HFkbwrE +c9LwwYRpVtx3XMBuS+AAqdIK55re5fPix6x46sIXIeYdxvJCgZgHa2Q9fxuC8eKY +gbpIPgbDq5aSRA4I8OBiue3WNOUCZcN9+YP8kP6NdxNI4Mq1Fd735SsCgYEA4qD8 +/jXlcuY97mx+FfWBYNb3UKdN9j9y0kmKH7GUDqw4sS0Iao4z0jVLFjv+D69NnAkM +NAwWfdD1qOpjm+dKvudiFe0LGWz5XLYseIAJU3Pjg4E5VyhwM39/OqlUKqF+9RZm +wH930d9e9c//gpOYGfbP9mN4xcjhAwuyVnD/yOMCgYEAy/Wapxi9wypzbCPC+1xg +OHtJ85jPP2V2wTL3bWvZttUDvMDzRl80XCtr6s0bKiknBdh8P0Bps+xpZAaOHnRa +qakIcZ6ZkB2t8uIXn5VJHdAQO1+vkFMqfV5Wzf8gmVfLaTCNNMH62odZ7RgAcR1C +g1l7mrcOoG0y4k+Nv43kIMMCgYBoxlsQwCQrYc0CHMCSMGW3OssuS5scnKreE8e6 +7WNxAShYqWQ5tzK4HZFwXx4PbFGqMPimW2xOkLvycyLIIj+JUPok/ulhwOLsfQDE +WRV2sp5d3vF+nSB6fph4q25RI0bJ0qiAmK3xpp6FcLtFSC1K27O7yrM8Zam5ub+i +fS2UVwKBgEhQD9Vt11lNZFQ5d7DTODo8j3GLhaQB2f9eVY5lGO136vTDjeMCflRq +nUlQzhq37d7V/jPNn4snO5WpqNdvGX61GArVmGf3MTUlzThHHIL3QXORuS3bWNaN +RxsBN0Ph/02rlKQ50Yq1XpUmEyDjTwrIaqTcmZw3pPqyQRicbeOD +-----END RSA PRIVATE KEY----- diff --git a/test/e2e/testbackend/tls/client.pem b/test/e2e/testbackend/tls/client.pem new file mode 100644 index 0000000000..19a9ed8ca6 --- /dev/null +++ b/test/e2e/testbackend/tls/client.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDxDCCAqygAwIBAgIJAMF/G0VblXFoMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UEBwwISGFuZ3pob3UxDzAN +BgNVBAoMBkFQSVNJWDEPMA0GA1UECwwGQVBJU0lYMQ8wDQYDVQQDDAZBUElTSVgx +FTATBgkqhkiG9w0BCQEWBkFQSVNJWDAeFw0yMTExMjIwMTQyMzRaFw00NDA2MjQw +MTQyMzRaMHIxCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UE +BwwISGFuZ3pob3UxDzANBgNVBAoMBkFQSVNJWDEXMBUGA1UECwwOQVBJU0lYX0lO +R1JFU1MxEzARBgNVBAMMCmUyZS5jbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDOtoxI7H9uiiEnmsT74VKFCUaK4UrkwTalPgMreCXeOfZhgSTU +3A7S+DIgbwkdH5yhI+LmzDHvCaVsE8QP4j4iAtD8jdQBUmuUdkOds0C2XmZBBFuS +QyIujofnfWs6k9WBU0b/1da1OUOxlGig+rqRX9EAHbbiYRjtEtrHSaerAAzdko3d +vMO9rq1AzHmtD8fAY+FDtdXooRnyS6aWpL4fVWUesSCbQ8t0BHVavOGYN8XfTK/S +6LvzjkeR6JipNDQCPHsUQ2uFFEV9k9GvG9Ux/eEj2yMtmriJxIANKfHZ3yZGaXjY +2e9c6LfuubDMIbi/sJohNCgr5EIFGDh2rs0hAgMBAAGjUjBQMB8GA1UdIwQYMBaA +FOJGVMCGMfWyb5vQ4a6QZYfDHGnzMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgTwMBUG +A1UdEQQOMAyCCmUyZS5jbGllbnQwDQYJKoZIhvcNAQELBQADggEBAJOkHKTf4cZO +wCZJ5poANx6VWhhp7L1hZD4Pp18sRmpd3mIEns2MfUNbMimEtlEj6UNO7/l6TozT +P3URonPow58MfH8y+zwH06bxpbZ0zFEP8HqwDXmOwsZnzB6JowufvB9os4QYdR+g +lPtxZlE+wtm29curT7Rq+DD+VilZB9ywm5UZ+FdqtnVK2cvAhzEO1U8wuJeNzKKO +SYrSOtnEPCOIlL9bYbRioDAK64iZKjWSn4ETQnVwcEjNcWPhJO3DszpvZ8Y3g3x0 +hoQV50Xjbm7sLPXjB+RqnhpqLd3Fsv4YCATIk6A+5xT53jreKSsPhwRwBeZmoD7+ +OXXcUuyg3iY= +-----END CERTIFICATE----- diff --git a/test/e2e/testbackend/tls/server.key b/test/e2e/testbackend/tls/server.key new file mode 100644 index 0000000000..c4a155a40f --- /dev/null +++ b/test/e2e/testbackend/tls/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEA55GnXAb+Hm9xpyxUc8SBJ6i2AAHOPpuj4ed5ZScf1QXxafkx +e8FAZ6deLd7/nOimchLhbIr1lw8+5WbNdnrAr9oX7Vxgt77DZi+EYk9v7K3jSnt8 +9Glwe8SiPze/KldBTrOi/Gk23jiBoEDvx4QB5m9Zgdk9oCSx4bs4PCucKfJ5u5UM +m9ote8GlzWNEB2Q9yfDKTWPNFHXtq/WSna001k1Oqa8+LB7ZtdXngR4Fhcv5f7jS +EYxTq1F19ZTzwMLYa/s3Du75aFQJxEdxfVFlE/34BaoS8BQr0+4C/LGsq5Caz46j +1MYX5sbd99szNfmiKeTA80BTQzf5wTBO0XVcxwIDAQABAoIBAQDBRh1EPwXcCzH1 +0JcQJMOTgUmeSeOE98xZoSP+HCCCYLp0s6rsWohRuyxs5sG7iaZacY26VWTTVsMt +HpeAOsYWP9ZWoxKKaeqWoDRDBYAqL5wUL2tEZ7idZKnyT6n7QeZdNKtlNr+3y7vN +MEWw5WnclbVEHjhEMDxTZjpyZgeqLYMlIq0mPcNgRyECZ70a+3BGkW9GmF5xAcki +cvUyE0H69Z9KNCOEjwQ+HV417yuCezu2I9GoQuUa/24dnBzrwzEvVvvKETK+IqR1 +bx8jzMjK/x0BOqAzrR6rENSHjw9XsUn0EiZlynz7nNe+TtcFaZ/6HSSQ3zZVbROK +qeQmqTuJAoGBAP/LxDQ36dh8PaWq804jAn0J/Sbzqxi0isjgwQhbERVMqzObEQ4L +1srSxA+JBO+rYstqxd6f0ahlwX/jBoU9YeVLNiA+SX/BH+FpMJf8NJGE3WV+rLs9 +s+9oyCjlu2cg7UluJIJb8JlVmv32p5DTc19Arl+9Y87jm9lgkYtscjGNAoGBAOfA +8K7dHPpURo7c4csrEraUbXaeDH5IycJuBdkJVi2O8UAtHwZTB9aDjKsOkgEp7/Qh +X1NeUDP7/g+5aFsqf04zj1dxbuyWQBpyLuEqh6+JdI//mCfQCry8/y+zt2rmVVa4 +CgWA75P226aXrOjj6Lrm8SXLs9AScjhxqv+BAxCjAoGAbkwLz0Ro1gtEfcIH5aJc ++VOsT/ZzyVRYH6QiOBskc526mKb9pKPgO1bEabp4YWvyTqo8pfEd81HlLOLUtfEw +3DEhJqgVAzxgJc84v+BlPnYfDRuhGZ/SjaIN5OyicSaWiroujfNc/JEYIvgPavhy +YBlA11GPzu8ADayBNbBOUSUCgYBzItCwHxvZZesT6LqohAKtAHqNdqHAT4sk9CIl +nFTbF2vVtVT3gGKheQN2rCtvNpWGlNnWAkIYQXYL+9HTkP5kLItnJuyzz0WTneya +YtW8KK7nJ1VBWkMrVz30RfW2vy3gglhAOblMqlSfpDT8EtY5nKhrXZM8qR1j21zX +yRFrvwKBgGIFkwhglyM+jKEwQQDxUPo5BH6H0gtZRqzctByM2v5QqowNni/Dg25D +fq6gSWvYLhqSsFHAwjk3pOPJrHpNMC4oQHlKIoaRDO3w02uwGgyAYwgVm3SQTngo +n8+oYN1bR/DxOSRGBPbw1n0idCC2yHFRrB/DWIpSLGhXApHLnF1F +-----END RSA PRIVATE KEY----- diff --git a/test/e2e/testbackend/tls/server.pem b/test/e2e/testbackend/tls/server.pem new file mode 100644 index 0000000000..52d6beca7f --- /dev/null +++ b/test/e2e/testbackend/tls/server.pem @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID0DCCArigAwIBAgIJAMF/G0VblXFnMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV +BAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UEBwwISGFuZ3pob3UxDzAN +BgNVBAoMBkFQSVNJWDEPMA0GA1UECwwGQVBJU0lYMQ8wDQYDVQQDDAZBUElTSVgx +FTATBgkqhkiG9w0BCQEWBkFQSVNJWDAeFw0yMTExMjIwMTI5MDJaFw00NDA2MjQw +MTI5MDJaMHgxCzAJBgNVBAYTAkNOMREwDwYDVQQIDAhaaGVqaWFuZzERMA8GA1UE +BwwISGFuZ3pob3UxDzANBgNVBAoMBkFQSVNJWDEXMBUGA1UECwwOQVBJU0lYX0lO +R1JFU1MxGTAXBgNVBAMMEGUyZS5hcGlzaXgubG9jYWwwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDnkadcBv4eb3GnLFRzxIEnqLYAAc4+m6Ph53llJx/V +BfFp+TF7wUBnp14t3v+c6KZyEuFsivWXDz7lZs12esCv2hftXGC3vsNmL4RiT2/s +reNKe3z0aXB7xKI/N78qV0FOs6L8aTbeOIGgQO/HhAHmb1mB2T2gJLHhuzg8K5wp +8nm7lQyb2i17waXNY0QHZD3J8MpNY80Ude2r9ZKdrTTWTU6prz4sHtm11eeBHgWF +y/l/uNIRjFOrUXX1lPPAwthr+zcO7vloVAnER3F9UWUT/fgFqhLwFCvT7gL8sayr +kJrPjqPUxhfmxt332zM1+aIp5MDzQFNDN/nBME7RdVzHAgMBAAGjWDBWMB8GA1Ud +IwQYMBaAFOJGVMCGMfWyb5vQ4a6QZYfDHGnzMAkGA1UdEwQCMAAwCwYDVR0PBAQD +AgTwMBsGA1UdEQQUMBKCEGUyZS5hcGlzaXgubG9jYWwwDQYJKoZIhvcNAQELBQAD +ggEBABQCbGzsrK/3OnpJghSAklGkD26HHAGFLEQ9eC389OjNSFek7O6tPI1ul+Ty +7vunE/KRNDzR6Dv2U7OsGpixwE2I1m9tyIMu17muGR3nVwOLK4+qIocsn2q4nGnY +UniI29NZBDSz1PZCbk+5vKthSo+khMXAIdvBy34gyQMKjQe7c6rwQ8iJHYagzxxH +cK1Dtlo9u7AiPmjdJb5sTKTFOIRhrvpjhi9Dsn15P1/bkPAl+Pjuf+LZz04cWZ0k ++8LMttXvzYw70pvrb65AnDpKQbN3BiY//wD88ifAAA07SZvzMnsUNfrFuLYUw4Wu +3OCryTj//5zgzPaby5MXEnRwooI= +-----END CERTIFICATE-----