github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/topgun/k8s/https_web_tls_termination_test.go (about)

     1  package k8s_test
     2  
     3  import (
     4  	"io/ioutil"
     5  	"net"
     6  	"os"
     7  	"time"
     8  
     9  	"github.com/onsi/gomega/gbytes"
    10  	"github.com/square/certstrap/pkix"
    11  
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  var _ = Describe("Web HTTP or HTTPS(TLS) termination at web node", func() {
    17  
    18  	var (
    19  		serverCertBytes []byte
    20  		serverKeyBytes  []byte
    21  		caCertFile      *os.File
    22  	)
    23  
    24  	BeforeEach(func() {
    25  		var err error
    26  
    27  		setReleaseNameAndNamespace("wtt")
    28  
    29  		CACert, serverKey, serverCert := generateKeyPairWithCA(namespace, releaseName+"-web")
    30  		CACertBytes, err := CACert.Export()
    31  		Expect(err).NotTo(HaveOccurred())
    32  
    33  		caCertFile, err = ioutil.TempFile("", "ca")
    34  		caCertFile.Write(CACertBytes)
    35  		caCertFile.Close()
    36  
    37  		serverKeyBytes, err = serverKey.ExportPrivate()
    38  		Expect(err).NotTo(HaveOccurred())
    39  
    40  		serverCertBytes, err = serverCert.Export()
    41  		Expect(err).NotTo(HaveOccurred())
    42  	})
    43  
    44  	AfterEach(func() {
    45  		os.Remove(caCertFile.Name())
    46  	})
    47  
    48  	Context("when configured correctly", func() {
    49  
    50  		var (
    51  			atc Endpoint
    52  
    53  			chartConfig []string
    54  			proxyPort   string
    55  		)
    56  
    57  		JustBeforeEach(func() {
    58  			deployConcourseChart(releaseName, chartConfig...)
    59  
    60  			waitAllPodsInNamespaceToBeReady(namespace)
    61  
    62  			atc = endpointFactory.NewServiceEndpoint(
    63  				namespace,
    64  				releaseName+"-web",
    65  				proxyPort,
    66  			)
    67  		})
    68  
    69  		AfterEach(func() {
    70  			atc.Close()
    71  			cleanupReleases()
    72  		})
    73  
    74  		Context("with tls termination at web", func() {
    75  
    76  			BeforeEach(func() {
    77  				chartConfig = generateChartConfig(
    78  					"--set=concourse.web.externalUrl=https://test.com",
    79  					"--set=concourse.web.tls.enabled=true",
    80  					"--set=secrets.webTlsCert="+string(serverCertBytes),
    81  					"--set=secrets.webTlsKey="+string(serverKeyBytes),
    82  				)
    83  
    84  				proxyPort = "443"
    85  			})
    86  
    87  			It("fly login succeeds when using the correct CA and host", func() {
    88  				fly.Login(
    89  					"test",
    90  					"test",
    91  					"https://"+atc.Address(),
    92  					"--ca-cert", caCertFile.Name(),
    93  				)
    94  			})
    95  
    96  			It("fly login fails when NOT using the correct CA", func() {
    97  				Eventually(func() *gbytes.Buffer {
    98  					sess := fly.Start("login", "-u", "test", "-p", "test",
    99  						"--ca-cert", "k8s/certs/wrong-ca.crt",
   100  						"-c", "https://"+atc.Address(),
   101  					)
   102  					<-sess.Exited
   103  					return sess.Err
   104  				}, 2*time.Minute, 10*time.Second).
   105  					Should(gbytes.Say(`x509: certificate signed by unknown authority`))
   106  			})
   107  		})
   108  
   109  	})
   110  
   111  	Context("When NOT configured correctly", func() {
   112  
   113  		BeforeEach(func() {
   114  			setReleaseNameAndNamespace("wtt")
   115  		})
   116  
   117  		It("fails if tls is enabled but externalURL is NOT set", func() {
   118  			expectedErr := "Must specify HTTPS external URL when concourse.web.tls.enabled is true"
   119  
   120  			chartConfig := generateChartConfig(
   121  				"--set=concourse.web.tls.enabled=true",
   122  				"--set=secrets.webTlsCert="+string(serverCertBytes),
   123  				"--set=secrets.webTlsKey="+string(serverKeyBytes),
   124  			)
   125  
   126  			deployFailingConcourseChart(releaseName, expectedErr,
   127  				chartConfig...,
   128  			)
   129  		})
   130  
   131  		It("fails when tls is enabled but ssl cert and ssl key are NOT set", func() {
   132  			expectedErr := "secrets.webTlsCert is required because secrets.create is true and concourse.web.tls.enabled is true"
   133  
   134  			chartConfig := generateChartConfig("--set=concourse.web.externalUrl=https://test.com",
   135  				"--set=concourse.web.tls.enabled=true")
   136  
   137  			deployFailingConcourseChart(releaseName, expectedErr,
   138  				chartConfig...,
   139  			)
   140  		})
   141  	})
   142  
   143  })
   144  
   145  func generateChartConfig(args ...string) []string {
   146  	return append(args,
   147  		"--set=worker.enabled=false",
   148  		"--set=concourse.worker.baggageclaim.driver=detect",
   149  		"--set=concourse.web.tls.bindPort=443",
   150  	)
   151  }
   152  func generateKeyPairWithCA(namespace, service string) (*pkix.Certificate, *pkix.Key, *pkix.Certificate) {
   153  	CAKey, err := pkix.CreateRSAKey(1024)
   154  	Expect(err).NotTo(HaveOccurred())
   155  
   156  	CACert, err := pkix.CreateCertificateAuthority(CAKey, "", time.Now().Add(time.Hour), "Pivotal", "", "", "", "CA")
   157  	Expect(err).NotTo(HaveOccurred())
   158  
   159  	serverKey, err := pkix.CreateRSAKey(1024)
   160  	Expect(err).NotTo(HaveOccurred())
   161  
   162  	certificateSigningRequest, err := pkix.CreateCertificateSigningRequest(
   163  		serverKey, "", []net.IP{net.IPv4(127, 0, 0, 1)},
   164  		[]string{serviceAddress(namespace, service)},
   165  		"Pivotal", "", "", "", "127.0.0.1")
   166  	Expect(err).NotTo(HaveOccurred())
   167  
   168  	serverCert, err := pkix.CreateCertificateHost(CACert, CAKey,
   169  		certificateSigningRequest, time.Now().Add(time.Hour))
   170  	Expect(err).NotTo(HaveOccurred())
   171  
   172  	return CACert, serverKey, serverCert
   173  }