diff --git a/README.md b/README.md index 42afad54..3ffc483a 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,11 @@ Usage examples can be found in the #### The Node.js buildpack is compatible with the following builder(s): - [Paketo Full Builder](https://github.com/paketo-buildpacks/full-builder) - [Paketo Base Builder](https://github.com/paketo-buildpacks/base-builder) (for apps which do not leverage common C libraries) + +This buildpack also includes the following utility buildpacks: +- [Procfile CNB](https://github.com/paketo-buildpacks/procfile) +- [Environment Variables CNB](https://github.com/paketo-buildpacks/environment-variables) +- [Image Labels CNB](https://github.com/paketo-buildpacks/image-labels) +- [CA Certificates CNB](https://github.com/paketo-buildpacks/ca-certificates) + +Check out the [Paketo Node.js docs](https://paketo.io/docs/buildpacks/language-family-buildpacks/nodejs/) for more information. diff --git a/buildpack.toml b/buildpack.toml index 4139c46a..96d4a155 100644 --- a/buildpack.toml +++ b/buildpack.toml @@ -10,6 +10,11 @@ api = "0.2" [[order]] + [[order.group]] + id = "paketo-buildpacks/ca-certificates" + optional = true + version = "2.1.0" + [[order.group]] id = "paketo-buildpacks/node-engine" version = "0.2.2" @@ -43,6 +48,11 @@ api = "0.2" [[order]] + [[order.group]] + id = "paketo-buildpacks/ca-certificates" + optional = true + version = "2.1.0" + [[order.group]] id = "paketo-buildpacks/node-engine" version = "0.2.2" @@ -72,6 +82,11 @@ api = "0.2" [[order]] + [[order.group]] + id = "paketo-buildpacks/ca-certificates" + optional = true + version = "2.1.0" + [[order.group]] id = "paketo-buildpacks/node-engine" version = "0.2.2" diff --git a/integration/node_start_test.go b/integration/node_start_test.go index 670c900b..184b7a03 100644 --- a/integration/node_start_test.go +++ b/integration/node_start_test.go @@ -1,6 +1,8 @@ package integration_test import ( + "crypto/tls" + "crypto/x509" "fmt" "io/ioutil" "net/http" @@ -111,7 +113,7 @@ func testNodeStart(t *testing.T, context spec.G, it spec.S) { Expect(logs).To(ContainLines(ContainSubstring("Environment Variables Buildpack"))) Expect(logs).To(ContainLines(ContainSubstring("Image Labels Buildpack"))) - Expect(image.Buildpacks[3].Layers["environment-variables"].Metadata["variables"]).To(Equal(map[string]interface{}{"SOME_VARIABLE": "some-value"})) + Expect(image.Buildpacks[4].Layers["environment-variables"].Metadata["variables"]).To(Equal(map[string]interface{}{"SOME_VARIABLE": "some-value"})) Expect(image.Labels["some-label"]).To(Equal("some-value")) container, err = docker.Container.Run. @@ -133,5 +135,88 @@ func testNodeStart(t *testing.T, context spec.G, it spec.S) { Expect(string(content)).To(ContainSubstring("hello world")) }) }) + + context("when using CA certificates", func() { + var ( + client *http.Client + ) + + it.Before(func() { + var err error + name, err = occam.RandomName() + Expect(err).NotTo(HaveOccurred()) + source, err = occam.Source(filepath.Join("testdata", "ca_cert_apps")) + Expect(err).NotTo(HaveOccurred()) + + caCert, err := ioutil.ReadFile(fmt.Sprintf("%s/client-certs/ca.pem", source)) + Expect(err).ToNot(HaveOccurred()) + + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + cert, err := tls.LoadX509KeyPair(fmt.Sprintf("%s/client-certs/cert.pem", source), fmt.Sprintf("%s/client-certs/key.pem", source)) + Expect(err).ToNot(HaveOccurred()) + + client = &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: caCertPool, + Certificates: []tls.Certificate{cert}, + MinVersion: tls.VersionTLS12, + }, + }, + } + }) + + it("builds a working OCI image and uses a client-side CA cert for requests", func() { + var err error + var logs fmt.Stringer + image, logs, err = pack.WithNoColor().Build. + WithBuildpacks(nodeBuildpack). + WithPullPolicy("never"). + Execute(name, filepath.Join(source, "node_server")) + Expect(err).NotTo(HaveOccurred()) + + Expect(logs).To(ContainLines(ContainSubstring("CA Certificates Buildpack"))) + Expect(logs).To(ContainLines(ContainSubstring("Node Engine Buildpack"))) + Expect(logs).To(ContainLines(ContainSubstring("Node Start Buildpack"))) + + // NOTE: NODE_OPTIONS="--use-openssl-ca" is NOT required since the node binary is compiled with `--openssl-use-def-ca-store` + container, err = docker.Container.Run. + WithPublish("8080"). + WithEnv(map[string]string{ + "PORT": "8080", + "SERVICE_BINDING_ROOT": "/bindings", + }). + WithVolume(fmt.Sprintf("%s/binding:/bindings/ca-certificates", source)). + Execute(image.ID) + Expect(err).NotTo(HaveOccurred()) + + Eventually(func() string { + cLogs, err := docker.Container.Logs.Execute(container.ID) + Expect(err).NotTo(HaveOccurred()) + return cLogs.String() + }).Should( + ContainSubstring("Added 1 additional CA certificate(s) to system truststore"), + ) + + request, err := http.NewRequest("GET", fmt.Sprintf("https://localhost:%s", container.HostPort("8080")), nil) + Expect(err).NotTo(HaveOccurred()) + + var response *http.Response + Eventually(func() error { + var err error + response, err = client.Do(request) + return err + }).Should(BeNil()) + defer response.Body.Close() + + Expect(response.StatusCode).To(Equal(http.StatusOK)) + + content, err := ioutil.ReadAll(response.Body) + Expect(err).NotTo(HaveOccurred()) + Expect(string(content)).To(ContainSubstring("Hello, world!")) + }) + }) }) } diff --git a/integration/npm_test.go b/integration/npm_test.go index 00f25279..b6154a0d 100644 --- a/integration/npm_test.go +++ b/integration/npm_test.go @@ -1,6 +1,8 @@ package integration_test import ( + "crypto/tls" + "crypto/x509" "encoding/json" "fmt" "io/ioutil" @@ -117,7 +119,7 @@ func testNPM(t *testing.T, context spec.G, it spec.S) { Expect(logs).To(ContainLines(ContainSubstring("Environment Variables Buildpack"))) Expect(logs).To(ContainLines(ContainSubstring("Image Labels Buildpack"))) - Expect(image.Buildpacks[4].Layers["environment-variables"].Metadata["variables"]).To(Equal(map[string]interface{}{"SOME_VARIABLE": "some-value"})) + Expect(image.Buildpacks[5].Layers["environment-variables"].Metadata["variables"]).To(Equal(map[string]interface{}{"SOME_VARIABLE": "some-value"})) Expect(image.Labels["some-label"]).To(Equal("some-value")) container, err = docker.Container.Run. @@ -140,5 +142,90 @@ func testNPM(t *testing.T, context spec.G, it spec.S) { Expect(env.NpmConfigLoglevel).To(Equal("error")) }) }) + + context("when using CA certificates", func() { + var ( + client *http.Client + ) + + it.Before(func() { + var err error + source, err = occam.Source(filepath.Join("testdata", "ca_cert_apps")) + Expect(err).NotTo(HaveOccurred()) + + caCert, err := ioutil.ReadFile(fmt.Sprintf("%s/client-certs/ca.pem", source)) + Expect(err).ToNot(HaveOccurred()) + + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + cert, err := tls.LoadX509KeyPair(fmt.Sprintf("%s/client-certs/cert.pem", source), fmt.Sprintf("%s/client-certs/key.pem", source)) + Expect(err).ToNot(HaveOccurred()) + + client = &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: caCertPool, + Certificates: []tls.Certificate{cert}, + MinVersion: tls.VersionTLS12, + }, + }, + } + }) + + it("builds a working OCI image and uses a client-side CA cert for requests", func() { + var err error + var logs fmt.Stringer + image, logs, err = pack.WithNoColor().Build. + WithBuildpacks(nodeBuildpack). + WithPullPolicy("never"). + Execute(name, filepath.Join(source, "npm_server")) + Expect(err).NotTo(HaveOccurred()) + + Expect(logs).To(ContainLines(ContainSubstring("CA Certificates Buildpack"))) + Expect(logs).To(ContainLines(ContainSubstring("Node Engine Buildpack"))) + Expect(logs).To(ContainLines(ContainSubstring("NPM Install Buildpack"))) + Expect(logs).To(ContainLines(ContainSubstring("NPM Start Buildpack"))) + + // NOTE: NODE_OPTIONS="--use-openssl-ca" is NOT required since the node binary is compiled with `--openssl-use-def-ca-store` + container, err = docker.Container.Run. + WithPublish("8080"). + WithEnv(map[string]string{ + "PORT": "8080", + "SERVICE_BINDING_ROOT": "/bindings", + }). + WithVolume(fmt.Sprintf("%s/binding:/bindings/ca-certificates", source)). + Execute(image.ID) + Expect(err).NotTo(HaveOccurred()) + + Eventually(func() string { + cLogs, err := docker.Container.Logs.Execute(container.ID) + Expect(err).NotTo(HaveOccurred()) + return cLogs.String() + }).Should( + ContainSubstring("Added 1 additional CA certificate(s) to system truststore"), + ) + + request, err := http.NewRequest("GET", fmt.Sprintf("https://localhost:%s/env", container.HostPort("8080")), nil) + Expect(err).NotTo(HaveOccurred()) + + var response *http.Response + Eventually(func() error { + var err error + response, err = client.Do(request) + return err + }).Should(BeNil()) + defer response.Body.Close() + + Expect(response.StatusCode).To(Equal(http.StatusOK)) + + var env struct { + NpmConfigLoglevel string `json:"NPM_CONFIG_LOGLEVEL"` + } + + Expect(json.NewDecoder(response.Body).Decode(&env)).To(Succeed()) + Expect(env.NpmConfigLoglevel).To(Equal("error")) + }) + }) }) } diff --git a/integration/testdata/ca_cert_apps/binding/ca.pem b/integration/testdata/ca_cert_apps/binding/ca.pem new file mode 100644 index 00000000..3777ad82 --- /dev/null +++ b/integration/testdata/ca_cert_apps/binding/ca.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFeTCCA2GgAwIBAgICB+UwDQYJKoZIhvcNAQELBQAwTjEaMBgGA1UEChMRUGFr +ZXRvIEJ1aWxkcGFja3MxMDAuBgNVBAMTJ1Bha2V0byBCdWlsZHBhY2tzIENlcnRp +ZmljYXRlIEF1dGhvcml0eTAeFw0yMTAzMDIxNjU5MjRaFw0zMTAzMDIxNjU5MjRa +ME4xGjAYBgNVBAoTEVBha2V0byBCdWlsZHBhY2tzMTAwLgYDVQQDEydQYWtldG8g +QnVpbGRwYWNrcyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDGQS7V1sKolBHl7WV19S3sDZwUCP4BR0UrZqvR2hmm +v0D1tsxmVDepX0hbQOMUq9oiSsDga2uNrVfvLNC81PZF+KePgTawdIVCF6eSPZyY +muVDorvd7UGpKdx1AL3Ez+QhLj9PGP1EW6nU7oD/6XzJWeRkNZWxPNP0Ev6fChfN +qKXkPJYNHPrq3G7LQ6do7oaexXEOMd+lxLtUObSXyzMQn50olkxbogLC0ncNb17h +8f0YzogQnZxe0LIkXTkbq47UJcZyZVXe4Vjuf6YXP8NY8ABW380hSbI/aHR0btD1 +mA24ups0XGcqD/4v8LtrEFm1pBC58faDQi435hVvaiuzz9wbhAMh1J18/FbiqnkR +P+l2nEQOButa1F4ClZZ989bhJboW6LSafQRJT4yAzfRuTXBzAWFYJrikdVabfnwZ +z2rZrR4lgj5IklEnTk1DiJVvNP87faTY4L0CZexrjj4YRq0BLvMG7hAkJ/7/5WZK +nNSJf+P7PNyDNWUPR+aN8R411PUG53Mxyi+lumi6eucmLQONCIuI2EdQ4iPP+QR4 +7r1eLS/+Sxn4mifux6GcDbzTrJDHXtaqCFWRyKUdooEo7dJVceJ/lxJLpn8W/enH +OJs8J9IkUjtYizNkfDniIvHQoU3mQZx6P8AzKTJ7XA5i3Xw+YUVaM/z91aQML5sz +xQIDAQABo2EwXzAOBgNVHQ8BAf8EBAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIG +CCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEwwGrd7Rto0v2qq +YBRt7pucOSjzMA0GCSqGSIb3DQEBCwUAA4ICAQBHNA41hSIBvV7DNy7Winm1ls0R +bICOEawuUOZnKY3Feq1XPsPj1IHaOa4TEwPyOFs89tS5Fig5jIDtpHp+f2dYRknC +eLKjDBZRUWnsuHQIR0MS4k8Bp6ztMiUTdAUSiY+Xv11sa4qGo/NCQdVSzp4wBEBM +ZgnPTF9jU2OjxTufTDhbvYNAbM1l8+aBdF4/88s6D5OEbp3mYhCy8t82x7FKmLee +9GcQHoZxZjdcJfX5pBtDo9nakeLVbg5PgRUbFsaZyVXQL56VhfEYiM3UzqZCDDuh +L+WU0pFkg0TX1xZ6438N8WD0zg44ObKEORfEvPAxbcKa+Nb8p1WsMKJmbeDDaXib +wu7A+kWa5s4rf9zlDt0Y4wVFNuO602dO6VFyZXg8dcRyjRNa/0w/l4elgOPRonbl +8P9JY1KtIkZvQ8+f7NwloSGg+/Q0j2XqTSM04TP+RQ92iSNfsm+x8gZotKdUrvUN +/7sLRgJvlJoBQ+bSHveT7r1IXE0zkM8535kYD8UEQ68cqZUEDOwK8qo2n4HY5oQ3 +4BTkHOAEu39Ov6MrgeiSDzINc2eBadJcb5CwTKH17gLGDeQz8H4fRKSv2+6Pty6H +esKmgqCE28Xnaz3snOEYSRfnG0+o5rgrXFUd0qAjpiu/rqCOXl9TeSEUM+YvjjRC +/HNPsIbBVFyt0n7mYw== +-----END CERTIFICATE----- diff --git a/integration/testdata/ca_cert_apps/binding/type b/integration/testdata/ca_cert_apps/binding/type new file mode 100644 index 00000000..a779e5d0 --- /dev/null +++ b/integration/testdata/ca_cert_apps/binding/type @@ -0,0 +1 @@ +ca-certificates diff --git a/integration/testdata/ca_cert_apps/client-certs/ca.pem b/integration/testdata/ca_cert_apps/client-certs/ca.pem new file mode 100644 index 00000000..3777ad82 --- /dev/null +++ b/integration/testdata/ca_cert_apps/client-certs/ca.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFeTCCA2GgAwIBAgICB+UwDQYJKoZIhvcNAQELBQAwTjEaMBgGA1UEChMRUGFr +ZXRvIEJ1aWxkcGFja3MxMDAuBgNVBAMTJ1Bha2V0byBCdWlsZHBhY2tzIENlcnRp +ZmljYXRlIEF1dGhvcml0eTAeFw0yMTAzMDIxNjU5MjRaFw0zMTAzMDIxNjU5MjRa +ME4xGjAYBgNVBAoTEVBha2V0byBCdWlsZHBhY2tzMTAwLgYDVQQDEydQYWtldG8g +QnVpbGRwYWNrcyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQDGQS7V1sKolBHl7WV19S3sDZwUCP4BR0UrZqvR2hmm +v0D1tsxmVDepX0hbQOMUq9oiSsDga2uNrVfvLNC81PZF+KePgTawdIVCF6eSPZyY +muVDorvd7UGpKdx1AL3Ez+QhLj9PGP1EW6nU7oD/6XzJWeRkNZWxPNP0Ev6fChfN +qKXkPJYNHPrq3G7LQ6do7oaexXEOMd+lxLtUObSXyzMQn50olkxbogLC0ncNb17h +8f0YzogQnZxe0LIkXTkbq47UJcZyZVXe4Vjuf6YXP8NY8ABW380hSbI/aHR0btD1 +mA24ups0XGcqD/4v8LtrEFm1pBC58faDQi435hVvaiuzz9wbhAMh1J18/FbiqnkR +P+l2nEQOButa1F4ClZZ989bhJboW6LSafQRJT4yAzfRuTXBzAWFYJrikdVabfnwZ +z2rZrR4lgj5IklEnTk1DiJVvNP87faTY4L0CZexrjj4YRq0BLvMG7hAkJ/7/5WZK +nNSJf+P7PNyDNWUPR+aN8R411PUG53Mxyi+lumi6eucmLQONCIuI2EdQ4iPP+QR4 +7r1eLS/+Sxn4mifux6GcDbzTrJDHXtaqCFWRyKUdooEo7dJVceJ/lxJLpn8W/enH +OJs8J9IkUjtYizNkfDniIvHQoU3mQZx6P8AzKTJ7XA5i3Xw+YUVaM/z91aQML5sz +xQIDAQABo2EwXzAOBgNVHQ8BAf8EBAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIG +CCsGAQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEwwGrd7Rto0v2qq +YBRt7pucOSjzMA0GCSqGSIb3DQEBCwUAA4ICAQBHNA41hSIBvV7DNy7Winm1ls0R +bICOEawuUOZnKY3Feq1XPsPj1IHaOa4TEwPyOFs89tS5Fig5jIDtpHp+f2dYRknC +eLKjDBZRUWnsuHQIR0MS4k8Bp6ztMiUTdAUSiY+Xv11sa4qGo/NCQdVSzp4wBEBM +ZgnPTF9jU2OjxTufTDhbvYNAbM1l8+aBdF4/88s6D5OEbp3mYhCy8t82x7FKmLee +9GcQHoZxZjdcJfX5pBtDo9nakeLVbg5PgRUbFsaZyVXQL56VhfEYiM3UzqZCDDuh +L+WU0pFkg0TX1xZ6438N8WD0zg44ObKEORfEvPAxbcKa+Nb8p1WsMKJmbeDDaXib +wu7A+kWa5s4rf9zlDt0Y4wVFNuO602dO6VFyZXg8dcRyjRNa/0w/l4elgOPRonbl +8P9JY1KtIkZvQ8+f7NwloSGg+/Q0j2XqTSM04TP+RQ92iSNfsm+x8gZotKdUrvUN +/7sLRgJvlJoBQ+bSHveT7r1IXE0zkM8535kYD8UEQ68cqZUEDOwK8qo2n4HY5oQ3 +4BTkHOAEu39Ov6MrgeiSDzINc2eBadJcb5CwTKH17gLGDeQz8H4fRKSv2+6Pty6H +esKmgqCE28Xnaz3snOEYSRfnG0+o5rgrXFUd0qAjpiu/rqCOXl9TeSEUM+YvjjRC +/HNPsIbBVFyt0n7mYw== +-----END CERTIFICATE----- diff --git a/integration/testdata/ca_cert_apps/client-certs/cert.pem b/integration/testdata/ca_cert_apps/client-certs/cert.pem new file mode 100644 index 00000000..775c1f0a --- /dev/null +++ b/integration/testdata/ca_cert_apps/client-certs/cert.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFfTCCA2WgAwIBAgICBnowDQYJKoZIhvcNAQELBQAwTjEaMBgGA1UEChMRUGFr +ZXRvIEJ1aWxkcGFja3MxMDAuBgNVBAMTJ1Bha2V0byBCdWlsZHBhY2tzIENlcnRp +ZmljYXRlIEF1dGhvcml0eTAeFw0yMTAzMDIxNjU5MjdaFw0zMTAzMDIxNjU5Mjda +MEQxGjAYBgNVBAoTEVBha2V0byBCdWlsZHBhY2tzMSYwJAYDVQQDEx1QYWtldG8g +QnVpbGRwYWNrcyBDZXJ0aWZpY2F0ZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC +AgoCggIBAKDexTQRJcn/3xPtCWUhJv20s1pjbr1QxaJlOv6sI+xXBg0nMSn2i0d4 +G7BC9yt704WJEy3rnKpA7WPejGYqi5dW711Z/gkie8MNL3zR1FrOX5/MgRgGm2S0 +3HNdjxs84zeanhRc64Z80Qyu7dfi7i68mUzp8Z5rwU9Lf8HuouAG9H94Uv4v/x4A +gIZydiSLepG4Mp1QTznogVUMsSynwG6xWLPTsfOTA9fMidTSKSFcHeLl/qBnecWv +MxQdIm8hkSlq+kGu+GXuZQA3eRBufvEhX/swZGIwla8XjDQqIWubQlLvNHm9ETMm +Eru3MTX1sO71Xiv2rZhaZeg/hnUFDZrR7cvFZLbGdhkApWpmq/5lAzKKu+QRgbXN ++TfMfw0Y650b4Nq718NEmwFjYp1TXWrcBB+uG4qvrtYbBC9W/BN/EuNeBUIBZIA0 +66UpoKCRXbd3OKZV0OPZs4apqqi+y+P54ye5tFEoASdAN6g70P4gIklUz6ftCj8T +fssPXRysqIwtZB0LTdEU0GZtfhGd32xF5RswJwxayfTOvd9c5yrqYs7iGg21MoOL +uxp+LU3Nb+Q96NMW+JuJ6XNSjTzpBTTUmFKeggAgizh7r+gHiX/sJT/g50cRztc6 +euJLEl1u8cSqiX/p5a6Ecpieu7ORjJZqJ6LPUEv5KDDWeNvGhoGBAgMBAAGjbzBt +MA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw +DgYDVR0OBAcEBQECAwQGMCwGA1UdEQQlMCOCCWxvY2FsaG9zdIcEfwAAAYcQAAAA +AAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAgEAiexbcqQJxIjKFSBQSLpX +q21pzxoCr8qULMoJEBTiBz+Aqn23nE076PBiKAd+8jWP2wIiQXqhdDqE0QV/MHvE +v3Atabd7L5hkulUw13Gl7JtG750b2nC9EoJpimgicmh/upWtzBUcBNXUN0cY9N+I +T58CfG/MYLbGR07mSeRlxnQiTMSfJ5m1G57UmqOSBqhqXai6x5/MCQHl+MIglLqh ++bRzeS1ZlgFKFWaoa+lHVQt5qqDsaaQmtFdjskudEjezlsKXNmHPOFbOH9enOJ7Z +1EobCIvb9eLCjc8FL6hEGyVFACuxAkDds23idwIJXcOVPMs7JOPa/Lb5jBNbOYLc +hYj1Op0piHEPosedtighQc3sFNvroDRYm46zBRrwbLTPQlplOBkZEssUnoDCJQJq +TwgwucnRj0nnZtHfSsaHv5LcWjW+GI9ox2qpxx8XJgTnmr2LfiNJIBViGppqjEoZ +FgGzqcd3Gle0LAXcz8mzCxHsGb0AyyVK7+GziZxTc7tiBorpn9LOA0tBlrWTrN0u +ptIfJIsKo//HVwv/rhEfRapQYTMv4trF6jFF/Kh/eyfbfkndRFlu3ywdtf+3peKI +vYZ8GeSBM86UvRyMA9nWbj8Q7NEsmg9ZHlzzG7iC32U+Zp1yy/rDrKqQWKxNojrv +o7kYPHxnraAtNlmQEDyEQ9s= +-----END CERTIFICATE----- diff --git a/integration/testdata/ca_cert_apps/client-certs/key.pem b/integration/testdata/ca_cert_apps/client-certs/key.pem new file mode 100644 index 00000000..f5c0c11f --- /dev/null +++ b/integration/testdata/ca_cert_apps/client-certs/key.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/integration/testdata/ca_cert_apps/node_server/cert.pem b/integration/testdata/ca_cert_apps/node_server/cert.pem new file mode 100644 index 00000000..775c1f0a --- /dev/null +++ b/integration/testdata/ca_cert_apps/node_server/cert.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFfTCCA2WgAwIBAgICBnowDQYJKoZIhvcNAQELBQAwTjEaMBgGA1UEChMRUGFr +ZXRvIEJ1aWxkcGFja3MxMDAuBgNVBAMTJ1Bha2V0byBCdWlsZHBhY2tzIENlcnRp +ZmljYXRlIEF1dGhvcml0eTAeFw0yMTAzMDIxNjU5MjdaFw0zMTAzMDIxNjU5Mjda +MEQxGjAYBgNVBAoTEVBha2V0byBCdWlsZHBhY2tzMSYwJAYDVQQDEx1QYWtldG8g +QnVpbGRwYWNrcyBDZXJ0aWZpY2F0ZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC +AgoCggIBAKDexTQRJcn/3xPtCWUhJv20s1pjbr1QxaJlOv6sI+xXBg0nMSn2i0d4 +G7BC9yt704WJEy3rnKpA7WPejGYqi5dW711Z/gkie8MNL3zR1FrOX5/MgRgGm2S0 +3HNdjxs84zeanhRc64Z80Qyu7dfi7i68mUzp8Z5rwU9Lf8HuouAG9H94Uv4v/x4A +gIZydiSLepG4Mp1QTznogVUMsSynwG6xWLPTsfOTA9fMidTSKSFcHeLl/qBnecWv +MxQdIm8hkSlq+kGu+GXuZQA3eRBufvEhX/swZGIwla8XjDQqIWubQlLvNHm9ETMm +Eru3MTX1sO71Xiv2rZhaZeg/hnUFDZrR7cvFZLbGdhkApWpmq/5lAzKKu+QRgbXN ++TfMfw0Y650b4Nq718NEmwFjYp1TXWrcBB+uG4qvrtYbBC9W/BN/EuNeBUIBZIA0 +66UpoKCRXbd3OKZV0OPZs4apqqi+y+P54ye5tFEoASdAN6g70P4gIklUz6ftCj8T +fssPXRysqIwtZB0LTdEU0GZtfhGd32xF5RswJwxayfTOvd9c5yrqYs7iGg21MoOL +uxp+LU3Nb+Q96NMW+JuJ6XNSjTzpBTTUmFKeggAgizh7r+gHiX/sJT/g50cRztc6 +euJLEl1u8cSqiX/p5a6Ecpieu7ORjJZqJ6LPUEv5KDDWeNvGhoGBAgMBAAGjbzBt +MA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw +DgYDVR0OBAcEBQECAwQGMCwGA1UdEQQlMCOCCWxvY2FsaG9zdIcEfwAAAYcQAAAA +AAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAgEAiexbcqQJxIjKFSBQSLpX +q21pzxoCr8qULMoJEBTiBz+Aqn23nE076PBiKAd+8jWP2wIiQXqhdDqE0QV/MHvE +v3Atabd7L5hkulUw13Gl7JtG750b2nC9EoJpimgicmh/upWtzBUcBNXUN0cY9N+I +T58CfG/MYLbGR07mSeRlxnQiTMSfJ5m1G57UmqOSBqhqXai6x5/MCQHl+MIglLqh ++bRzeS1ZlgFKFWaoa+lHVQt5qqDsaaQmtFdjskudEjezlsKXNmHPOFbOH9enOJ7Z +1EobCIvb9eLCjc8FL6hEGyVFACuxAkDds23idwIJXcOVPMs7JOPa/Lb5jBNbOYLc +hYj1Op0piHEPosedtighQc3sFNvroDRYm46zBRrwbLTPQlplOBkZEssUnoDCJQJq +TwgwucnRj0nnZtHfSsaHv5LcWjW+GI9ox2qpxx8XJgTnmr2LfiNJIBViGppqjEoZ +FgGzqcd3Gle0LAXcz8mzCxHsGb0AyyVK7+GziZxTc7tiBorpn9LOA0tBlrWTrN0u +ptIfJIsKo//HVwv/rhEfRapQYTMv4trF6jFF/Kh/eyfbfkndRFlu3ywdtf+3peKI +vYZ8GeSBM86UvRyMA9nWbj8Q7NEsmg9ZHlzzG7iC32U+Zp1yy/rDrKqQWKxNojrv +o7kYPHxnraAtNlmQEDyEQ9s= +-----END CERTIFICATE----- diff --git a/integration/testdata/ca_cert_apps/node_server/key.pem b/integration/testdata/ca_cert_apps/node_server/key.pem new file mode 100644 index 00000000..f5c0c11f --- /dev/null +++ b/integration/testdata/ca_cert_apps/node_server/key.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/integration/testdata/ca_cert_apps/node_server/main.js b/integration/testdata/ca_cert_apps/node_server/main.js new file mode 100644 index 00000000..e13590ac --- /dev/null +++ b/integration/testdata/ca_cert_apps/node_server/main.js @@ -0,0 +1,24 @@ +const fs = require('fs'); +const https = require('https'); +const port = process.env.PORT || 8080; + +const options = { + cert: fs.readFileSync('cert.pem'), + key: fs.readFileSync('key.pem'), + requestCert: true, + rejectUnauthorized: false, +}; + +const handler = (req, res) => { + if (!req.client.authorized) { + res.writeHead(401); + return res.end('Invalid client certificate authentication. ' + req.client.authorizationError); + } + + res.writeHead(200); + res.end('Hello, world!'); +}; + +const server = https.createServer(options, handler); + +server.listen(port); diff --git a/integration/testdata/ca_cert_apps/npm_server/.gitignore b/integration/testdata/ca_cert_apps/npm_server/.gitignore new file mode 100644 index 00000000..c2658d7d --- /dev/null +++ b/integration/testdata/ca_cert_apps/npm_server/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/integration/testdata/ca_cert_apps/npm_server/README.md b/integration/testdata/ca_cert_apps/npm_server/README.md new file mode 100644 index 00000000..e42c2640 --- /dev/null +++ b/integration/testdata/ca_cert_apps/npm_server/README.md @@ -0,0 +1 @@ +This file here to suppress "npm WARN package.json node_web_app@0.0.0 No README data" diff --git a/integration/testdata/ca_cert_apps/npm_server/cert.pem b/integration/testdata/ca_cert_apps/npm_server/cert.pem new file mode 100644 index 00000000..775c1f0a --- /dev/null +++ b/integration/testdata/ca_cert_apps/npm_server/cert.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFfTCCA2WgAwIBAgICBnowDQYJKoZIhvcNAQELBQAwTjEaMBgGA1UEChMRUGFr +ZXRvIEJ1aWxkcGFja3MxMDAuBgNVBAMTJ1Bha2V0byBCdWlsZHBhY2tzIENlcnRp +ZmljYXRlIEF1dGhvcml0eTAeFw0yMTAzMDIxNjU5MjdaFw0zMTAzMDIxNjU5Mjda +MEQxGjAYBgNVBAoTEVBha2V0byBCdWlsZHBhY2tzMSYwJAYDVQQDEx1QYWtldG8g +QnVpbGRwYWNrcyBDZXJ0aWZpY2F0ZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC +AgoCggIBAKDexTQRJcn/3xPtCWUhJv20s1pjbr1QxaJlOv6sI+xXBg0nMSn2i0d4 +G7BC9yt704WJEy3rnKpA7WPejGYqi5dW711Z/gkie8MNL3zR1FrOX5/MgRgGm2S0 +3HNdjxs84zeanhRc64Z80Qyu7dfi7i68mUzp8Z5rwU9Lf8HuouAG9H94Uv4v/x4A +gIZydiSLepG4Mp1QTznogVUMsSynwG6xWLPTsfOTA9fMidTSKSFcHeLl/qBnecWv +MxQdIm8hkSlq+kGu+GXuZQA3eRBufvEhX/swZGIwla8XjDQqIWubQlLvNHm9ETMm +Eru3MTX1sO71Xiv2rZhaZeg/hnUFDZrR7cvFZLbGdhkApWpmq/5lAzKKu+QRgbXN ++TfMfw0Y650b4Nq718NEmwFjYp1TXWrcBB+uG4qvrtYbBC9W/BN/EuNeBUIBZIA0 +66UpoKCRXbd3OKZV0OPZs4apqqi+y+P54ye5tFEoASdAN6g70P4gIklUz6ftCj8T +fssPXRysqIwtZB0LTdEU0GZtfhGd32xF5RswJwxayfTOvd9c5yrqYs7iGg21MoOL +uxp+LU3Nb+Q96NMW+JuJ6XNSjTzpBTTUmFKeggAgizh7r+gHiX/sJT/g50cRztc6 +euJLEl1u8cSqiX/p5a6Ecpieu7ORjJZqJ6LPUEv5KDDWeNvGhoGBAgMBAAGjbzBt +MA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw +DgYDVR0OBAcEBQECAwQGMCwGA1UdEQQlMCOCCWxvY2FsaG9zdIcEfwAAAYcQAAAA +AAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAgEAiexbcqQJxIjKFSBQSLpX +q21pzxoCr8qULMoJEBTiBz+Aqn23nE076PBiKAd+8jWP2wIiQXqhdDqE0QV/MHvE +v3Atabd7L5hkulUw13Gl7JtG750b2nC9EoJpimgicmh/upWtzBUcBNXUN0cY9N+I +T58CfG/MYLbGR07mSeRlxnQiTMSfJ5m1G57UmqOSBqhqXai6x5/MCQHl+MIglLqh ++bRzeS1ZlgFKFWaoa+lHVQt5qqDsaaQmtFdjskudEjezlsKXNmHPOFbOH9enOJ7Z +1EobCIvb9eLCjc8FL6hEGyVFACuxAkDds23idwIJXcOVPMs7JOPa/Lb5jBNbOYLc +hYj1Op0piHEPosedtighQc3sFNvroDRYm46zBRrwbLTPQlplOBkZEssUnoDCJQJq +TwgwucnRj0nnZtHfSsaHv5LcWjW+GI9ox2qpxx8XJgTnmr2LfiNJIBViGppqjEoZ +FgGzqcd3Gle0LAXcz8mzCxHsGb0AyyVK7+GziZxTc7tiBorpn9LOA0tBlrWTrN0u +ptIfJIsKo//HVwv/rhEfRapQYTMv4trF6jFF/Kh/eyfbfkndRFlu3ywdtf+3peKI +vYZ8GeSBM86UvRyMA9nWbj8Q7NEsmg9ZHlzzG7iC32U+Zp1yy/rDrKqQWKxNojrv +o7kYPHxnraAtNlmQEDyEQ9s= +-----END CERTIFICATE----- diff --git a/integration/testdata/ca_cert_apps/npm_server/key.pem b/integration/testdata/ca_cert_apps/npm_server/key.pem new file mode 100644 index 00000000..f5c0c11f --- /dev/null +++ b/integration/testdata/ca_cert_apps/npm_server/key.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/integration/testdata/ca_cert_apps/npm_server/package.json b/integration/testdata/ca_cert_apps/npm_server/package.json new file mode 100644 index 00000000..0454942f --- /dev/null +++ b/integration/testdata/ca_cert_apps/npm_server/package.json @@ -0,0 +1,20 @@ +{ + "name": "simple_app", + "version": "0.0.0", + "description": "some app", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "", + "dependencies": { + "leftpad": "~0.0.1" + }, + "repository": { + "type": "git", + "url": "" + }, + "engines": { + "node": "~10" + } +} diff --git a/integration/testdata/ca_cert_apps/npm_server/server.js b/integration/testdata/ca_cert_apps/npm_server/server.js new file mode 100644 index 00000000..617248f9 --- /dev/null +++ b/integration/testdata/ca_cert_apps/npm_server/server.js @@ -0,0 +1,28 @@ +const fs = require('fs'); +const https = require('https'); +const leftpad = require('leftpad'); +const port = process.env.PORT || 8080; + +const options = { + cert: fs.readFileSync('cert.pem'), + key: fs.readFileSync('key.pem'), + requestCert: true, + rejectUnauthorized: false, +}; + +const handler = (req, res) => { + if (!req.client.authorized) { + res.writeHead(401); + return res.end('Invalid client certificate authentication. ' + req.client.authorizationError); + } + res.end(JSON.stringify(process.env)); +}; + +const server = https.createServer(options, handler); + +server.listen(port, (err) => { + if (err) { + return console.log('something bad happened', err); + } + console.log(`server is listening on ${port}`); +}); diff --git a/integration/testdata/ca_cert_apps/yarn_server/.gitignore b/integration/testdata/ca_cert_apps/yarn_server/.gitignore new file mode 100644 index 00000000..c2658d7d --- /dev/null +++ b/integration/testdata/ca_cert_apps/yarn_server/.gitignore @@ -0,0 +1 @@ +node_modules/ diff --git a/integration/testdata/ca_cert_apps/yarn_server/README.md b/integration/testdata/ca_cert_apps/yarn_server/README.md new file mode 100644 index 00000000..e42c2640 --- /dev/null +++ b/integration/testdata/ca_cert_apps/yarn_server/README.md @@ -0,0 +1 @@ +This file here to suppress "npm WARN package.json node_web_app@0.0.0 No README data" diff --git a/integration/testdata/ca_cert_apps/yarn_server/cert.pem b/integration/testdata/ca_cert_apps/yarn_server/cert.pem new file mode 100644 index 00000000..775c1f0a --- /dev/null +++ b/integration/testdata/ca_cert_apps/yarn_server/cert.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFfTCCA2WgAwIBAgICBnowDQYJKoZIhvcNAQELBQAwTjEaMBgGA1UEChMRUGFr +ZXRvIEJ1aWxkcGFja3MxMDAuBgNVBAMTJ1Bha2V0byBCdWlsZHBhY2tzIENlcnRp +ZmljYXRlIEF1dGhvcml0eTAeFw0yMTAzMDIxNjU5MjdaFw0zMTAzMDIxNjU5Mjda +MEQxGjAYBgNVBAoTEVBha2V0byBCdWlsZHBhY2tzMSYwJAYDVQQDEx1QYWtldG8g +QnVpbGRwYWNrcyBDZXJ0aWZpY2F0ZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC +AgoCggIBAKDexTQRJcn/3xPtCWUhJv20s1pjbr1QxaJlOv6sI+xXBg0nMSn2i0d4 +G7BC9yt704WJEy3rnKpA7WPejGYqi5dW711Z/gkie8MNL3zR1FrOX5/MgRgGm2S0 +3HNdjxs84zeanhRc64Z80Qyu7dfi7i68mUzp8Z5rwU9Lf8HuouAG9H94Uv4v/x4A +gIZydiSLepG4Mp1QTznogVUMsSynwG6xWLPTsfOTA9fMidTSKSFcHeLl/qBnecWv +MxQdIm8hkSlq+kGu+GXuZQA3eRBufvEhX/swZGIwla8XjDQqIWubQlLvNHm9ETMm +Eru3MTX1sO71Xiv2rZhaZeg/hnUFDZrR7cvFZLbGdhkApWpmq/5lAzKKu+QRgbXN ++TfMfw0Y650b4Nq718NEmwFjYp1TXWrcBB+uG4qvrtYbBC9W/BN/EuNeBUIBZIA0 +66UpoKCRXbd3OKZV0OPZs4apqqi+y+P54ye5tFEoASdAN6g70P4gIklUz6ftCj8T +fssPXRysqIwtZB0LTdEU0GZtfhGd32xF5RswJwxayfTOvd9c5yrqYs7iGg21MoOL +uxp+LU3Nb+Q96NMW+JuJ6XNSjTzpBTTUmFKeggAgizh7r+gHiX/sJT/g50cRztc6 +euJLEl1u8cSqiX/p5a6Ecpieu7ORjJZqJ6LPUEv5KDDWeNvGhoGBAgMBAAGjbzBt +MA4GA1UdDwEB/wQEAwIHgDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw +DgYDVR0OBAcEBQECAwQGMCwGA1UdEQQlMCOCCWxvY2FsaG9zdIcEfwAAAYcQAAAA +AAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAgEAiexbcqQJxIjKFSBQSLpX +q21pzxoCr8qULMoJEBTiBz+Aqn23nE076PBiKAd+8jWP2wIiQXqhdDqE0QV/MHvE +v3Atabd7L5hkulUw13Gl7JtG750b2nC9EoJpimgicmh/upWtzBUcBNXUN0cY9N+I +T58CfG/MYLbGR07mSeRlxnQiTMSfJ5m1G57UmqOSBqhqXai6x5/MCQHl+MIglLqh ++bRzeS1ZlgFKFWaoa+lHVQt5qqDsaaQmtFdjskudEjezlsKXNmHPOFbOH9enOJ7Z +1EobCIvb9eLCjc8FL6hEGyVFACuxAkDds23idwIJXcOVPMs7JOPa/Lb5jBNbOYLc +hYj1Op0piHEPosedtighQc3sFNvroDRYm46zBRrwbLTPQlplOBkZEssUnoDCJQJq +TwgwucnRj0nnZtHfSsaHv5LcWjW+GI9ox2qpxx8XJgTnmr2LfiNJIBViGppqjEoZ +FgGzqcd3Gle0LAXcz8mzCxHsGb0AyyVK7+GziZxTc7tiBorpn9LOA0tBlrWTrN0u +ptIfJIsKo//HVwv/rhEfRapQYTMv4trF6jFF/Kh/eyfbfkndRFlu3ywdtf+3peKI +vYZ8GeSBM86UvRyMA9nWbj8Q7NEsmg9ZHlzzG7iC32U+Zp1yy/rDrKqQWKxNojrv +o7kYPHxnraAtNlmQEDyEQ9s= +-----END CERTIFICATE----- diff --git a/integration/testdata/ca_cert_apps/yarn_server/key.pem b/integration/testdata/ca_cert_apps/yarn_server/key.pem new file mode 100644 index 00000000..f5c0c11f --- /dev/null +++ b/integration/testdata/ca_cert_apps/yarn_server/key.pem @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/integration/testdata/ca_cert_apps/yarn_server/package.json b/integration/testdata/ca_cert_apps/yarn_server/package.json new file mode 100644 index 00000000..1028aa84 --- /dev/null +++ b/integration/testdata/ca_cert_apps/yarn_server/package.json @@ -0,0 +1,17 @@ +{ + "name": "simple_app", + "version": "0.0.0", + "description": "some app", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "MIT", + "dependencies": { + "leftpad": "~0.0.1" + }, + "repository": { + "type": "git", + "url": "" + } +} diff --git a/integration/testdata/ca_cert_apps/yarn_server/server.js b/integration/testdata/ca_cert_apps/yarn_server/server.js new file mode 100644 index 00000000..ed479073 --- /dev/null +++ b/integration/testdata/ca_cert_apps/yarn_server/server.js @@ -0,0 +1,26 @@ +const fs = require('fs'); +const https = require('https'); +const leftpad = require('leftpad'); +const tls = require('tls'); +const port = process.env.PORT || 8080; + +const options = { + cert: fs.readFileSync('cert.pem'), + key: fs.readFileSync('key.pem'), + requestCert: true, + rejectUnauthorized: false, +}; + +const requestHandler = (request, response) => { + response.end("Hello, World!") +} + +const server = https.createServer(options, requestHandler) + +server.listen(port, (err) => { + if (err) { + return console.log('something bad happened', err) + } + + console.log(`server is listening on ${port}`) +}) diff --git a/integration/testdata/ca_cert_apps/yarn_server/yarn.lock b/integration/testdata/ca_cert_apps/yarn_server/yarn.lock new file mode 100644 index 00000000..77a177cd --- /dev/null +++ b/integration/testdata/ca_cert_apps/yarn_server/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +leftpad@~0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/leftpad/-/leftpad-0.0.1.tgz#86b1a4de4face180ac545a83f1503523d8fed115" + integrity sha1-hrGk3k+s4YCsVFqD8VA1I9j+0RU= diff --git a/integration/yarn_test.go b/integration/yarn_test.go index 3168ecce..ab0a7b31 100644 --- a/integration/yarn_test.go +++ b/integration/yarn_test.go @@ -1,6 +1,8 @@ package integration_test import ( + "crypto/tls" + "crypto/x509" "fmt" "io/ioutil" "net/http" @@ -110,7 +112,7 @@ func testYarn(t *testing.T, context spec.G, it spec.S) { Expect(logs).To(ContainLines(ContainSubstring("Environment Variables Buildpack"))) Expect(logs).To(ContainLines(ContainSubstring("Image Labels Buildpack"))) - Expect(image.Buildpacks[5].Layers["environment-variables"].Metadata["variables"]).To(Equal(map[string]interface{}{"SOME_VARIABLE": "some-value"})) + Expect(image.Buildpacks[6].Layers["environment-variables"].Metadata["variables"]).To(Equal(map[string]interface{}{"SOME_VARIABLE": "some-value"})) Expect(image.Labels["some-label"]).To(Equal("some-value")) container, err = docker.Container.Run. @@ -132,5 +134,88 @@ func testYarn(t *testing.T, context spec.G, it spec.S) { Expect(string(content)).To(ContainSubstring("Hello, World!")) }) }) + + context("when using CA certificates", func() { + var ( + client *http.Client + ) + + it.Before(func() { + var err error + source, err = occam.Source(filepath.Join("testdata", "ca_cert_apps")) + Expect(err).NotTo(HaveOccurred()) + + caCert, err := ioutil.ReadFile(fmt.Sprintf("%s/client-certs/ca.pem", source)) + Expect(err).ToNot(HaveOccurred()) + + caCertPool := x509.NewCertPool() + caCertPool.AppendCertsFromPEM(caCert) + + cert, err := tls.LoadX509KeyPair(fmt.Sprintf("%s/client-certs/cert.pem", source), fmt.Sprintf("%s/client-certs/key.pem", source)) + Expect(err).ToNot(HaveOccurred()) + + client = &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + RootCAs: caCertPool, + Certificates: []tls.Certificate{cert}, + MinVersion: tls.VersionTLS12, + }, + }, + } + }) + + it("builds a working OCI image and uses a client-side CA cert for requests", func() { + var err error + var logs fmt.Stringer + image, logs, err = pack.WithNoColor().Build. + WithBuildpacks(nodeBuildpack). + WithPullPolicy("never"). + Execute(name, filepath.Join(source, "yarn_server")) + Expect(err).NotTo(HaveOccurred()) + + Expect(logs).To(ContainLines(ContainSubstring("CA Certificates Buildpack"))) + Expect(logs).To(ContainLines(ContainSubstring("Node Engine Buildpack"))) + Expect(logs).To(ContainLines(ContainSubstring("Yarn Buildpack"))) + Expect(logs).To(ContainLines(ContainSubstring("Yarn Install Buildpack"))) + Expect(logs).To(ContainLines(ContainSubstring("Yarn Start Buildpack"))) + + // NOTE: NODE_OPTIONS="--use-openssl-ca" is NOT required since the node binary is compiled with `--openssl-use-def-ca-store` + container, err = docker.Container.Run. + WithPublish("8080"). + WithEnv(map[string]string{ + "PORT": "8080", + "SERVICE_BINDING_ROOT": "/bindings", + }). + WithVolume(fmt.Sprintf("%s/binding:/bindings/ca-certificates", source)). + Execute(image.ID) + Expect(err).NotTo(HaveOccurred()) + + Eventually(func() string { + cLogs, err := docker.Container.Logs.Execute(container.ID) + Expect(err).NotTo(HaveOccurred()) + return cLogs.String() + }).Should( + ContainSubstring("Added 1 additional CA certificate(s) to system truststore"), + ) + + request, err := http.NewRequest("GET", fmt.Sprintf("https://localhost:%s", container.HostPort("8080")), nil) + Expect(err).NotTo(HaveOccurred()) + + var response *http.Response + Eventually(func() error { + var err error + response, err = client.Do(request) + return err + }).Should(BeNil()) + defer response.Body.Close() + + Expect(response.StatusCode).To(Equal(http.StatusOK)) + + content, err := ioutil.ReadAll(response.Body) + Expect(err).NotTo(HaveOccurred()) + Expect(string(content)).To(ContainSubstring("Hello, World!")) + }) + }) }) } diff --git a/package.toml b/package.toml index 78cf1c43..9ee701d8 100644 --- a/package.toml +++ b/package.toml @@ -31,3 +31,6 @@ [[dependencies]] uri = "docker://gcr.io/paketo-buildpacks/image-labels:3.0.0" + +[[dependencies]] + uri = "docker://gcr.io/paketo-buildpacks/ca-certificates:2.1.0"