Skip to content

Commit 683c279

Browse files
committed
Use spec.storage.s3.trustedCA
1 parent f1b3d19 commit 683c279

File tree

4 files changed

+386
-46
lines changed

4 files changed

+386
-46
lines changed

pkg/storage/s3/s3.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,21 @@ func (d *driver) getCredentialsConfigData() ([]byte, error) {
206206
}
207207
}
208208

209-
// CABundle gets the custom CA bundle for trusting communication with the AWS API
209+
// CABundle gets the custom CA bundle for trusting communication with the AWS
210+
// API.
210211
func (d *driver) CABundle() (string, bool, error) {
212+
if d.Config.TrustedCA.Name != "" {
213+
trustedCA, err := d.Listers.OpenShiftConfig.Get(d.Config.TrustedCA.Name)
214+
if err != nil {
215+
return "", false, fmt.Errorf("failed to get trusted CA %q: %w", d.Config.TrustedCA.Name, err)
216+
}
217+
bundle, ok := trustedCA.Data["ca-bundle.crt"]
218+
if !ok {
219+
return "", false, fmt.Errorf("trusted CA config map %q does not contain required key %q", d.Config.TrustedCA.Name, "ca-bundle.crt")
220+
}
221+
return string(bundle), false, nil
222+
}
223+
211224
cloudConfig, err := d.Listers.OpenShiftConfigManaged.Get(defaults.KubeCloudConfigName)
212225
switch {
213226
case errors.IsNotFound(err):

test/e2e/configuration_test.go

Lines changed: 1 addition & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,7 @@ package e2e
22

33
import (
44
"context"
5-
"crypto/rand"
6-
"crypto/rsa"
7-
"crypto/x509"
8-
"crypto/x509/pkix"
9-
"encoding/pem"
105
"fmt"
11-
"math/big"
126
"reflect"
137
"strings"
148
"testing"
@@ -429,50 +423,12 @@ func TestOperandProxyConfiguration(t *testing.T) {
429423
framework.CheckEnvVars(te, resourceVars, registryDeployment.Spec.Template.Spec.Containers[0].Env, true)
430424
}
431425

432-
func generateCertificate(hostname string) ([]byte, []byte, error) {
433-
priv, err := rsa.GenerateKey(rand.Reader, 2048)
434-
if err != nil {
435-
return nil, nil, fmt.Errorf("failed to generate private key: %s", err)
436-
}
437-
438-
notBefore := time.Now()
439-
notAfter := notBefore.Add(24 * time.Hour)
440-
441-
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
442-
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
443-
if err != nil {
444-
return nil, nil, fmt.Errorf("failed to generate serial number: %s", err)
445-
}
446-
447-
template := x509.Certificate{
448-
SerialNumber: serialNumber,
449-
Subject: pkix.Name{
450-
Organization: []string{"Example Ltd"},
451-
},
452-
NotBefore: notBefore,
453-
NotAfter: notAfter,
454-
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
455-
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
456-
BasicConstraintsValid: true,
457-
DNSNames: []string{hostname},
458-
}
459-
460-
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
461-
if err != nil {
462-
return nil, nil, fmt.Errorf("failed to create certificate: %s", err)
463-
}
464-
465-
cert := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
466-
key := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)})
467-
return cert, key, nil
468-
}
469-
470426
func TestSecureRouteConfiguration(t *testing.T) {
471427
te := framework.Setup(t)
472428
defer framework.TeardownImageRegistry(te)
473429

474430
hostname := "test.example.com"
475-
cert, key, err := generateCertificate(hostname)
431+
cert, key, err := framework.GenerateX509Certificate(hostname, nil, nil)
476432
if err != nil {
477433
t.Fatal(err)
478434
}

test/e2e/s3endpoint_test.go

Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
package e2e
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"testing"
7+
8+
imageregistryv1 "github.com/openshift/api/imageregistry/v1"
9+
operatorv1 "github.com/openshift/api/operator/v1"
10+
"github.com/openshift/cluster-image-registry-operator/test/framework"
11+
appsv1 "k8s.io/api/apps/v1"
12+
corev1 "k8s.io/api/core/v1"
13+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14+
"k8s.io/apimachinery/pkg/util/intstr"
15+
)
16+
17+
type CleanupFunc func()
18+
19+
type Cleanup struct {
20+
funcs []CleanupFunc
21+
done bool // true if Func has been called
22+
}
23+
24+
func (c *Cleanup) Add(f CleanupFunc) {
25+
c.funcs = append(c.funcs, f)
26+
}
27+
28+
func (c *Cleanup) Func() CleanupFunc {
29+
c.done = true
30+
return func() {
31+
for _, f := range c.funcs {
32+
defer f()
33+
}
34+
}
35+
}
36+
37+
func (c *Cleanup) Defer() {
38+
if !c.done {
39+
for _, f := range c.funcs {
40+
defer f()
41+
}
42+
c.funcs = nil
43+
}
44+
}
45+
46+
func deployMinio(ctx context.Context, te framework.TestEnv) (minioEndpoint string, minioAccessKey string, minioSecretKey string, minioCAConfigMapName string, cleanupFunc CleanupFunc) {
47+
var cleanup Cleanup
48+
defer cleanup.Defer()
49+
50+
const caConfigMapName = "e2e-image-registry-s3-minio-ca"
51+
const nsName = "e2e-image-registry-s3-minio"
52+
const accessKey = "accesskey"
53+
const secretKey = "secretkey"
54+
55+
caCert, caKey, err := framework.GenerateX509RootCA()
56+
if err != nil {
57+
te.Fatalf("failed to generate CA: %s", err)
58+
}
59+
60+
hostname := fmt.Sprintf("minio.%s.svc", nsName)
61+
62+
cert, key, err := framework.GenerateX509Certificate(hostname, caCert, caKey)
63+
if err != nil {
64+
te.Fatalf("failed to generate certificate: %s", err)
65+
}
66+
67+
te.Logf("creating namespace %s...", nsName)
68+
ns, err := te.Client().Namespaces().Create(ctx, &corev1.Namespace{
69+
ObjectMeta: metav1.ObjectMeta{
70+
Name: nsName,
71+
},
72+
}, metav1.CreateOptions{})
73+
if err != nil {
74+
te.Fatalf("failed to create test namespace: %v", err)
75+
}
76+
cleanup.Add(func() {
77+
te.Logf("deleting namespace %s...", nsName)
78+
err = te.Client().Namespaces().Delete(ctx, ns.Name, metav1.DeleteOptions{})
79+
if err != nil {
80+
te.Errorf("failed to delete namespace %s: %v", ns.Name, err)
81+
}
82+
})
83+
84+
te.Logf("creating config map %s...", caConfigMapName)
85+
_, err = te.Client().ConfigMaps("openshift-config").Create(ctx, &corev1.ConfigMap{
86+
ObjectMeta: metav1.ObjectMeta{
87+
Name: caConfigMapName,
88+
},
89+
Data: map[string]string{
90+
"ca-bundle.crt": string(framework.EncodeX509Certificate(caCert)),
91+
},
92+
}, metav1.CreateOptions{})
93+
if err != nil {
94+
te.Fatalf("failed to create config map: %s", err)
95+
}
96+
cleanup.Add(func() {
97+
te.Logf("deleting config map %s...", caConfigMapName)
98+
if err := te.Client().ConfigMaps("openshift-config").Delete(ctx, caConfigMapName, metav1.DeleteOptions{}); err != nil {
99+
te.Errorf("failed to delete config map %s: %w", caConfigMapName, err)
100+
}
101+
})
102+
103+
te.Logf("creating Minio certs...")
104+
_, err = te.Client().Secrets(nsName).Create(ctx, &corev1.Secret{
105+
ObjectMeta: metav1.ObjectMeta{
106+
Name: "minio-certs",
107+
},
108+
Data: map[string][]byte{
109+
"public.crt": cert,
110+
"private.key": key,
111+
},
112+
}, metav1.CreateOptions{})
113+
if err != nil {
114+
te.Fatalf("failed to create certs secret: %s", err)
115+
}
116+
117+
te.Logf("creating Minio deployment...")
118+
replicas := int32(1)
119+
runAsNonRoot := true
120+
allowPrivilegeEscalation := false
121+
_, err = te.Client().Deployments(nsName).Create(ctx, &appsv1.Deployment{
122+
ObjectMeta: metav1.ObjectMeta{
123+
Name: "minio",
124+
},
125+
Spec: appsv1.DeploymentSpec{
126+
Replicas: &replicas,
127+
Selector: &metav1.LabelSelector{
128+
MatchLabels: map[string]string{
129+
"app": "minio",
130+
},
131+
},
132+
Template: corev1.PodTemplateSpec{
133+
ObjectMeta: metav1.ObjectMeta{
134+
Labels: map[string]string{
135+
"app": "minio",
136+
},
137+
},
138+
Spec: corev1.PodSpec{
139+
Containers: []corev1.Container{
140+
{
141+
Name: "minio",
142+
Image: "minio/minio:RELEASE.2022-03-26T06-49-28Z",
143+
Args: []string{
144+
"minio",
145+
"--certs-dir=/certs",
146+
"server",
147+
"/data",
148+
},
149+
Ports: []corev1.ContainerPort{
150+
{
151+
ContainerPort: 9000,
152+
},
153+
},
154+
VolumeMounts: []corev1.VolumeMount{
155+
{
156+
Name: "minio-certs",
157+
MountPath: "/certs/public.crt",
158+
SubPath: "public.crt",
159+
},
160+
{
161+
Name: "minio-certs",
162+
MountPath: "/certs/private.key",
163+
SubPath: "private.key",
164+
},
165+
},
166+
Env: []corev1.EnvVar{
167+
{
168+
Name: "MINIO_ROOT_USER",
169+
Value: accessKey,
170+
},
171+
{
172+
Name: "MINIO_ROOT_PASSWORD",
173+
Value: secretKey,
174+
},
175+
},
176+
SecurityContext: &corev1.SecurityContext{
177+
Capabilities: &corev1.Capabilities{
178+
Drop: []corev1.Capability{"ALL"},
179+
},
180+
RunAsNonRoot: &runAsNonRoot,
181+
AllowPrivilegeEscalation: &allowPrivilegeEscalation,
182+
SeccompProfile: &corev1.SeccompProfile{
183+
Type: corev1.SeccompProfileTypeRuntimeDefault,
184+
},
185+
},
186+
},
187+
},
188+
Volumes: []corev1.Volume{
189+
{
190+
Name: "minio-certs",
191+
VolumeSource: corev1.VolumeSource{
192+
Secret: &corev1.SecretVolumeSource{
193+
SecretName: "minio-certs",
194+
},
195+
},
196+
},
197+
},
198+
},
199+
},
200+
},
201+
}, metav1.CreateOptions{})
202+
if err != nil {
203+
te.Fatalf("failed to create deployment: %s", err)
204+
}
205+
206+
_, err = te.Client().Services(nsName).Create(ctx, &corev1.Service{
207+
ObjectMeta: metav1.ObjectMeta{
208+
Name: "minio",
209+
},
210+
Spec: corev1.ServiceSpec{
211+
Ports: []corev1.ServicePort{
212+
{
213+
Port: 443,
214+
TargetPort: intstr.FromInt(9000),
215+
},
216+
},
217+
Selector: map[string]string{
218+
"app": "minio",
219+
},
220+
},
221+
}, metav1.CreateOptions{})
222+
if err != nil {
223+
te.Fatalf("failed to create service: %s", err)
224+
}
225+
226+
return "https://" + hostname, accessKey, secretKey, caConfigMapName, cleanup.Func()
227+
}
228+
229+
func TestS3Minio(t *testing.T) {
230+
ctx := context.Background()
231+
232+
te := framework.Setup(t)
233+
234+
te.Logf("deploying Minio...")
235+
minioEndpoint, accessKey, secretKey, caConfigMapName, cleanup := deployMinio(ctx, te)
236+
defer cleanup()
237+
238+
defer framework.TeardownImageRegistry(te)
239+
240+
_, err := te.Client().Secrets("openshift-image-registry").Create(ctx, &corev1.Secret{
241+
ObjectMeta: metav1.ObjectMeta{
242+
Name: "image-registry-private-configuration-user",
243+
},
244+
Data: map[string][]byte{
245+
"REGISTRY_STORAGE_S3_ACCESSKEY": []byte(accessKey),
246+
"REGISTRY_STORAGE_S3_SECRETKEY": []byte(secretKey),
247+
},
248+
}, metav1.CreateOptions{})
249+
if err != nil {
250+
te.Fatalf("failed to create registry secrets: %s", err)
251+
}
252+
defer func() {
253+
if err := te.Client().Secrets("openshift-image-registry").Delete(ctx, "image-registry-private-configuration-user", metav1.DeleteOptions{}); err != nil {
254+
te.Errorf("failed to delete registry secrets: %s", err)
255+
}
256+
}()
257+
258+
framework.DeployImageRegistry(te, &imageregistryv1.ImageRegistrySpec{
259+
ManagementState: operatorv1.Managed,
260+
Replicas: 1,
261+
Storage: imageregistryv1.ImageRegistryConfigStorage{
262+
S3: &imageregistryv1.ImageRegistryConfigStorageS3{
263+
Region: "us-east-1",
264+
RegionEndpoint: minioEndpoint,
265+
TrustedCA: imageregistryv1.S3TrustedCASource{
266+
Name: caConfigMapName,
267+
},
268+
},
269+
},
270+
})
271+
framework.WaitUntilImageRegistryIsAvailable(te)
272+
}

0 commit comments

Comments
 (0)