Skip to content

Commit 13d1618

Browse files
authored
Add ca certificates bp (paketo-buildpacks#352)
1 parent 5cc9a9f commit 13d1618

33 files changed

Lines changed: 1299 additions & 16 deletions

buildpack.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ api = "0.5"
99

1010
[[order]]
1111

12+
[[order.group]]
13+
id = "paketo-buildpacks/ca-certificates"
14+
optional = true
15+
version = "2.3.2"
16+
1217
[[order.group]]
1318
id = "paketo-community/cpython"
1419
version = "0.7.0"
@@ -46,6 +51,11 @@ api = "0.5"
4651

4752
[[order]]
4853

54+
[[order.group]]
55+
id = "paketo-buildpacks/ca-certificates"
56+
optional = true
57+
version = "2.3.2"
58+
4959
[[order.group]]
5060
id = "paketo-community/cpython"
5161
version = "0.7.0"
@@ -79,6 +89,11 @@ api = "0.5"
7989

8090
[[order]]
8191

92+
[[order.group]]
93+
id = "paketo-buildpacks/ca-certificates"
94+
optional = true
95+
version = "2.3.2"
96+
8297
[[order.group]]
8398
id = "paketo-community/miniconda"
8499
version = "0.2.0"
@@ -108,6 +123,11 @@ api = "0.5"
108123

109124
[[order]]
110125

126+
[[order.group]]
127+
id = "paketo-buildpacks/ca-certificates"
128+
optional = true
129+
version = "2.3.2"
130+
111131
[[order.group]]
112132
id = "paketo-community/cpython"
113133
version = "0.7.0"

integration/conda_test.go

Lines changed: 84 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package integration_test
22

33
import (
4+
"crypto/tls"
5+
"crypto/x509"
46
"fmt"
5-
"io/ioutil"
7+
"io"
68
"net/http"
79
"os"
810
"path/filepath"
@@ -82,20 +84,98 @@ func testConda(t *testing.T, context spec.G, it spec.S) {
8284

8385
Expect(response.StatusCode).To(Equal(http.StatusOK))
8486

85-
content, err := ioutil.ReadAll(response.Body)
87+
content, err := io.ReadAll(response.Body)
8688
Expect(err).NotTo(HaveOccurred())
8789
Expect(string(content)).To(ContainSubstring("Hello, world!"))
8890

91+
Expect(logs).To(ContainLines(ContainSubstring("CA Certificates Buildpack")))
8992
Expect(logs).To(ContainLines(ContainSubstring("Miniconda Buildpack")))
9093
Expect(logs).To(ContainLines(ContainSubstring("Conda Env Update Buildpack")))
9194
Expect(logs).To(ContainLines(ContainSubstring("Python Start Buildpack")))
9295
Expect(logs).To(ContainLines(ContainSubstring("Procfile Buildpack")))
9396
Expect(logs).To(ContainLines(ContainSubstring("Environment Variables Buildpack")))
9497
Expect(logs).To(ContainLines(ContainSubstring("Image Labels Buildpack")))
9598

96-
Expect(image.Buildpacks[4].Key).To(Equal("paketo-buildpacks/environment-variables"))
97-
Expect(image.Buildpacks[4].Layers["environment-variables"].Metadata["variables"]).To(Equal(map[string]interface{}{"SOME_VARIABLE": "some-value"}))
99+
Expect(image.Buildpacks[5].Key).To(Equal("paketo-buildpacks/environment-variables"))
100+
Expect(image.Buildpacks[5].Layers["environment-variables"].Metadata["variables"]).To(Equal(map[string]interface{}{"SOME_VARIABLE": "some-value"}))
98101
Expect(image.Labels["some-label"]).To(Equal("some-value"))
99102
})
103+
104+
context("when using CA certificates", func() {
105+
var client *http.Client
106+
107+
it.Before(func() {
108+
var err error
109+
source, err = occam.Source(filepath.Join("testdata", "ca_cert_apps"))
110+
Expect(err).NotTo(HaveOccurred())
111+
112+
caCert, err := os.ReadFile(filepath.Join(source, "client_certs", "ca.pem"))
113+
Expect(err).NotTo(HaveOccurred())
114+
115+
caCertPool := x509.NewCertPool()
116+
caCertPool.AppendCertsFromPEM(caCert)
117+
118+
cert, err := tls.LoadX509KeyPair(
119+
filepath.Join(source, "client_certs", "cert.pem"),
120+
filepath.Join(source, "client_certs", "key.pem"))
121+
Expect(err).NotTo(HaveOccurred())
122+
123+
client = &http.Client{
124+
Transport: &http.Transport{
125+
TLSClientConfig: &tls.Config{
126+
RootCAs: caCertPool,
127+
Certificates: []tls.Certificate{cert},
128+
MinVersion: tls.VersionTLS12,
129+
},
130+
},
131+
}
132+
})
133+
134+
it("builds a working OCI image with a start command and uses a client-side CA cert for requests", func() {
135+
var err error
136+
var logs fmt.Stringer
137+
138+
image, logs, err = pack.WithNoColor().Build.
139+
WithBuildpacks(pythonBuildpack).
140+
WithPullPolicy("never").
141+
Execute(name, filepath.Join(source, "conda"))
142+
Expect(err).NotTo(HaveOccurred())
143+
144+
Expect(logs).To(ContainLines(ContainSubstring("CA Certificates Buildpack")))
145+
Expect(logs).To(ContainLines(ContainSubstring("Conda Env Update Buildpack")))
146+
Expect(logs).To(ContainLines(ContainSubstring("Python Start Buildpack")))
147+
148+
container, err = docker.Container.Run.
149+
WithPublish("8080").
150+
WithEnv(map[string]string{
151+
"PORT": "8080",
152+
"SERVICE_BINDING_ROOT": "/bindings",
153+
}).
154+
WithVolume(fmt.Sprintf("%s:/bindings/ca-certificates", filepath.Join(source, "bindings"))).
155+
Execute(image.ID)
156+
Expect(err).NotTo(HaveOccurred())
157+
158+
Eventually(func() string {
159+
cLogs, err := docker.Container.Logs.Execute(container.ID)
160+
Expect(err).NotTo(HaveOccurred())
161+
return cLogs.String()
162+
}).Should(
163+
ContainSubstring("Added 1 additional CA certificate(s) to system truststore"),
164+
)
165+
166+
request, err := http.NewRequest("GET", fmt.Sprintf("https://localhost:%s", container.HostPort("8080")), nil)
167+
Expect(err).NotTo(HaveOccurred())
168+
169+
var response *http.Response
170+
Eventually(func() error {
171+
var err error
172+
response, err = client.Do(request)
173+
return err
174+
}).Should(BeNil())
175+
defer response.Body.Close()
176+
177+
Expect(response.StatusCode).To(Equal(http.StatusOK))
178+
})
179+
})
100180
})
101181
}

integration/no_package_manager_test.go

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package integration_test
22

33
import (
4+
"crypto/tls"
5+
"crypto/x509"
46
"fmt"
5-
"io/ioutil"
7+
"net/http"
68
"os"
79
"path/filepath"
810
"testing"
@@ -83,7 +85,7 @@ func testNoPackageManager(t *testing.T, context spec.G, it spec.S) {
8385
source, err = occam.Source(filepath.Join("testdata", "no_package_manager"))
8486
Expect(err).NotTo(HaveOccurred())
8587

86-
Expect(ioutil.WriteFile(filepath.Join(source, "Procfile"),
88+
Expect(os.WriteFile(filepath.Join(source, "Procfile"),
8789
[]byte("web: python hello.py"), os.ModePerm)).
8890
To(Succeed())
8991

@@ -98,14 +100,15 @@ func testNoPackageManager(t *testing.T, context spec.G, it spec.S) {
98100
Execute(name, source)
99101
Expect(err).NotTo(HaveOccurred(), logs.String())
100102

103+
Expect(logs).To(ContainLines(ContainSubstring("CA Certificates Buildpack")))
101104
Expect(logs).To(ContainLines(ContainSubstring("CPython Buildpack")))
102105
Expect(logs).To(ContainLines(ContainSubstring("Python Start Buildpack")))
103106
Expect(logs).To(ContainLines(ContainSubstring("Procfile Buildpack")))
104107
Expect(logs).To(ContainLines(ContainSubstring("Environment Variables Buildpack")))
105108
Expect(logs).To(ContainLines(ContainSubstring("Image Labels Buildpack")))
106109

107-
Expect(image.Buildpacks[3].Key).To(Equal("paketo-buildpacks/environment-variables"))
108-
Expect(image.Buildpacks[3].Layers["environment-variables"].Metadata["variables"]).To(Equal(map[string]interface{}{"SOME_VARIABLE": "some-value"}))
110+
Expect(image.Buildpacks[4].Key).To(Equal("paketo-buildpacks/environment-variables"))
111+
Expect(image.Buildpacks[4].Layers["environment-variables"].Metadata["variables"]).To(Equal(map[string]interface{}{"SOME_VARIABLE": "some-value"}))
109112
Expect(image.Labels["some-label"]).To(Equal("some-value"))
110113

111114
container, err = docker.Container.Run.Execute(image.ID)
@@ -118,5 +121,83 @@ func testNoPackageManager(t *testing.T, context spec.G, it spec.S) {
118121
}).Should(ContainSubstring("Hello"))
119122
})
120123
})
124+
125+
context("when using CA certificates", func() {
126+
var client *http.Client
127+
128+
it.Before(func() {
129+
var err error
130+
source, err = occam.Source(filepath.Join("testdata", "ca_cert_apps"))
131+
Expect(err).NotTo(HaveOccurred())
132+
133+
caCert, err := os.ReadFile(filepath.Join(source, "client_certs", "ca.pem"))
134+
Expect(err).NotTo(HaveOccurred())
135+
136+
caCertPool := x509.NewCertPool()
137+
caCertPool.AppendCertsFromPEM(caCert)
138+
139+
cert, err := tls.LoadX509KeyPair(
140+
filepath.Join(source, "client_certs", "cert.pem"),
141+
filepath.Join(source, "client_certs", "key.pem"))
142+
Expect(err).NotTo(HaveOccurred())
143+
144+
client = &http.Client{
145+
Transport: &http.Transport{
146+
TLSClientConfig: &tls.Config{
147+
RootCAs: caCertPool,
148+
Certificates: []tls.Certificate{cert},
149+
MinVersion: tls.VersionTLS12,
150+
},
151+
},
152+
}
153+
})
154+
155+
it("builds a working OCI image with a start command and uses a client-side CA cert for requests", func() {
156+
var err error
157+
var logs fmt.Stringer
158+
159+
image, logs, err = pack.WithNoColor().Build.
160+
WithBuildpacks(pythonBuildpack).
161+
WithPullPolicy("never").
162+
Execute(name, filepath.Join(source, "no_package_manager"))
163+
Expect(err).NotTo(HaveOccurred())
164+
165+
Expect(logs).To(ContainLines(ContainSubstring("CA Certificates Buildpack")))
166+
Expect(logs).To(ContainLines(ContainSubstring("CPython Buildpack")))
167+
Expect(logs).To(ContainLines(ContainSubstring("Python Start Buildpack")))
168+
Expect(logs).To(ContainLines(ContainSubstring("Procfile Buildpack")))
169+
170+
container, err = docker.Container.Run.
171+
WithPublish("8080").
172+
WithEnv(map[string]string{
173+
"PORT": "8080",
174+
"SERVICE_BINDING_ROOT": "/bindings",
175+
}).
176+
WithVolume(fmt.Sprintf("%s:/bindings/ca-certificates", filepath.Join(source, "bindings"))).
177+
Execute(image.ID)
178+
Expect(err).NotTo(HaveOccurred())
179+
180+
Eventually(func() string {
181+
cLogs, err := docker.Container.Logs.Execute(container.ID)
182+
Expect(err).NotTo(HaveOccurred())
183+
return cLogs.String()
184+
}).Should(
185+
ContainSubstring("Added 1 additional CA certificate(s) to system truststore"),
186+
)
187+
188+
request, err := http.NewRequest("GET", fmt.Sprintf("https://localhost:%s", container.HostPort("8080")), nil)
189+
Expect(err).NotTo(HaveOccurred())
190+
191+
var response *http.Response
192+
Eventually(func() error {
193+
var err error
194+
response, err = client.Do(request)
195+
return err
196+
}).Should(BeNil())
197+
defer response.Body.Close()
198+
199+
Expect(response.StatusCode).To(Equal(http.StatusOK))
200+
})
201+
})
121202
})
122203
}

0 commit comments

Comments
 (0)