Add TLS origination doc test (#7367)

* Add TLS origination doc test

* Fix build

* Add header

* lint
This commit is contained in:
John Howard 2020-05-21 14:10:26 -07:00 committed by GitHub
parent e320eb98c5
commit e9e963a617
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 327 additions and 30 deletions

View File

@ -79,7 +79,7 @@ be done by the egress gateway, as opposed to by the sidecar in the previous exam
1. Verify that your `ServiceEntry` was applied correctly by sending a request to [http://edition.cnn.com/politics](https://edition.cnn.com/politics).
{{< text bash >}}
$ kubectl exec -it $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
$ kubectl exec $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
HTTP/1.1 301 Moved Permanently
...
location: https://edition.cnn.com/politics
@ -179,7 +179,7 @@ be done by the egress gateway, as opposed to by the sidecar in the previous exam
1. Send an HTTP request to [http://edition.cnn.com/politics](https://edition.cnn.com/politics).
{{< text bash >}}
$ kubectl exec -it $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
$ kubectl exec $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
HTTP/1.1 200 OK
...
content-length: 150793
@ -523,7 +523,7 @@ to hold the configuration of the NGINX server:
Normally, a DNS entry exists for the destination hostname and you would not use the `--resolve` option of `curl`.
{{< text bash >}}
$ kubectl exec -it $SOURCE_POD -c sleep -- curl -v --resolve nginx.example.com:443:1.1.1.1 --cacert /etc/nginx-ca-certs/ca-chain.cert.pem --cert /etc/nginx-client-certs/tls.crt --key /etc/nginx-client-certs/tls.key https://nginx.example.com
$ kubectl exec $SOURCE_POD -c sleep -- curl -v --resolve nginx.example.com:443:1.1.1.1 --cacert /etc/nginx-ca-certs/ca-chain.cert.pem --cert /etc/nginx-client-certs/tls.crt --key /etc/nginx-client-certs/tls.key https://nginx.example.com
...
Server certificate:
subject: C=US; ST=Denial; L=Springfield; O=Dis; CN=nginx.example.com
@ -550,7 +550,7 @@ to hold the configuration of the NGINX server:
1. Verify that the server requires the client's certificate:
{{< text bash >}}
$ kubectl exec -it $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl -k --resolve nginx.example.com:443:1.1.1.1 https://nginx.example.com
$ kubectl exec $(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name}) -c sleep -- curl -k --resolve nginx.example.com:443:1.1.1.1 https://nginx.example.com
<html>
<head><title>400 No required SSL certificate was sent</title></head>
<body bgcolor="white">
@ -744,7 +744,7 @@ to hold the configuration of the NGINX server:
1. Send an HTTP request to `http://nginx.example.com`:
{{< text bash >}}
$ kubectl exec -it $SOURCE_POD -c sleep -- curl -s --resolve nginx.example.com:80:1.1.1.1 http://nginx.example.com
$ kubectl exec $SOURCE_POD -c sleep -- curl -s --resolve nginx.example.com:80:1.1.1.1 http://nginx.example.com
<!DOCTYPE html>
<html>
<head>

View File

@ -3,6 +3,7 @@ title: Egress TLS Origination
description: Describes how to configure Istio to perform TLS origination for traffic to external services.
keywords: [traffic-management,egress]
weight: 20
test: true
aliases:
- /docs/examples/advanced-gateways/egress-tls-origination/
---
@ -60,7 +61,7 @@ This time, however, use a single `ServiceEntry` to enable both HTTP and HTTPS ac
1. Create a `ServiceEntry` and `VirtualService` to enable access to `edition.cnn.com`:
{{< text bash >}}
{{< text syntax=bash snip_id=apply_simple >}}
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
@ -101,17 +102,14 @@ This time, however, use a single `ServiceEntry` to enable both HTTP and HTTPS ac
1. Make a request to the external HTTP service:
{{< text bash >}}
$ kubectl exec -it $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
{{< text syntax=bash snip_id=curl_simple >}}
$ kubectl exec "${SOURCE_POD}" -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
HTTP/1.1 301 Moved Permanently
...
location: https://edition.cnn.com/politics
...
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
Content-Length: 151654
HTTP/2 200
...
{{< /text >}}
@ -137,7 +135,7 @@ Both of these issues can be resolved by configuring Istio to perform TLS origina
1. Redefine your `ServiceEntry` and `VirtualService` from the previous section to rewrite the HTTP request port
and add a `DestinationRule` to perform TLS origination.
{{< text bash >}}
{{< text syntax=bash snip_id=apply_origination >}}
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
@ -198,12 +196,9 @@ Both of these issues can be resolved by configuring Istio to perform TLS origina
1. Send an HTTP request to `http://edition.cnn.com/politics`, as in the previous section:
{{< text bash >}}
$ kubectl exec -it $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
{{< text syntax=bash snip_id=curl_origination_http >}}
$ kubectl exec "${SOURCE_POD}" -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
Content-Length: 151654
...
{{< /text >}}
@ -219,12 +214,9 @@ Both of these issues can be resolved by configuring Istio to perform TLS origina
1. Note that the applications that used HTTPS to access the external service continue to work as before:
{{< text bash >}}
$ kubectl exec -it $SOURCE_POD -c sleep -- curl -sL -o /dev/null -D - https://edition.cnn.com/politics
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
Content-Length: 151654
{{< text syntax=bash snip_id=curl_origination_https >}}
$ kubectl exec "${SOURCE_POD}" -c sleep -- curl -sL -o /dev/null -D - https://edition.cnn.com/politics
HTTP/2 200
...
{{< /text >}}

View File

@ -0,0 +1,168 @@
#!/bin/bash
# shellcheck disable=SC2034,SC2153,SC2155
# Copyright Istio Authors. All Rights Reserved.
#
# Licensed 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.
####################################################################################################
# WARNING: THIS IS AN AUTO-GENERATED FILE, DO NOT EDIT. PLEASE MODIFY THE ORIGINAL MARKDOWN FILE:
# docs/tasks/traffic-management/egress/egress-tls-origination/index.md
####################################################################################################
snip_before_you_begin_1() {
kubectl apply -f samples/sleep/sleep.yaml
}
snip_before_you_begin_2() {
kubectl apply -f <(istioctl kube-inject -f samples/sleep/sleep.yaml)
}
snip_before_you_begin_3() {
export SOURCE_POD=$(kubectl get pod -l app=sleep -o jsonpath={.items..metadata.name})
}
snip_apply_simple() {
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: edition-cnn-com
spec:
hosts:
- edition.cnn.com
ports:
- number: 80
name: http-port
protocol: HTTP
- number: 443
name: https-port
protocol: HTTPS
resolution: DNS
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: edition-cnn-com
spec:
hosts:
- edition.cnn.com
tls:
- match:
- port: 443
sniHosts:
- edition.cnn.com
route:
- destination:
host: edition.cnn.com
port:
number: 443
weight: 100
EOF
}
snip_curl_simple() {
kubectl exec "${SOURCE_POD}" -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
}
! read -r -d '' snip_curl_simple_out <<\ENDSNIP
HTTP/1.1 301 Moved Permanently
...
location: https://edition.cnn.com/politics
...
HTTP/2 200
...
ENDSNIP
snip_apply_origination() {
kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
name: edition-cnn-com
spec:
hosts:
- edition.cnn.com
ports:
- number: 80
name: http-port
protocol: HTTP
- number: 443
name: https-port-for-tls-origination
protocol: HTTPS
resolution: DNS
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: edition-cnn-com
spec:
hosts:
- edition.cnn.com
http:
- match:
- port: 80
route:
- destination:
host: edition.cnn.com
subset: tls-origination
port:
number: 443
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: edition-cnn-com
spec:
host: edition.cnn.com
subsets:
- name: tls-origination
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
portLevelSettings:
- port:
number: 443
tls:
mode: SIMPLE # initiates HTTPS when accessing edition.cnn.com
EOF
}
snip_curl_origination_http() {
kubectl exec "${SOURCE_POD}" -c sleep -- curl -sL -o /dev/null -D - http://edition.cnn.com/politics
}
! read -r -d '' snip_curl_origination_http_out <<\ENDSNIP
HTTP/1.1 200 OK
...
ENDSNIP
snip_curl_origination_https() {
kubectl exec "${SOURCE_POD}" -c sleep -- curl -sL -o /dev/null -D - https://edition.cnn.com/politics
}
! read -r -d '' snip_curl_origination_https_out <<\ENDSNIP
HTTP/2 200
...
ENDSNIP
snip_cleanup_1() {
kubectl delete serviceentry edition-cnn-com
kubectl delete virtualservice edition-cnn-com
kubectl delete destinationrule edition-cnn-com
}
snip_cleanup_2() {
kubectl delete -f samples/sleep/sleep.yaml
}

5
go.mod
View File

@ -10,7 +10,10 @@ replace github.com/spf13/viper => github.com/istio/viper v1.3.3-0.20190515210538
replace github.com/docker/docker => github.com/docker/engine v1.4.2-0.20191011211953-adfac697dc5b
require istio.io/istio v0.0.0-20200518170651-df8ea82bf434
require (
istio.io/istio v0.0.0-20200518170651-df8ea82bf434
istio.io/pkg v0.0.0-20200511212725-7bfbbf968c23
)
replace github.com/Azure/go-autorest/autorest => github.com/Azure/go-autorest/autorest v0.9.0

View File

@ -17,6 +17,7 @@ package istioio
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
@ -26,6 +27,7 @@ import (
"istio.io/istio/pkg/test/framework/resource/environment"
"istio.io/istio/pkg/test/scopes"
"istio.io/pkg/log"
)
const (
@ -103,20 +105,36 @@ func (s Script) run(ctx Context) {
cmd.Env = s.getEnv(ctx, fileName)
cmd.Stdin = strings.NewReader(command)
// Output will be streamed to logs as well as to the output buffer (to be written to disk)
var output bytes.Buffer
cmd.Stdout = io.MultiWriter(&LogWriter{}, &output)
cmd.Stderr = io.MultiWriter(&LogWriter{}, &output)
// Run the command and get the output.
output, err := cmd.CombinedOutput()
cmdErr := cmd.Run()
// Copy the command output from the script to workDir
outputFileName := fileName + "_output.txt"
if err := ioutil.WriteFile(filepath.Join(ctx.WorkDir(), outputFileName), bytes.TrimSpace(output), 0644); err != nil {
ctx.Fatalf("failed copying output for command %s: %v", input.Name(), err)
if werr := ioutil.WriteFile(filepath.Join(ctx.WorkDir(), outputFileName), bytes.TrimSpace(output.Bytes()), 0644); werr != nil {
ctx.Fatalf("failed copying output for command %s: %v", input.Name(), werr)
}
if err != nil {
ctx.Fatalf("script %s returned an error: %v. Output:\n%s", input.Name(), err, string(output))
if cmdErr != nil {
ctx.Fatalf("script %s returned an error: %v. Output:\n%s", input.Name(), cmdErr, output.String())
}
}
var scriptLog = log.RegisterScope("script", "output of test scripts", 0)
type LogWriter struct{}
func (l LogWriter) Write(p []byte) (n int, err error) {
scriptLog.Debugf("%v", strings.TrimSpace(string(p)))
return len(p), nil
}
var _ io.Writer = &LogWriter{}
func (s Script) getWorkDir(ctx Context) string {
if s.WorkDir != "" {
// User-specified work dir for the script.

View File

@ -0,0 +1,37 @@
// Copyright Istio Authors
//
// Licensed 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 egress
import (
"testing"
"istio.io/istio/pkg/test/framework"
"istio.io/istio/pkg/test/framework/components/istio"
"istio.io/istio/pkg/test/framework/resource/environment"
)
var (
inst istio.Instance
)
func TestMain(m *testing.M) {
// Integration test for Egress
framework.
NewSuite("trafficmanagement_egress", m).
SetupOnEnv(environment.Kube, istio.Setup(&inst, nil)).
RequireEnvironment(environment.Kube).
Run()
}

View File

@ -0,0 +1,36 @@
#!/usr/bin/env bash
# shellcheck disable=SC1090,SC2154
# Copyright 2020 Istio Authors
#
# Licensed 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.
set -e
set -u
set -o pipefail
source "${REPO_ROOT}/content/en/docs/tasks/traffic-management/egress/egress-tls-origination/snips.sh"
source "${REPO_ROOT}/tests/util/samples.sh"
# Deploy sample and set up variable pointing to it
startup_sleep_sample
snip_before_you_begin_3
# Confirm we can access plain HTTP
snip_apply_simple
_run_and_verify_elided snip_curl_simple "$snip_curl_simple_out"
# Apply TLS origination config, check http and https content is correct
snip_apply_origination
_run_and_verify_elided snip_curl_origination_http "$snip_curl_origination_http_out"
_run_and_verify_elided snip_curl_origination_https "$snip_curl_origination_https_out"

View File

@ -0,0 +1,43 @@
// Copyright Istio Authors
//
// Licensed 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 egress
import (
"testing"
"istio.io/istio/pkg/test/framework"
"istio.io/istio.io/pkg/test/istioio"
)
func TestTlsOrigination(t *testing.T) {
framework.
NewTest(t).
Run(istioio.NewBuilder("tasks__traffic_management__egress_tls_origination").
Add(istioio.Script{
Input: istioio.Path("scripts/tls_origination.sh"),
}).
Defer(istioio.Script{
Input: istioio.Inline{
FileName: "cleanup.sh",
Value: `
set +e # ignore cleanup errors
source "${REPO_ROOT}/content/en/docs/tasks/traffic-management/egress/egress-tls-origination/snips.sh"
snip_cleanup_1
snip_cleanup_2`,
},
}).
Build())
}